Snap for 7478067 from 51de0564c74157b7dffc745e36395e4eaf064afa to mainline-cellbroadcast-release

Change-Id: I266d4183a777a1c1cb2b678018ef244bbf19a609
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..15e1824
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,109 @@
+version: '{build}'
+
+clone_depth: 5
+
+matrix:
+  fast_finish: true
+
+install:
+  - cinst winflexbison
+  - win_flex --version
+  - win_bison --version
+  - appveyor DownloadFile https://www.winpcap.org/install/bin/WpdPack_4_1_2.zip
+  - 7z x .\WpdPack_4_1_2.zip -oc:\projects\libpcap\Win32
+  - appveyor DownloadFile https://nmap.org/npcap/dist/npcap-sdk-1.05.zip
+  - 7z x .\npcap-sdk-1.05.zip -oc:\projects\libpcap\Win32\npcap-sdk-1.05
+  - appveyor DownloadFile https://support.riverbed.com/bin/support/download?sid=l3vk3eu649usgu3rj60uncjqqu -FileName AirPcap_Devpack.zip
+  - 7z x .\AirPcap_Devpack.zip -oc:\projects\libpcap\Win32
+
+environment:
+  matrix:
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "MinGW Makefiles"
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+      MINGW_ROOT: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "MinGW Makefiles"
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+      MINGW_ROOT: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "Visual Studio 14 2015"
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "Visual Studio 14 2015 Win64"
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "Visual Studio 14 2015"
+      SDK: npcap-sdk-1.05
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+      GENERATOR: "Visual Studio 14 2015 Win64"
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      GENERATOR: "Visual Studio 15 2017"
+      SDK: WpdPack
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      GENERATOR: "Visual Studio 15 2017 Win64"
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      GENERATOR: "Visual Studio 15 2017"
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      GENERATOR: "Visual Studio 15 2017 Win64"
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      GENERATOR: "Visual Studio 15 2017 Win64"
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=NO
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      GENERATOR: "Visual Studio 16 2019"
+      PLATFORM: Win32
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      GENERATOR: "Visual Studio 16 2019"
+      PLATFORM: x64
+      SDK: WpdPack
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      GENERATOR: "Visual Studio 16 2019"
+      PLATFORM: Win32
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      GENERATOR: "Visual Studio 16 2019"
+      PLATFORM: x64
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=YES
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      GENERATOR: "Visual Studio 16 2019"
+      PLATFORM: x64
+      SDK: npcap-sdk-1.05
+      AIRPCAP: -DDISABLE_AIRPCAP=NO
+
+build_script:
+  #
+  # Appveyor defaults to cmd.exe, so use cmd.exe syntax.
+  #
+  - type NUL >.devel
+  - md build
+  - cd build
+  # Remove the default MinGW path
+  - if "%GENERATOR%"=="MinGW Makefiles" set PATH=%PATH:C:\MinGW\bin;=%
+  # Add the specified MinGW path
+  - if "%GENERATOR%"=="MinGW Makefiles" set PATH=%MINGW_ROOT%\mingw64\bin;%PATH%
+  # Remove the path to Git, so that we don't pick up its sh.exe, as
+  # that breaks MinGW builds - CMake checks for that and fails in the
+  # configuration stage
+  - if "%GENERATOR%"=="MinGW Makefiles" set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
+  - if NOT DEFINED PLATFORM  cmake %AIRPCAP% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DAirPcap_ROOT=c:\projects\libpcap\Win32\Airpcap_Devpack -G"%GENERATOR%" ..
+  - if DEFINED PLATFORM cmake %AIRPCAP% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -DPacket_ROOT=c:\projects\libpcap\Win32\%SDK% -G"%GENERATOR%" -DAirPcap_ROOT=c:\projects\libpcap\Win32\Airpcap_Devpack -G"%GENERATOR%" -A %PLATFORM% ..
+  - if NOT "%GENERATOR%"=="MinGW Makefiles" msbuild /m /nologo /p:Configuration=Release pcap.sln
+  - if "%GENERATOR%"=="MinGW Makefiles" mingw32-make
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 0000000..0f71d89
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,25 @@
+# The internal git client reads CIRRUS_CLONE_DEPTH.
+env:
+  CIRRUS_CLONE_DEPTH: 3
+  MAXJOBS: 2
+  IGNORE_OSVERSION: yes
+
+task:
+  freebsd_instance:
+    image_family: $IMAGE_FAMILY
+  env:
+    matrix:
+      - IMAGE_FAMILY: freebsd-11-4
+      - IMAGE_FAMILY: freebsd-12-2
+      - IMAGE_FAMILY: freebsd-13-0-snap
+  script:
+    - freebsd-version
+    - pkg install -qy autoconf
+    - touch .devel
+    - ./configure --enable-remote --prefix=/tmp
+    - make -s all
+    - make -s testprogs
+    - make install
+    - make releasetar
+    - testprogs/findalldevstest
+
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..a7ff19e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# things that only make sense on github.com
+.github export-ignore
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..b654739
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,28 @@
+Assar Westerlund <assar@sics.se> assar <assar>
+Bill Fenner <fenner@gmail.com> fenner <fenner>
+Denis Ovsienko <denis@ovsienko.info> <infrastation@yandex.ru>
+Francois-Xavier Le Bail <devel.fx.lebail@orange.fr> fxlb <fx.lebail@yahoo.com>
+Francois-Xavier Le Bail <devel.fx.lebail@orange.fr> <fx.lebail@yahoo.com>
+Fulvio Risso <risso@polito.it> risso <risso>
+Gianluca Varenni <gianluca.varenni@gmail.com> gianluca <gianluca>
+Guy Harris <gharris@sonic.net> <gharris@localhost.localdomain>
+Guy Harris <gharris@sonic.net> <gharris@steve.local>
+Guy Harris <gharris@sonic.net> <gharris@ubu9-10.(none)>
+Guy Harris <gharris@sonic.net> <guy@alum.mit.edu>
+Guy Harris <gharris@sonic.net> Guy (Core OS) Harris <gharris@gharris.apple.com>
+Guy Harris <gharris@sonic.net> guy <guy>
+Hannes Gredler <hannes@gredler.at> hannes <hannes>
+Hannes Gredler <hannes@gredler.at> <hannes@juniper.net>
+Jun-ichiro itojun Hagino <itojun@iijlab.net> itojun <itojun>
+Ken Hornstein <kenh@cmf.nrl.navy.mil> kenh <kenh>
+Loris Degioanni <loris@netgroup-serv.polito.it> loris <loris>
+Michael Richardson <mcr@sandelman.ca> <mcr@credil.org>
+Michael Richardson <mcr@sandelman.ca> <mcr@finepoint.com>
+Michael Richardson <mcr@sandelman.ca> mcr <mcr>
+Michael Richardson <mcr@sandelman.ca> <mcr@sandelman.ottawa.on.ca>
+Michael Richardson <mcr@sandelman.ca> <mcr@tcpdump.org>
+Stephen Donnelly <stephen.donnelly@emulex.com> <sfd@nzhmlwks0033.(none)>
+Stephen Donnelly <stephen.donnelly@emulex.com> sfd <stephen.donnelly@emulex.com>
+Stephen Donnelly <stephen.donnelly@emulex.com> sfd <stephen.donnelly@endace.com>
+Stephen Donnelly <stephen.donnelly@emulex.com> <stephen.donnelly@endace.com>
+Torsten Landschoff <t.landschoff@gmx.net> torsten <torsten>
diff --git a/.travis-coverity-scan-build.sh b/.travis-coverity-scan-build.sh
new file mode 100644
index 0000000..892dac1
--- /dev/null
+++ b/.travis-coverity-scan-build.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+set -e
+
+# Environment check
+echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m"
+[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1
+#[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1
+[ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1
+[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1
+[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1
+
+PLATFORM=`uname`
+TOOL_ARCHIVE=/tmp/cov-analysis-${PLATFORM}.tgz
+TOOL_URL=https://scan.coverity.com/download/cxx/${PLATFORM}
+TOOL_BASE=/tmp/coverity-scan-analysis
+UPLOAD_URL="https://scan.coverity.com/builds"
+SCAN_URL="https://scan.coverity.com"
+
+# Verify Coverity Scan run condition
+COVERITY_SCAN_RUN_CONDITION=${coverity_scan_run_condition:-true}
+echo -ne "\033[33;1mTesting '${COVERITY_SCAN_RUN_CONDITION}' condition... "
+if eval [ $COVERITY_SCAN_RUN_CONDITION ]; then
+  echo -e "True.\033[0m"
+else
+  echo -e "False. Exit.\033[0m"
+  exit 0
+fi
+
+# Do not run on pull requests
+if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then
+  echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m"
+  exit 0
+fi
+
+# Verify this branch should run
+IS_COVERITY_SCAN_BRANCH=`ruby -e "puts '${TRAVIS_BRANCH}' =~ /\\A$COVERITY_SCAN_BRANCH_PATTERN\\z/ ? 1 : 0"`
+if [ "$IS_COVERITY_SCAN_BRANCH" = "1" ]; then
+  echo -e "\033[33;1mCoverity Scan configured to run on branch ${TRAVIS_BRANCH}\033[0m"
+else
+  echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${TRAVIS_BRANCH}\033[0m"
+  exit 1
+fi
+
+# Verify upload is permitted
+AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted`
+if [ "$AUTH_RES" = "Access denied" ]; then
+  echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m"
+  exit 1
+else
+  AUTH=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']"`
+  if [ "$AUTH" = "true" ]; then
+    echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m"
+  else
+    WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"`
+    echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m"
+    exit 0
+  fi
+fi
+
+if [ ! -d $TOOL_BASE ]; then
+  # Download Coverity Scan Analysis Tool
+  if [ ! -e $TOOL_ARCHIVE ]; then
+    echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m"
+    wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN"
+  fi
+
+  # Extract Coverity Scan Analysis Tool
+  echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m"
+  mkdir -p $TOOL_BASE
+  pushd $TOOL_BASE
+  tar xzf $TOOL_ARCHIVE
+  popd
+fi
+
+TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'`
+export PATH=$TOOL_DIR/bin:$PATH
+
+# Build
+echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m"
+COV_BUILD_OPTIONS=""
+#COV_BUILD_OPTIONS="--return-emit-failures 8 --parse-error-threshold 85"
+RESULTS_DIR="cov-int"
+eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}"
+COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND
+cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1
+
+# Upload results
+echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m"
+RESULTS_ARCHIVE=analysis-results.tgz
+tar czf $RESULTS_ARCHIVE $RESULTS_DIR
+SHA=`git rev-parse --short HEAD`
+VERSION_SHA=$(cat VERSION)#$SHA
+
+# Verify Coverity Scan script test mode
+if [ "$coverity_scan_script_test_mode" = true ]; then
+  echo -e "\033[33;1mCoverity Scan configured in script test mode. Exit.\033[0m"
+  exit 0
+fi
+
+echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m"
+response=$(curl \
+  --silent --write-out "\n%{http_code}\n" \
+  --form project=$COVERITY_SCAN_PROJECT_NAME \
+  --form token=$COVERITY_SCAN_TOKEN \
+  --form email=blackhole@blackhole.io \
+  --form file=@$RESULTS_ARCHIVE \
+  --form version=$SHA \
+  --form description="$VERSION_SHA" \
+  $UPLOAD_URL)
+status_code=$(echo "$response" | sed -n '$p')
+if [ "$status_code" != "201" ]; then
+  TEXT=$(echo "$response" | sed '$d')
+  echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m"
+  exit 1
+fi
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b840a66
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,135 @@
+language: c
+
+#
+# Try building on these 4 architectures; all are 64-bit, and all but
+# "s390x", a/k/a z/Architecture, are little-endian.
+#
+arch:
+  - amd64
+  - ppc64le
+  - s390x
+  - arm64
+
+os:
+  - linux
+  - osx
+
+dist: bionic
+
+compiler:
+  - gcc
+  - clang
+
+#
+# Linux runs on all of the architectures listed above; macOS currently
+# runs only on 64-bit x86, although the Spaceshipologists are all in a
+# tizzy about the possibility of Arm-based Macs.  Suppress the macOS
+# builds that don't work.
+#
+# In addition, with newer versions of macOS, Apple ships a "gcc" that's
+# just another front end to Clang, presumably for backwards
+# compatibility with build scripts etc. that expect the compiler to be
+# "gcc", so don't bother doing "gcc" builds on macOS.
+#
+jobs:
+  exclude:
+  - arch: ppc64le
+    os: osx
+  - arch: s390x
+    os: osx
+  - arch: arm64
+    os: osx
+  - compiler: gcc
+    os: osx
+
+cache: ccache
+
+env:
+  global:
+    # encrypted COVERITY_SCAN_TOKEN from
+    # https://scan.coverity.com/projects/<project_id>/submit_build?tab=travis_ci
+    - secure: "SwNcek+I4lMVcnb5EGGmNm6ljWN6C/mnXzBr82a5rEQNKxAoJfdvvPpKIp0iEfg5j0PtYlcRHoIDyVZ/6QM/WEw0wrio9Z0cio9hkOS6kV8g2QouXfnoNtKJ5nNso7UD2GPJ9+M0GIR1GZ0Edvxr81sHlNAkpVKydYGBwCIMGyg="
+    # Coverity run condition (avoid matrix multiple runs), need customized
+    # build script. Need an update if new matrix cases.
+    - coverity_scan_run_condition='"$TRAVIS_CPU_ARCH" = amd64 -a "$TRAVIS_OS_NAME" = linux -a "$CC" = gcc -a "$REMOTE" = enable -a "$CMAKE" = no'
+    # Coverity script test mode (if true no uploading, avoid reaching the quota)
+    # usual processing: false.
+    - coverity_scan_script_test_mode=false
+    - MAKEFLAGS='-j 2' # Travis CI VMs come with 2 cores
+  matrix:
+    - REMOTE=disable CMAKE=no
+    - ENABLE_REMOTE="" CMAKE=yes
+    - REMOTE=enable CMAKE=no
+    - ENABLE_REMOTE="-DENABLE_REMOTE=ON" CMAKE=yes
+
+matrix:
+  fast_finish: true
+
+addons:
+  coverity_scan:
+    # customized build script URL
+    # TRAVIS_REPO_SLUG: owner_name/repo_name of repository currently being built
+    # TRAVIS_BRANCH: name of the branch currently being built
+    build_script_url: https://raw.githubusercontent.com/$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/.travis-coverity-scan-build.sh
+    # project metadata
+    project:
+      name: $TRAVIS_REPO_SLUG
+    # Where email notification of build analysis results will be sent
+    #notification_email: tcpdump-workers@lists.tcpdump.org
+    # Commands to prepare for build_command
+    build_command_prepend: ./configure --enable-remote
+    # This command will be added as an argument to "cov-build" to compile
+    # the project for analysis
+    build_command: make
+    # Pattern to match selecting branches that will run analysis
+    branch_pattern: coverity_scan
+  apt:
+    packages:
+      - libdbus-1-dev
+      - libbluetooth-dev
+      - libnl-genl-3-dev
+      - libibverbs-dev
+
+git:
+  quiet: true
+  depth: 3
+
+before_install:
+  - uname -a
+  - date
+  - if [ "$TRAVIS_OS_NAME" = linux ]; then apt list --installed 'lib*-dev'; fi
+
+install:
+
+before_script:
+
+script:
+  - if [ "$COVERITY_SCAN_BRANCH" = 1 ]; then echo "Coverity build - nothing more to do"; exit 0; fi
+  - touch .devel configure
+  - if [ "$CMAKE" = no ]; then echo '$ ./configure [...]' && echo travis_fold:start:script.configure; fi
+  - if [ "$CMAKE" = no ]; then ./configure --prefix=/tmp "--${REMOTE}-remote"; fi
+  - if [ "$CMAKE" = no ]; then echo -n travis_fold:end:script.configure; fi
+  - if [ "$CMAKE" = yes ]; then mkdir build; fi
+  - if [ "$CMAKE" = yes ]; then cd build; fi
+  - if [ "$CMAKE" = yes ]; then echo travis_fold:start:script.cmake; fi
+  - if [ "$CMAKE" = yes ]; then cmake -DCMAKE_INSTALL_PREFIX=/tmp $ENABLE_REMOTE ..; fi
+  - if [ "$CMAKE" = yes ]; then echo -n travis_fold:end:script.cmake; fi
+  - make -s
+  - make -s testprogs
+  - echo '$ make install [...]' && echo travis_fold:start:script.make_install
+  - PATH=$PATH make install
+  - echo -n travis_fold:end:script.make_install
+  - if [ "$CMAKE" = no ]; then testprogs/findalldevstest; fi
+  - if [ "$CMAKE" = yes ]; then run/findalldevstest; fi
+  - if [ "$CMAKE" = no ]; then make releasetar; fi
+  - echo '$ cat Makefile [...]'; echo travis_fold:start:script.cat_makefile
+  - if [ "$CMAKE" = no ]; then cat Makefile | sed -n '1,/DO NOT DELETE THIS LINE -- mkdep uses it/p'; fi
+  - if [ "$CMAKE" = yes ]; then cat Makefile; fi
+  - echo -n travis_fold:end:script.cat_makefile
+  - echo '$ cat config.h'; echo travis_fold:start:script.cat_config_h
+  - cat config.h
+  - echo -n travis_fold:end:script.cat_config_h
+  - if [ "$CMAKE" = no ]; then echo '$ cat config.log'; echo travis_fold:start:script.cat_config_log; fi
+  - if [ "$CMAKE" = no ]; then cat config.log; fi
+  - if [ "$CMAKE" = no ]; then echo -n travis_fold:end:script.cat_config_log; fi
+  - if [ "$TRAVIS_OS_NAME" = osx ]; then sleep 10; fi
diff --git a/Android.bp b/Android.bp
index eb0ea10..e3a7a1b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,16 +1,21 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+package {
+    default_applicable_licenses: ["external_libpcap_license"],
+}
+
+license {
+    name: "external_libpcap_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-ISC",
+        "SPDX-license-identifier-MIT",
+    ],
+    license_text: [
+        "LICENSE",
+        "NOTICE",
+    ],
+}
 
 cc_defaults {
     name: "libpcap_defaults",
@@ -65,6 +70,11 @@
     ],
 
     target: {
+        linux: {
+            srcs: [
+                "missing/strlcpy.c",
+            ],
+        },
         darwin: {
             enabled: false,
         },
diff --git a/CHANGES b/CHANGES
index 4607f14..4dd30f1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,183 @@
+Tuesday, December 29, 2020
+  Summary for 1.10.0 libpcap release
+    Require, and assume, some level of C99 support in the C compiler
+    Require Visual Studio 2015 or later if using Visual Studio
+    Add support for capturing on DPDK devices
+    rpcap: support rpcap-over-TLS
+    Windows: report the system error for PacketSetHwFilter() failures
+    Label most APIs by the first release in which they're available
+    Add support for getting and setting packet time stamp types
+        with Npcap
+    Add pcap_init(), and add support for UTF-8 strings, including error
+        messages, on Windows
+    Improve man pages, including adding backward compatibility notes
+    Fix configure script issues, including with libnl on Linux
+    Fix CMake issues
+    Squelch complaints from Bison about "%define api.pure" being
+        deprecated
+    Fix some memory leaks, including in pcap_compile()
+    Linux: handle systems without AF_INET or AF_UNIX socket support
+    Catch invalid IPv4 addresses in filters
+    AIX: fix loading of BPF kernel extension
+    rpcapd: fix core dumps with invalid configuration file
+    Show special Linux BPF offsets symbolically in bpf_image() and
+        bpf_dump()
+    Add some overflow checks in the optimizer
+    Add pcap_datalink_val_to_description_or_dlt()
+    Windows: make the snapshot length work even if pcap_setfilter()
+        isn't called
+    Linux: get rid of Wireless Extensions for turning monitor mode on
+    Handle the pcap private data in a fashion that makes fewer
+       assumptions about memory layouts (might fix GitHub issue #940
+       on ARM)
+    Fix "unknown ether proto 'aarp'"
+    Fix some issues found by cppcheck.
+    Linux: proper memory sync for PACKET_MMAP (may prevent GitHub issue
+        #898)
+    Remove undocumented and rather old "ether proto" protocols
+    Fix some thread safety issues
+    Windows: add pcap_handle(), and deprecate pcap_fileno()
+    AirPcap: add AirPcap support in a module, rather than using
+        WinPcap/Npcap's support for it
+    Linux: drop support for libnl 1 and 2.
+    Linux: Require PF_PACKET support, and kernel 2.6.27 or later
+    Add DLT_LINUX_SLL2
+    Add a new filter "ifindex" for DLT_LINUX_SLL2 files and live
+        Linux captures
+    optimizer: add a hack to try to catch certain optimizer loops
+        (should prevent GitHub issue #112)
+    Probe CONFIGURATION descriptor of connected USB devices
+    macOS: cope with getting EPWROFF from SIOCGIFMEDIA
+    Linux: return error on interface going away, but not if it just went
+        down
+    Windows: fix compilation on Cygwin/MSYS
+    Linux: set socket protocol only after packet ring configured,
+        reducing bogus packet drop reports
+    pcap_findalldevs(): don't sort interfaces by unit number
+    Linux: get ifdrop stats from sysfs.
+    Fix various security issues reported by Charles Smith at Tangible
+        Security
+    Fix various security issues reported by Include Security
+    rpcapd: on UN*X, don't tell the client why authentication failed
+    Linux: when adjusting BPF programs, do not subtract the
+        SLL[2]_HDR_LEN if the location is negative (special metadata
+        offset)
+    Preserve references to metadata when adjusting the program;
+        see https://github.com/the-tcpdump-group/tcpdump/issues/480#issuecomment-486827278
+    Always return a list of supported time-stamp types, even if only
+        host time stamps are supported
+    Linux: with a timeout of zero, wait indefinitely
+    Linux: clean up support for some non-GNU libc C libraries
+    Increase the maximum snaplen for LINKTYPE_USBPCAP/DLT_USBPCAP
+    Fix handling of some ioctls that fail with "permission denied" even
+        when the ioctl isn't supported at all
+    Added support for ICMPv6 types 1-4 as tokens in filters
+    Windows: Report PCAP_ERROR_NO_SUCH_DEVICE for a non-existent device
+    Windows: return an appropriate error message for device removed or
+        device unusable due to a suspend/resume
+    BPF: treat both ENXIO (everybody but OpenBSD) and EIO (OpenBSD) as
+        meaning "the interface was removed"
+    BPF: report "the interface disappeared", not "the interface went
+        down", if the interface was removed during a capture
+    Linux, Windows: report a warning for unknown link-layer header types
+    Create the file in pcap_dump_open_append() if it doesn't exist
+    Linux, NPF: have pcap_breakloop() forcibly break out of a sleeping
+        capture loop
+    Report the DLT description in error messages
+    Linux: Add support for DSA data link types
+    Linux USB: use the snapshot length to set the buffer size, and set
+        the len field to reflect the length in the URB (GitHub issue
+        #808)
+    rpcapd: allow rpcapd to rebind more rapidly (GitHub issue #765)
+    Windows: clean up building DLL
+    Fix compilation of pcap-tc.c
+    Add Haiku pcap implementation
+    Windows: handle CRT mismatch for pcap_dump_fopen()
+    Windows: map NdisMediumWirelessWan to DLT_RAW
+    rpcap: add some new authentication libpcap error codes for
+        specific errors
+    rpcap: redo protocol version negotiation to avoid problems with old
+        servers (it still works with servers using the old negotiation,
+        as well as servers not supporting negotiation)
+    rpcap: error handling cleanups
+    rpcapd: fix some inetd issues
+    Don't assume ARM supports unaligned accesses
+    Remove (unused) SITA support here.
+    Correctly handle pcapng captures with more than one IDB with a
+        snspshot length greater than the supported maximum
+
+Sunday, July 22, 2018
+  Summary for 1.9.1 libpcap release
+    Mention pcap_get_required_select_timeout() in the main pcap man page
+    Fix pcap-usb-linux.c build on systems with musl
+    Fix assorted man page and other documentation issues
+    Plug assorted memory leaks
+    Documentation changes to use https:
+    Changes to how time stamp calculations are done
+    Lots of tweaks to make newer compilers happier and warning-free and
+        to fix instances of C undefined behavior
+    Warn if AC_PROG_CC_C99 can't enable C99 support
+    Rename pcap_set_protocol() to  pcap_set_protocol_linux().
+    Align pcap_t private data on an 8-byte boundary.
+    Fix various error messages
+    Use 64-bit clean API in dag_findalldevs()
+    Fix cleaning up after some errors
+    Work around some ethtool ioctl bugs in newer Linux kernels (GitHub
+        issue #689)
+    Add backwards compatibility sections to some man pages (GitHub issue
+        #745)
+    Fix autotool configuration on AIX and macOS
+    Don't export bpf_filter_with_aux_data() or struct bpf_aux_data;
+        they're internal-only and subject to change
+    Fix pcapng block size checking
+    On macOS, don't build rpcapd or test programs any fatter than they
+        need to be
+    Fix reading of capture statistics for Linux USB
+    Fix packet size values for Linux USB packets (GitHub issue #808)
+    Check only VID in VLAN test in filterss (GitHub issue #461)
+    Fix pcap_list_datalinks on 802.11 devices on macOS
+    Fix overflows with very large snapshot length in pcap file
+    Improve parsing of rpcapd configuration file (GitHub issue #767)
+    Handle systems without strlcpy() or strlcat() better
+    Fix crashes and other errors with invalid filter expressions
+    Fix use of uninitialized file descriptor in remote capture
+    Fix some CMake issues
+    Fix some divide-by-zero issues with the filter compiler
+    Work around a GNU libc bug in pcap_nametonetaddr()
+    Add support for DLT_LINUX_SLL2
+    Fix handling of the packet-count argument for Myricom SNF devices
+    Fix --disable-rdma in configure script (GitHub issue #782)
+    Fix compilation of TurboCap support (GitHub issue #764)
+    Constify first argument to pcap_findalldevs_ex()
+    Fix a number of issues when running rpcapd as an inetd-style daemon
+    Fix CMake issues with D-Bus libraries
+    In rpcapd, clean up termination of a capture session
+    Redo remote capture protocol negotiation
+    In rpcapd, report the same error for "invalid user name" and
+        "invalid password", to make brute-forcing harder
+    For remote captures, add an error code for "the server requires TLS"
+    Fix pcap_dump_fopen() on Windows to avoid clashes between
+        {Win,N}Pcap and application C runtimes
+    Fix exporting of functions from Windows DLLs (GitHub issue #810)
+    Fix building as part of Npcap
+    Allow rpcapd to rebind more rapidly
+    Fix building shared libpcap library on midipix (midipix.org)
+    Fix hack to detect UTF-16LE adapter names on Windows not to go past
+        the end of the string
+    Fix handling of "wireless WAN" (mobile phone network modems) on
+        Windows with WinPcap/Npcap (GitHub issue #824)
+    Have pcap_dump_open_append() create the dump file if it doesn't
+        exists (GitHub issue #247)
+    Fix the maxmum snapshot length for DLT_USBPCAP
+    Use -fPIC when building for 64-bit SPARC on Linux (GitHub issue #837)
+    Fix CMake 64-bit library installation directory on some Linux
+        distributions
+    Boost the TPACKET_V3 timeout to the maximum if a timeout of 0 was
+        specified
+    Five CVE-2019-15161, CVE-2019-15162, CVE-2019-15163, CVE-2019-15164, CVE-2019-15165
+    Fixes for CVE-2018-16301, errors in pcapng reading.
+    PCAPNG reader applies some sanity checks before doing malloc().
+
 Sunday, June 24, 2018, by mcr@sandelman.ca
   Summary for 1.9.0 libpcap release
     Added testing system to libpcap, independent of tcpdump
@@ -21,7 +201,7 @@
     Make VLAN filter handle both metadata and inline tags
     D-Bus captures can now be up to 128MB in size
     Added LORATAP DLT value
-    Added DLT_VSOCK for http://qemu-project.org/Features/VirtioVsock
+    Added DLT_VSOCK for https://qemu-project.org/Features/VirtioVsock
     probe_devices() fixes not to overrun buffer for name of device
     Add linux-specific pcap_set_protocol_linux() to allow specifying a specific capture protocol.
     RDMA sniffing support for pcap
@@ -203,7 +383,7 @@
 	    than the mcr repository
 	Checks added for malloc()/realloc()/etc. failures
 	Fixed build on Solaris 11
-	Support filtering filtering E1 SS7 traffic on MTP2 layer Annex A
+	Support filtering E1 SS7 traffic on MTP2 layer Annex A
 	Use "ln -s" to link man pages by default
         Add support for getting nanosecond-resolution time stamps when
 	    capturing and reading capture files
@@ -264,7 +444,7 @@
 Friday  December 9, 2011.  guy@alum.mit.edu.
 Summary for 1.2.1 libpcap release
 	Update README file.
-	Fix typoes in README.linux file.
+	Fix typos in README.linux file.
 	Clean up some compiler warnings.
 	Fix Linux compile problems and tests for ethtool.h.
 	Treat Debian/kFreeBSD and GNU/Hurd as systems with GNU
@@ -297,7 +477,7 @@
         Noted real nature of LINKTYPE_ARCNET.
         Add a link-layer type for DVB-CI.
         Fix configure-script discovery of VLAN acceleration support.
-         see http://netoptimizer.blogspot.com/2010/09/tcpdump-vs-vlan-tags.html
+         see https://netoptimizer.blogspot.com/2010/09/tcpdump-vs-vlan-tags.html
         Linux, HP-UX, AIX, NetBSD and OpenBSD compilation/conflict fixes.
         Protect against including AIX 5.x's <net/bpf.h> having been included.
         Add DLT_DBUS, for raw D-Bus messages.
@@ -496,7 +676,7 @@
 	 beginning+link-layer
 	Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay
 	Fix allocation of buffer for list of link-layer types
-	Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages
+	Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communication Messages
 	Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_
 	Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN).
 	Added definition for DLT_A429 and LINKTYPE_A429 as #184.
@@ -610,7 +790,7 @@
 
 	Header files fixed to allow use in C++ programs.
 
-	Removed dependancy on native headers for packet layout.
+	Removed dependency on native headers for packet layout.
 	Removed Linux specific headers that were shipped.
 
 	Security fixes: Strcpy replaced with strlcpy, sprintf replaced
@@ -748,7 +928,7 @@
 
 v0.2.1 Sun Jul 14 03:02:26 PDT 1996
 
-- Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram
+- Fixes for HP-UX 10. Thanks in part to Thomas Wolfram
   (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com)
 
 - Added support for SINIX. Thanks to Andrej Borsenkow
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 905ba61..50bf171 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,11 @@
-cmake_minimum_required(VERSION 2.8.6)
+if(WIN32)
+    #
+    # We need 3.12 or later, so that we can set policy CMP0074; see
+    # below.
+    cmake_minimum_required(VERSION 3.12)
+else(WIN32)
+    cmake_minimum_required(VERSION 2.8.6)
+endif(WIN32)
 
 #
 # Apple doesn't build with an install_name starting with @rpath, and
@@ -9,44 +16,34 @@
     cmake_policy(SET CMP0042 OLD)
 endif()
 
-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
+#
+# Squelch noise about quoted strings in if() statements.
+# WE KNOW WHAT WE'RE DOING, WE'RE DOING EVERYTHING THE WAY THAT NEWER
+# VERSIONS OF CMAKE EXPECT BY DEFAULT, DON'T WASTE OUR TIME WITH NOISE.
+#
+if(POLICY CMP0054)
+    cmake_policy(SET CMP0054 NEW)
+endif()
+
+#
+# We want find_file() and find_library() to honor {packagename}_ROOT,
+# as that appears to be the only way, with the Visual Studio 2019 IDE
+# and its CMake support, to tell CMake where to look for the Npcap
+# or WinPcap SDK.
+#
+if(POLICY CMP0074)
+    cmake_policy(SET CMP0074 NEW)
+endif()
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
 
 project(pcap)
 
-#
-# Try to enable as many C99 features as we can.
-# At minimum, we want C++/C99-style // comments.
-#
-# Newer versions of compilers might default to supporting C99, but older
-# versions may require a special flag.
-#
-# Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
-# so, unless and until we require CMake 3.1 or later, we have to do it
-# ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
-# of CMake.
-#
-# Note: with CMake 3.1 through 3.5, the only compilers for which CMake
-# handles CMAKE_C_STANDARD are GCC and Clang.  3.6 adds support only
-# for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
-# 3.10 adds support for Cray C and IAR C, but no version of CMake has
-# support for HP C.  Therefore, even if we use CMAKE_C_STANDARD with
-# compilers for which CMake supports it, we may still have to do it
-# ourselves on other compilers.
-#
-# See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
-# for a list of compiler IDs.
-#
-# We don't worry about MSVC; it doesn't have such a flag - either it
-# doesn't support the C99 features we need at all, or it supports them
-# regardless of the compiler flag.
-#
-# XXX - this just tests whether the option works and adds it if it does.
-# We don't test whether it's necessary in order to get the C99 features
-# that we use; if we ever have a user who tries to compile with a compiler
-# that can't be made to support those features, we can add a test to make
-# sure we actually *have* C99 support.
-#
 include(CheckCCompilerFlag)
+
+#
+# For checking if a compiler flag works and adding it if it does.
+#
 macro(check_and_add_compiler_option _option)
     message(STATUS "Checking C compiler flag ${_option}")
     string(REPLACE "=" "-" _temp_option_variable ${_option})
@@ -57,23 +54,103 @@
     endif()
 endmacro()
 
+#
+# If we're building with Visual Studio, we require Visual Studio 2015,
+# in order to get sufficient C99 compatibility.  Check for that.
+#
+# If not, try the appropriate flag for the compiler to enable C99
+# features.
+#
 set(C_ADDITIONAL_FLAGS "")
-if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
-   CMAKE_C_COMPILER_ID MATCHES "Clang")
-    check_and_add_compiler_option("-std=gnu99")
-elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
+if(MSVC)
+    if(MSVC_VERSION LESS 1900)
+        message(FATAL_ERROR "Visual Studio 2015 or later is required")
+    endif()
+
     #
-    # We want support for extensions picked up for GNU C compatibility,
-    # so we use -qlanglvl=extc99.
+    # Treat source files as being in UTF-8 with MSVC if it's not using
+    # the Clang front end.
+    # We assume that UTF-8 source is OK with other compilers and with
+    # MSVC if it's using the Clang front end.
     #
-    check_and_add_compiler_option("-qlanglvl=extc99")
-elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
-    check_and_add_compiler_option("-AC99")
-elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
-    check_and_add_compiler_option("-xc99")
-elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
-    check_and_add_compiler_option("-c99")
-endif()
+    if(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+        set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} /utf-8")
+    endif(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+else(MSVC)
+    #
+    # For checking if a compiler flag works, failing if it doesn't,
+    # and adding it otherwise.
+    #
+    macro(require_and_add_compiler_option _option)
+        message(STATUS "Checking C compiler flag ${_option}")
+        string(REPLACE "=" "-" _temp_option_variable ${_option})
+        string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
+        check_c_compiler_flag("${_option}" ${_option_variable})
+        if(${${_option_variable}})
+            set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
+        else()
+            message(FATAL_ERROR "C99 support is required, but the compiler doesn't support a compiler flag to enable it")
+        endif()
+    endmacro()
+
+    #
+    # Try to enable as many C99 features as we can.
+    # At minimum, we want C++/C99-style // comments.
+    #
+    # Newer versions of compilers might default to supporting C99, but
+    # older versions may require a special flag.
+    #
+    # Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
+    # so, unless and until we require CMake 3.1 or later, we have to do it
+    # ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
+    # of CMake.
+    #
+    # Note: with CMake 3.1 through 3.5, the only compilers for which CMake
+    # handles CMAKE_C_STANDARD are GCC and Clang.  3.6 adds support only
+    # for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
+    # 3.10 adds support for Cray C and IAR C, but no version of CMake has
+    # support for HP C.  Therefore, even if we use CMAKE_C_STANDARD with
+    # compilers for which CMake supports it, we may still have to do it
+    # ourselves on other compilers.
+    #
+    # See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
+    # for a list of compiler IDs.
+    #
+    # XXX - this just tests whether the option works, fails if it doesn't,
+    # and adds it if it does.  We don't test whether it's necessary in order
+    # to get the C99 features that we use, or whether, if it's used, it
+    # enables all the features that we require.
+    #
+    if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
+       CMAKE_C_COMPILER_ID MATCHES "Clang")
+        require_and_add_compiler_option("-std=gnu99")
+    elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
+        #
+        # We want support for extensions picked up for GNU C compatibility,
+        # so we use -qlanglvl=extc99.
+        #
+        require_and_add_compiler_option("-qlanglvl=extc99")
+    elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
+        require_and_add_compiler_option("-AC99")
+    elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
+        require_and_add_compiler_option("-xc99")
+    elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
+        require_and_add_compiler_option("-c99")
+    endif()
+endif(MSVC)
+
+#
+# If we're building with MinGW, we need to specify _WIN32_WINNT as
+# 0x0600 ("NT 6.0", a/k/a Vista/Windows Server 2008) in order to
+# get the full IPv6 API, including inet_ntop().
+#
+# NOTE: pcap does *NOT* work with msvcrt.dll; it must link with
+# a newer version of the C library, i.e. Visual Studio 2015 or
+# later, as it depends on C99 features introduced in VS 2015.
+#
+if(MINGW)
+    add_definitions(-D_WIN32_WINNT=0x0600)
+endif(MINGW)
 
 #
 # Build all runtimes in the top-level binary directory; that way,
@@ -107,9 +184,12 @@
 endif(WIN32)
 option(BUILD_SHARED_LIBS "Build shared libraries" ON)
 if(WIN32)
-    set(PACKET_DLL_DIR "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
+    set(Packet_ROOT "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
+    set(AirPcap_ROOT "" CACHE PATH "Path to directory with include and lib subdirectories for airpcap.dll")
 endif(WIN32)
 
+option(ENABLE_PROFILING "Enable code profiling" OFF)
+
 # To pacify those who hate the protochain instruction
 option(NO_PROTOCHAIN "Disable protochain instruction" OFF)
 
@@ -131,93 +211,19 @@
 endif(WIN32)
 
 if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-    option(PCAP_SUPPORT_PACKET_RING "Enable Linux packet ring support" ON)
     option(BUILD_WITH_LIBNL "Build with libnl" ON)
 endif()
 
 #
-# By default, build universal with the appropriate set of architectures
-# for the OS on which we're doing the build.
-#
-if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
-    #
-    # Get the major version of Darwin.
-    #
-    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
-
-    if(SYSTEM_VERSION_MAJOR LESS 8)
-        #
-        # Pre-Tiger.  Build only for 32-bit PowerPC.
-        #
-        set(CMAKE_OSX_ARCHITECTURES "ppc")
-    elseif(SYSTEM_VERSION_MAJOR EQUAL 8)
-        #
-        # Tiger.  Is this prior to, or with, Intel support?
-        #
-        # Get the minor version of Darwin.
-        #
-        string(REPLACE "${SYSTEM_VERSION_MAJOR}." "" SYSTEM_MINOR_AND_PATCH_VERSION ${CMAKE_SYSTEM_VERSION})
-        string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MINOR "${SYSTEM_MINOR_AND_PATCH_VERSION}")
-        if(SYSTEM_VERSION_MINOR LESS 4)
-            #
-            # Prior to Intel support.  Build for 32-bit
-            # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
-            # first.  (I'm guessing that's what Apple does.)
-            #
-            set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64")
-        elseif(SYSTEM_VERSION_MINOR LESS 7)
-            #
-            # With Intel support but prior to x86-64 support.
-            # Build for 32-bit PowerPC, 64-bit PowerPC, and x86,
-            # with 32-bit PowerPC first.
-            # (I'm guessing that's what Apple does.)
-            #
-            set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386")
-        else()
-            #
-            # With Intel support including x86-64 support.
-            # Build for 32-bit PowerPC, 64-bit PowerPC, x86,
-            # and x86-64, with 32-bit PowerPC first.
-            # (I'm guessing that's what Apple does.)
-            #
-            set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386;x86_64")
-        endif()
-    elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
-        #
-        # Leopard.  Build for 32-bit PowerPC, 64-bit
-        # PowerPC, x86, and x86-64, with 32-bit PowerPC
-        # first.  (That's what Apple does.)
-        #
-        set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386;x86_64")
-    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
-        #
-        # Snow Leopard.  Build for x86-64, x86, and
-        # 32-bit PowerPC, with x86-64 first.  (That's
-        # what Apple does, even though Snow Leopard
-        # doesn't run on PPC, so PPC libpcap runs under
-        # Rosetta, and Rosetta doesn't support BPF
-        # ioctls, so PPC programs can't do live
-        # captures.)
-        #
-        set(CMAKE_OSX_ARCHITECTURES "x86_64;i386;ppc")
-    else()
-        #
-        # Post-Snow Leopard.  Build for x86-64 and
-        # x86, with x86-64 first.  (That's probably what
-        # Apple does, given that Rosetta is gone.)
-        # XXX - update if and when Apple drops support
-        # for 32-bit x86 code.
-        #
-        set(CMAKE_OSX_ARCHITECTURES "x86_64;i386")
-    endif()
-endif()
-
-#
 # Additional capture modules.
 #
-option(DISABLE_USB "Disable USB sniffing support" OFF)
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    option(DISABLE_LINUX_USBMON "Disable Linux usbmon USB sniffing support" OFF)
+endif()
 option(DISABLE_BLUETOOTH "Disable Bluetooth sniffing support" OFF)
 option(DISABLE_NETMAP "Disable netmap support" OFF)
+option(DISABLE_DPDK "Disable DPDK support" OFF)
+
 #
 # We don't support D-Bus sniffing on macOS; see
 #
@@ -233,7 +239,7 @@
 option(DISABLE_DAG "Disable Endace DAG card support" OFF)
 
 option(DISABLE_SEPTEL "Disable Septel card support" OFF)
-set(SEPTEL_ROOT "${CMAKE_SOURCE_DIR}/../septel" CACHE PATH "Path to directory with include and lib subdirectories for Septel API")
+set(SEPTEL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../septel" CACHE PATH "Path to directory with include and lib subdirectories for Septel API")
 
 option(DISABLE_SNF "Disable Myricom SNF support" OFF)
 
@@ -289,6 +295,7 @@
 
 include(CheckFunctionExists)
 include(CMakePushCheckState)
+include(CheckSymbolExists)
 
 if(WIN32)
 
@@ -307,9 +314,18 @@
         cmake_push_check_state()
         set(CMAKE_REQUIRED_LIBRARIES ${PACKET_LIBRARIES})
         check_function_exists(PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER)
+        check_function_exists(PacketGetTimestampModes HAVE_PACKET_GET_TIMESTAMP_MODES)
         cmake_pop_check_state()
     endif(PACKET_FOUND)
 
+    message(STATUS "checking for Npcap's version.h")
+    check_symbol_exists(WINPCAP_PRODUCT_NAME "../../version.h" HAVE_VERSION_H)
+    if(HAVE_VERSION_H)
+        message(STATUS "HAVE version.h")
+    else(HAVE_VERSION_H)
+        message(STATUS "MISSING version.h")
+    endif(HAVE_VERSION_H)
+
 endif(WIN32)
 
 if(MSVC)
@@ -344,6 +360,11 @@
 include(CheckTypeSize)
 
 #
+# Tests are a bit expensive with Visual Studio on Windows, so, on
+# Windows, we skip tests for UN*X-only headers and functions.
+#
+
+#
 # Header files.
 #
 check_include_file(inttypes.h HAVE_INTTYPES_H)
@@ -357,9 +378,7 @@
     check_include_file(sys/ioccom.h HAVE_SYS_IOCCOM_H)
     check_include_file(sys/sockio.h HAVE_SYS_SOCKIO_H)
     check_include_file(sys/select.h HAVE_SYS_SELECT_H)
-endif(NOT WIN32)
-check_include_file(limits.h HAVE_LIMITS_H)
-if(NOT WIN32)
+
     check_include_file(netpacket/packet.h HAVE_NETPACKET_PACKET_H)
     check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H)
     if(HAVE_NET_PFVAR_H)
@@ -381,13 +400,6 @@
             HAVE_PF_NAT_THROUGH_PF_NORDR)
     endif(HAVE_NET_PFVAR_H)
     check_include_file(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H)
-    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-        check_include_file(linux/sockios.h HAVE_LINUX_SOCKIOS_H)
-        #
-        # linux/if_bonding.h requires sys/socket.h.
-        #
-        check_include_files("sys/socket.h;linux/if_bonding.h" HAVE_LINUX_IF_BONDING_H)
-    endif()
 endif(NOT WIN32)
 
 #
@@ -395,12 +407,58 @@
 #
 check_function_exists(strerror HAVE_STRERROR)
 check_function_exists(strerror_r HAVE_STRERROR_R)
-check_function_exists(strerror_s HAVE_STRERROR_S)
+if(HAVE_STRERROR_R)
+    #
+    # We have strerror_r; if we define _GNU_SOURCE, is it a
+    # POSIX-compliant strerror_r() or a GNU strerror_r()?
+    #
+    check_c_source_compiles(
+"#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+	return 0;
+}
+"
+            HAVE_GNU_STRERROR_R)
+    if(NOT HAVE_GNU_STRERROR_R)
+        set(HAVE_POSIX_STRERROR_R YES)
+    endif(NOT HAVE_GNU_STRERROR_R)
+else(HAVE_STRERROR_R)
+    #
+    # We don't have strerror_r; do we have _wcserror_s?
+    #
+    check_function_exists(_wcserror_s HAVE__WCSERROR_S)
+endif(HAVE_STRERROR_R)
+
+#
+# Make sure we have vsnprintf() and snprintf(); we require them.
+# We use check_symbol_exists(), as they aren't necessarily external
+# functions - in Visual Studio, for example, they're inline functions
+# calling a common external function.
+#
+check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
+if(NOT HAVE_VSNPRINTF)
+    message(FATAL_ERROR "vsnprintf() is required but wasn't found")
+endif(NOT HAVE_VSNPRINTF)
+check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
+if(NOT HAVE_SNPRINTF)
+    message(FATAL_ERROR "snprintf() is required but wasn't found")
+endif()
+
 check_function_exists(strlcpy HAVE_STRLCPY)
 check_function_exists(strlcat HAVE_STRLCAT)
-check_function_exists(snprintf HAVE_SNPRINTF)
-check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(asprintf HAVE_ASPRINTF)
+check_function_exists(vasprintf HAVE_VASPRINTF)
 check_function_exists(strtok_r HAVE_STRTOK_R)
+if(NOT WIN32)
+    check_function_exists(vsyslog HAVE_VSYSLOG)
+endif()
 
 #
 # These tests are for network applications that need socket functions
@@ -429,7 +487,6 @@
 #
 set(PCAP_LINK_LIBRARIES "")
 include(CheckLibraryExists)
-include(CheckSymbolExists)
 if(WIN32)
     #
     # We need winsock2.h and ws2tcpip.h.
@@ -465,10 +522,18 @@
             #
             set(PCAP_LINK_LIBRARIES socket nsl ${PCAP_LINK_LIBRARIES})
         else(LIBSOCKET_HAS_GETADDRINFO)
-            #
-            # We didn't find it.
-            #
-            message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+            check_library_exists(network getaddrinfo "" LIBNETWORK_HAS_GETADDRINFO)
+            if(LIBNETWORK_HAS_GETADDRINFO)
+                #
+                # OK, we found it in libnetwork (Haiku).
+                #
+                set(PCAP_LINK_LIBRARIES network ${PCAP_LINK_LIBRARIES})
+            else(LIBNETWORK_HAS_GETADDRINFO)
+                #
+                # We didn't find it.
+                #
+                message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+            endif(LIBNETWORK_HAS_GETADDRINFO)
         endif(LIBSOCKET_HAS_GETADDRINFO)
 
         #
@@ -844,6 +909,125 @@
   endif(NOT CMAKE_USE_PTHREADS_INIT)
 endif(NOT WIN32)
 
+if(ENABLE_PROFILING)
+    if(NOT MSVC)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+    endif()
+endif()
+
+#
+# Based on
+#
+#    https://github.com/commonmark/cmark/blob/master/FindAsan.cmake
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2013 Matthew Arsenault
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# Test if the each of the sanitizers in the ENABLE_SANITIZERS list are
+# supported by the compiler, and, if so, adds the appropriate flags to
+# CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, and SANITIZER_FLAGS.  If not, it fails.
+#
+# Do this last, in the hope that it will prevent configuration on Linux
+# from somehow deciding it doesn't need -lpthread when building rpcapd
+# (it does require it, but somehow, in some mysterious fashion that no
+# obvious CMake debugging flag reveals, it doesn't realize that if we
+# turn sanitizer stuff on).
+#
+set(SANITIZER_FLAGS "")
+foreach(sanitizer IN LISTS ENABLE_SANITIZERS)
+    # Set -Werror to catch "argument unused during compilation" warnings
+
+    message(STATUS "Checking sanitizer ${sanitizer}")
+    set(sanitizer_variable "sanitize_${sanitizer}")
+    set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=${sanitizer}")
+    check_c_compiler_flag("-fsanitize=${sanitizer}" ${sanitizer_variable})
+    if(${${sanitizer_variable}})
+        set(SANITIZER_FLAGS "${SANITIZER_FLAGS} -fsanitize=${sanitizer}")
+        message(STATUS "${sanitizer} sanitizer supported using -fsanitizer=${sanitizer}")
+    else()
+        #
+        # Try the versions supported prior to Clang 3.2.
+        # If the sanitizer is "address", try -fsanitize-address.
+        # If it's "undefined", try -fcatch-undefined-behavior.
+        # Otherwise, give up.
+        #
+        set(sanitizer_variable "OLD_${sanitizer_variable}")
+        if ("${sanitizer}" STREQUAL "address")
+            set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize-address")
+            check_c_compiler_flag("-fsanitize-address" ${sanitizer_variable})
+            if(${${sanitizer_variable}})
+                set(SANITIZER_FLAGS "${SANITIZER_FLAGS} -fsanitize-address")
+                message(STATUS "${sanitizer} sanitizer supported using -fsanitize-address")
+            else()
+                message(FATAL_ERROR "${sanitizer} isn't a supported sanitizer")
+            endif()
+        elseif("${sanitizer}" STREQUAL "undefined")
+            set(CMAKE_REQUIRED_FLAGS "-Werror -fcatch-undefined-behavior")
+            check_c_compiler_flag("-fcatch-undefined-behavior" ${sanitizer_variable})
+            if(${${sanitizer_variable}})
+                set(SANITIZER_FLAGS "${SANITIZER_FLAGS} -fcatch-undefined-behavior")
+                message(STATUS "${sanitizer} sanitizer supported using catch-undefined-behavior")
+            else()
+                message(FATAL_ERROR "${sanitizer} isn't a supported sanitizer")
+            endif()
+        else()
+            message(FATAL_ERROR "${sanitizer} isn't a supported sanitizer")
+        endif()
+    endif()
+
+    unset(CMAKE_REQUIRED_FLAGS)
+endforeach()
+
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -g ${SANITIZER_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O1 -g ${SANITIZER_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls")
+endif()
+
+#
+# OpenSSL/libressl.
+#
+find_package(OpenSSL)
+if(OPENSSL_FOUND)
+  #
+  # We have OpenSSL.
+  #
+  include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
+  set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${OPENSSL_LIBRARIES})
+  set(HAVE_OPENSSL YES)
+endif(OPENSSL_FOUND)
+
+#
+# Additional linker flags.
+#
+set(LINKER_FLAGS "${SANITIZER_FLAGS}")
+if(ENABLE_PROFILING)
+    if(MSVC)
+        set(LINKER_FLAGS " /PROFILE")
+    else()
+        set(LINKER_FLAGS " -pg")
+    endif()
+endif()
+
 ######################################
 # Input files
 ######################################
@@ -865,11 +1049,25 @@
 )
 
 if(WIN32)
-    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/win_snprintf.c)
+    #
+    # We add the character set conversion routines; they're Windows-only
+    # for now.
+    #
+    # We assume we don't have asprintf(), and provide an implementation
+    # that uses _vscprintf() to determine how big the string needs to be.
+    #
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+        charconv.c missing/win_asprintf.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_ASPRINTF)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
+    endif()
+    if(NOT HAVE_STRLCAT)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
+    endif(NOT HAVE_STRLCAT)
+    if(NOT HAVE_STRLCPY)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcpy.c)
+    endif(NOT HAVE_STRLCPY)
     if(NOT HAVE_STRTOK_R)
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strtok_r.c)
     endif(NOT HAVE_STRTOK_R)
@@ -931,13 +1129,16 @@
             # as it's a Linux, it should use packet sockets,
             # instead.
             #
-            #
             # We need:
             #
             #  sys/types.h, because FreeBSD 10's net/bpf.h
             #  requires that various BSD-style integer types
             #  be defined;
             #
+            #  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+            #  doesn't include it but does use struct timeval
+            #  in ioctl definitions;
+            #
             #  sys/ioctl.h and, if we have it, sys/ioccom.h,
             #  because net/bpf.h defines ioctls;
             #
@@ -952,9 +1153,9 @@
             # of those headers itself.
             #
             if(HAVE_SYS_IOCCOM_H)
-                check_symbol_exists(BIOCSETIF "sys/types.h;sys/ioctl.h;sys/socket.h;sys/ioccom.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;sys/ioccom.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
             else(HAVE_SYS_IOCCOM_H)
-                check_symbol_exists(BIOCSETIF "sys/types.h;sys/ioctl.h;sys/socket.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
             endif(HAVE_SYS_IOCCOM_H)
         endif(HAVE_NET_BPF_H)
         check_include_file(net/pfilt.h HAVE_NET_PFILT_H)
@@ -964,6 +1165,7 @@
         check_include_file(linux/socket.h HAVE_LINUX_SOCKET_H)
         check_include_file(net/raw.h HAVE_NET_RAW_H)
         check_include_file(sys/dlpi.h HAVE_SYS_DLPI_H)
+        check_include_file(config/HaikuConfig.h HAVE_CONFIG_HAIKUCONFIG_H)
 
         if(BPF_H_DEFINES_BIOCSETIF)
             #
@@ -1007,6 +1209,11 @@
             # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
             #
             set(PCAP_TYPE dlpi)
+        elseif(HAVE_CONFIG_HAIKUCONFIG_H)
+            #
+            # Haiku.
+            #
+            set(PCAP_TYPE haiku)
         else()
             #
             # Nothing we support.
@@ -1017,18 +1224,20 @@
 endif(WIN32)
 message(STATUS "Packet capture mechanism type: ${PCAP_TYPE}")
 
+find_package(PkgConfig QUIET)
+
 #
 # Do capture-mechanism-dependent tests.
 #
 if(WIN32)
     if(PCAP_TYPE STREQUAL "npf")
         #
-        # Link with packet.dll before WinSock2.
+        # Link with packet.dll before Winsock2.
         #
         set(PCAP_LINK_LIBRARIES ${PACKET_LIBRARIES} ${PCAP_LINK_LIBRARIES})
     elseif(PCAP_TYPE STREQUAL "null")
     else()
-        message(ERROR "${PCAP_TYPE} is not a valid pcap type")
+        message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
     endif()
 else(WIN32)
     if(PCAP_TYPE STREQUAL "dlpi")
@@ -1088,70 +1297,34 @@
 
         #
         # Do we have libnl?
+        # We only want version 3.  Version 2 was, apparently,
+        # short-lived, and version 1 is source and binary
+        # incompatible with version 3, and it appears that,
+        # these days, everybody's using version 3.  We're
+        # not supporting older versions of the Linux kernel;
+        # let's drop support for older versions of libnl, too.
         #
         if(BUILD_WITH_LIBNL)
-            #
-            # Try libnl 3.x first.
-            #
-            cmake_push_check_state()
-            set(CMAKE_REQUIRED_LIBRARIES nl-3)
-            check_function_exists(nl_socket_alloc HAVE_LIBNL)
-            cmake_pop_check_state()
-            if(HAVE_LIBNL)
-                #
-                # Yes, we have libnl 3.x.
-                #
-                set(PCAP_LINK_LIBRARIES nl-genl-3 nl-3 ${PCAP_LINK_LIBRARIES})
-                set(HAVE_LIBNL_3_x ON)
-                set(HAVE_LIBNL_NLE ON)
-                set(HAVE_LIBNL_SOCKETS ON)
-                include_directories("/usr/include/libnl3")
+            pkg_check_modules(LIBNL libnl-3.0)
+            if(LIBNL_FOUND)
+                set(PCAP_LINK_LIBRARIES ${LIBNL_LIBRARIES} ${PCAP_LINK_LIBRARIES})
             else()
-                #
-                # Try libnl 2.x.
-                #
                 cmake_push_check_state()
-                set(CMAKE_REQUIRED_LIBRARIES nl)
+                set(CMAKE_REQUIRED_LIBRARIES nl-3)
                 check_function_exists(nl_socket_alloc HAVE_LIBNL)
                 cmake_pop_check_state()
                 if(HAVE_LIBNL)
                     #
-                    # Yes, we have libnl 2.x.
+                    # Yes, we have libnl 3.x.
                     #
-                    set(PCAP_LINK_LIBRARIES nl-genl nl ${PCAP_LINK_LIBRARIES})
-                    set(HAVE_LIBNL_2_x ON)
-                    set(HAVE_LIBNL_NLE ON)
-                    set(HAVE_LIBNL_SOCKETS ON)
-                else()
-                    #
-                    # No, we don't; do we have libnl 1.x?
-                    #
-                    cmake_push_check_state()
-                    set(CMAKE_REQUIRED_LIBRARIES nl)
-                    check_function_exists(nl_handle_alloc HAVE_LIBNL)
-                    cmake_pop_check_state()
-                    if(HAVE_LIBNL)
-                        set(PCAP_LINK_LIBRARIES nl ${PCAP_LINK_LIBRARIES})
-                    endif()
+                    set(PCAP_LINK_LIBRARIES nl-genl-3 nl-3 ${PCAP_LINK_LIBRARIES})
+                    include_directories("/usr/include/libnl3")
                 endif()
             endif()
+        else()
+            unset(HAVE_LIBNL CACHE) # check_function_exists stores results in cache
         endif()
 
-        check_include_file(linux/ethtool.h HAVE_LINUX_ETHTOOL_H)
-
-        #
-        # Checks to see if tpacket_stats is defined in linux/if_packet.h
-        # If so then pcap-linux.c can use this to report proper statistics.
-        #
-        # XXX - there's no check_type() macro that's like check_type_size()
-        # except that it only checks for the existence of the structure type,
-        # so we use check_type_size() and ignore the size.
-        #
-        cmake_push_check_state()
-        set(CMAKE_EXTRA_INCLUDE_FILES linux/if_packet.h)
-        check_type_size("struct tpacket_stats" STRUCT_TPACKET_STATS)
-        cmake_pop_check_state()
-
         check_struct_has_member("struct tpacket_auxdata" tp_vlan_tci linux/if_packet.h HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
     elseif(PCAP_TYPE STREQUAL "bpf")
         #
@@ -1175,13 +1348,23 @@
             check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
         endif()
         cmake_pop_check_state()
+    elseif(PCAP_TYPE STREQUAL "haiku")
+        #
+        # Check for some headers just in case.
+        #
+        check_include_files("net/if.h;net/if_dl.h;net/if_types.h" HAVE_NET_IF_TYPES_H)
+        set(PCAP_SRC pcap-${PCAP_TYPE}.cpp)
     elseif(PCAP_TYPE STREQUAL "null")
     else()
         message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
     endif()
 endif(WIN32)
 
-set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-${PCAP_TYPE}.c)
+if(NOT DEFINED PCAP_SRC)
+set(PCAP_SRC pcap-${PCAP_TYPE}.c)
+endif()
+
+set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${PCAP_SRC})
 
 #
 # Now figure out how we get a list of interfaces and addresses,
@@ -1287,11 +1470,13 @@
 # Check for additional native sniffing capabilities.
 #
 
-# Check for USB sniffing support on Linux.
-# On FreeBSD, it uses BPF, so we don't need to do anything special here.
-if(NOT DISABLE_USB)
-    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-        set(PCAP_SUPPORT_USB TRUE)
+#
+# Various Linux-specific mechanisms.
+#
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    # Check for usbmon USB sniffing support.
+    if(NOT DISABLE_LINUX_USBMON)
+        set(PCAP_SUPPORT_LINUX_USBMON TRUE)
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-usb-linux.c)
         set(LINUX_USB_MON_DEV /dev/usbmon)
         #
@@ -1321,10 +1506,9 @@
             endif(HAVE_LINUX_COMPILER_H)
         endif()
     endif()
-endif()
 
-# Check for netfilter sniffing support.
-if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    #
+    # Check for netfilter sniffing support.
     #
     # Life's too short to deal with trying to get this to compile
     # if you don't get the right types defined with
@@ -1380,6 +1564,48 @@
     endif(PCAP_SUPPORT_NETMAP)
 endif()
 
+# Check for DPDK sniffing support
+if(NOT DISABLE_DPDK)
+    find_package(dpdk)
+    if(dpdk_FOUND)
+        #
+        # We include rte_bus.h, and older versions of DPDK didn't have
+        # it, so check for it.
+        #
+        # Also, we call rte_eth_dev_count_avail(), and older versions
+        # of DPDK didn't have it, so check for it.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_INCLUDES ${dpdk_INCLUDE_DIRS})
+        check_include_file(rte_bus.h HAVE_RTE_BUS_H)
+        set(CMAKE_REQUIRED_LIBRARIES ${dpdk_LIBRARIES})
+        check_function_exists(rte_eth_dev_count_avail HAVE_RTE_ETH_DEV_COUNT_AVAIL)
+        cmake_pop_check_state()
+        if(HAVE_RTE_BUS_H AND HAVE_RTE_ETH_DEV_COUNT_AVAIL)
+            set(DPDK_C_FLAGS "-march=native")
+            set(DPDK_LIB dpdk rt m numa dl)
+            set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} ${DPDK_C_FLAGS})
+            include_directories(AFTER ${dpdk_INCLUDE_DIRS})
+            link_directories(AFTER ${dpdk_LIBRARIES})
+            set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${dpdk_LIBRARIES})
+            set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dpdk.c)
+            set(PCAP_SUPPORT_DPDK TRUE)
+
+            #
+            # Check whether the rte_ether.h file defines
+            # struct ether_addr or struct rte_ether_addr.
+            #
+            # ("API compatibility?  That's for losers!")
+            #
+            cmake_push_check_state()
+            set(CMAKE_REQUIRED_INCLUDES ${dpdk_INCLUDE_DIRS})
+            set(CMAKE_EXTRA_INCLUDE_FILES rte_ether.h)
+            check_type_size("struct rte_ether_addr" STRUCT_RTE_ETHER_ADDR)
+            cmake_pop_check_state()
+        endif()
+    endif()
+endif()
+
 # Check for Bluetooth sniffing support
 if(NOT DISABLE_BLUETOOTH)
     if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
@@ -1418,9 +1644,11 @@
             endif(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
         endif(HAVE_BLUETOOTH_BLUETOOTH_H)
     endif()
+else()
+    unset(PCAP_SUPPORT_BT_MONITOR CACHE)
 endif()
 
-# Check for Bluetooth sniffing support
+# Check for D-Bus sniffing support
 if(NOT DISABLE_DBUS)
     #
     # We don't support D-Bus sniffing on macOS; see
@@ -1430,13 +1658,33 @@
     if(APPLE)
         message(FATAL_ERROR "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS")
     endif(APPLE)
-    include(FindPkgConfig)
     pkg_check_modules(DBUS dbus-1)
     if(DBUS_FOUND)
         set(PCAP_SUPPORT_DBUS TRUE)
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dbus.c)
         include_directories(${DBUS_INCLUDE_DIRS})
-        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARIES})
+
+        #
+        # This "helpfully" supplies DBUS_LIBRARIES as a bunch of
+        # library names - not paths - and DBUS_LIBRARY_DIRS as
+        # a bunch of directories.
+        #
+        # CMake *really* doesn't like the notion of specifying "here are
+        # the directories in which to look for libraries" except in
+        # find_library() calls; it *really* prefers using full paths to
+        # library files, rather than library names.
+        #
+        # Find the libraries and add their full paths.
+        #
+        set(DBUS_LIBRARY_FULLPATHS)
+        foreach(_lib IN LISTS DBUS_LIBRARIES)
+            #
+            # Try to find this library, so we get its full path.
+            #
+            find_library(_libfullpath ${_lib} HINTS ${DBUS_LIBRARY_DIRS})
+            list(APPEND DBUS_LIBRARY_FULLPATHS ${_libfullpath})
+        endforeach()
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARY_FULLPATHS})
     endif(DBUS_FOUND)
 endif(NOT DISABLE_DBUS)
 
@@ -1544,6 +1792,27 @@
     endif()
 endif()
 
+# Check for Riverbed AirPcap support.
+if(NOT DISABLE_AIRPCAP)
+    #
+    # Try to find the AirPcap header file and library.
+    #
+    find_package(AirPcap)
+
+    #
+    # Did we succeed?
+    #
+    if(AIRPCAP_FOUND)
+        #
+        # Yes.
+        #
+        include_directories(AFTER ${AIRPCAP_INCLUDE_DIRS})
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-airpcap.c)
+        set(HAVE_AIRPCAP_API TRUE)
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${AIRPCAP_LIBRARIES})
+    endif()
+endif()
+
 # Check for Riverbed TurboCap support.
 if(NOT DISABLE_TC)
     #
@@ -1561,7 +1830,7 @@
         include_directories(AFTER ${TC_INCLUDE_DIRS})
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-tc.c)
         set(HAVE_TC_API TRUE)
-        set(PCAP_LINK_LIBRARIES "${PCAP_LINK_LIBRARIES} ${TC_LIBRARIES} ${CMAKE_USE_PTHREADS_INIT} stdc++")
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${TC_LIBRARIES} ${CMAKE_USE_PTHREADS_INIT} stdc++)
     endif()
 endif()
 
@@ -1582,12 +1851,12 @@
     # the check.
     #
     cmake_push_check_state()
-    set(CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR})
+    set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
     check_struct_has_member("struct msghdr" msg_control "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_CONTROL)
     check_struct_has_member("struct msghdr" msg_flags "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_FLAGS)
     cmake_pop_check_state()
     set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
-        pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c)
+        pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c sslutils.c)
 endif(ENABLE_REMOTE)
 
 ###################################################################
@@ -1597,7 +1866,7 @@
 #
 # Check and add warning options if we have a .devel file.
 #
-if(EXISTS ${CMAKE_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
     #
     # Warning options.
     #
@@ -1656,6 +1925,20 @@
         # structure members.
         #
         check_and_add_compiler_option(-wd4820)
+        #
+        # We do *not* care about every single place the compiler would
+        # have inserted Spectre mitigation if only we had told it to
+        # do so with /Qspectre.  Maybe it's worth it, as that's in
+        # Bison-generated code that we don't control.
+        #
+        # XXX - add /Qspectre if that is really worth doing.
+        #
+        check_and_add_compiler_option(-wd5045)
+
+        #
+        # Treat all (remaining) warnings as errors.
+        #
+        check_and_add_compiler_option(-WX)
     else()
         #
         # Other compilers, including MSVC with a Clang front end and
@@ -1663,21 +1946,23 @@
         # they might support GCC-style -W options.
         #
         check_and_add_compiler_option(-Wall)
-        check_and_add_compiler_option(-Wsign-compare)
-        check_and_add_compiler_option(-Wmissing-prototypes)
-        check_and_add_compiler_option(-Wstrict-prototypes)
-        check_and_add_compiler_option(-Wshadow)
-        check_and_add_compiler_option(-Wdeclaration-after-statement)
-        check_and_add_compiler_option(-Wused-but-marked-unused)
-        check_and_add_compiler_option(-Wdocumentation)
         check_and_add_compiler_option(-Wcomma)
-        check_and_add_compiler_option(-Wmissing-noreturn)
         # Warns about safeguards added in case the enums are extended
         # check_and_add_compiler_option(-Wcovered-switch-default)
-        check_and_add_compiler_option(-Wmissing-variable-declarations)
-        check_and_add_compiler_option(-Wunused-parameter)
+        check_and_add_compiler_option(-Wdocumentation)
         check_and_add_compiler_option(-Wformat-nonliteral)
+        check_and_add_compiler_option(-Wmissing-noreturn)
+        check_and_add_compiler_option(-Wmissing-prototypes)
+        check_and_add_compiler_option(-Wmissing-variable-declarations)
+        check_and_add_compiler_option(-Wpointer-arith)
+        check_and_add_compiler_option(-Wpointer-sign)
+        check_and_add_compiler_option(-Wshadow)
+        check_and_add_compiler_option(-Wsign-compare)
+        check_and_add_compiler_option(-Wshorten-64-to-32)
+        check_and_add_compiler_option(-Wstrict-prototypes)
         check_and_add_compiler_option(-Wunreachable-code)
+        check_and_add_compiler_option(-Wunused-parameter)
+        check_and_add_compiler_option(-Wused-but-marked-unused)
     endif()
 endif()
 
@@ -1774,6 +2059,27 @@
 if(YACC_EXECUTABLE STREQUAL "YACC_EXECUTABLE-NOTFOUND")
     message(FATAL_ERROR "Neither bison nor win_bison nor byacc nor yacc was found.")
 endif()
+
+if(YACC_EXECUTABLE MATCHES "byacc" OR YACC_EXECUTABLE MATCHES "yacc")
+    #
+    # Berkeley YACC doesn't support "%define api.pure", so use
+    # "%pure-parser".
+    #
+    set(REENTRANT_PARSER "%pure-parser")
+else()
+    #
+    # Bison prior to 2.4(.1) doesn't support "%define api.pure", so use
+    # "%pure-parser".
+    #
+    execute_process(COMMAND ${YACC_EXECUTABLE} -V OUTPUT_VARIABLE bison_full_version)
+    string(REGEX MATCH "[1-9][0-9]*[.][1-9][0-9]*" bison_major_minor ${bison_full_version})
+    if (bison_major_minor VERSION_LESS "2.4")
+        set(REENTRANT_PARSER "%pure-parser")
+    else()
+        set(REENTRANT_PARSER "%define api.pure")
+    endif()
+endif()
+
 message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
 
 #
@@ -1787,9 +2093,9 @@
 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
+    SOURCE ${pcap_BINARY_DIR}/grammar.y
+    COMMAND ${YACC_EXECUTABLE} ${YACC_COMPATIBILITY_FLAG} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_BINARY_DIR}/grammar.y
+    DEPENDS ${pcap_BINARY_DIR}/grammar.y
 )
 
 #
@@ -1808,10 +2114,12 @@
 
 #
 # Assume, by default, no support for shared libraries and V7/BSD
-# convention for man pages (file formats in section 5, miscellaneous
-# info in section 7, administrative commands and daemons in section 8).
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
 # Individual cases can override this.
 #
+set(MAN_DEVICES 4)
 set(MAN_FILE_FORMATS 5)
 set(MAN_MISC_INFO 7)
 set(MAN_ADMIN_COMMANDS 8)
@@ -1869,6 +2177,7 @@
     #
     set(MAN_FILE_FORMATS 4)
     set(MAN_MISC_INFO 5)
+    set(MAN_DEVICES 7)
 elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
     #
     # SunOS 5.x.
@@ -1892,7 +2201,13 @@
         set(MAN_ADMIN_COMMANDS 1m)
         set(MAN_FILE_FORMATS 4)
         set(MAN_MISC_INFO 5)
+        set(MAN_DEVICES 7D)
     endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
+    #
+    # Haiku needs _BSD_SOURCE for the _IO* macros because it doesn't use them.
+    #
+    add_definitions(-D_BSD_SOURCE)
 endif()
 
 source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
@@ -1923,7 +2238,7 @@
 #
 # See
 #
-#  http://public.kitware.com/pipermail/cmake/2013-August/055510.html
+#  https://public.kitware.com/pipermail/cmake/2013-August/055510.html
 #
 add_custom_target(SerializeTarget
     DEPENDS
@@ -1944,6 +2259,20 @@
     add_dependencies(${LIBRARY_NAME} SerializeTarget)
     set_target_properties(${LIBRARY_NAME} PROPERTIES
         COMPILE_DEFINITIONS BUILDING_PCAP)
+    #
+    # No matter what the library is called - it might be called "wpcap"
+    # in a Windows build - the symbol to define to indicate that we're
+    # building the library, rather than a program using the library,
+    # and thus that we're exporting functions defined in our public
+    # header files, rather than importing those functions, is
+    # pcap_EXPORTS.
+    #
+    set_target_properties(${LIBRARY_NAME} PROPERTIES
+        DEFINE_SYMBOL pcap_EXPORTS)
+    if(NOT "${LINKER_FLAGS}" STREQUAL "")
+        set_target_properties(${LIBRARY_NAME} PROPERTIES
+            LINK_FLAGS "${LINKER_FLAGS}")
+    endif()
 endif(BUILD_SHARED_LIBS)
 
 add_library(${LIBRARY_NAME}_static STATIC
@@ -2020,6 +2349,130 @@
     set_target_properties(${LIBRARY_NAME}_static PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
 endif()
 
+#
+# On macOS, build libpcap for the appropriate architectures, if
+# CMAKE_OSX_ARCHITECTURES isn't set (if it is, let that control
+# the architectures for which to build it).
+#
+if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+    #
+    # Get the major version of Darwin.
+    #
+    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+    if(SYSTEM_VERSION_MAJOR LESS 8)
+        #
+        # Pre-Tiger.  Build only for 32-bit PowerPC.
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "ppc")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 8)
+        #
+        # Tiger.  Is this prior to, or with, Intel support?
+        #
+        # Get the minor version of Darwin.
+        #
+        string(REPLACE "${SYSTEM_VERSION_MAJOR}." "" SYSTEM_MINOR_AND_PATCH_VERSION ${CMAKE_SYSTEM_VERSION})
+        string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MINOR "${SYSTEM_MINOR_AND_PATCH_VERSION}")
+        if(SYSTEM_VERSION_MINOR LESS 4)
+            #
+            # Prior to Intel support.  Build for 32-bit
+            # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
+            # first.  (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64")
+        elseif(SYSTEM_VERSION_MINOR LESS 7)
+            #
+            # With Intel support but prior to x86-64 support.
+            # Build for 32-bit PowerPC, 64-bit PowerPC, and 32-bit x86,
+            # with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386")
+        else()
+            #
+            # With Intel support including x86-64 support.
+            # Build for 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+            # and x86-64, with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+        endif()
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
+        #
+        # Leopard.  Build for 32-bit PowerPC, 64-bit
+        # PowerPC, 32-bit x86, and x86-64, with 32-bit PowerPC
+        # first.  (That's what Apple does.)
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+        #
+        # Snow Leopard.  Build for x86-64, 32-bit x86, and
+        # 32-bit PowerPC, with x86-64 first.  (That's
+        # what Apple does, even though Snow Leopard
+        # doesn't run on PPC, so PPC libpcap runs under
+        # Rosetta, and Rosetta doesn't support BPF
+        # ioctls, so PPC programs can't do live
+        # captures.)
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386;ppc")
+    else()
+        #
+        # Post-Snow Leopard.  Build for x86-64 and 32-bit x86,
+        # with x86-64 first.  (That's what Apple does)
+        # XXX - update if and when Apple drops support
+        # for 32-bit x86 code and if and when Apple adds
+        # ARM-based Macs.  (You're on your own for iOS etc.)
+        #
+        # First, check whether we're building with OpenSSL.
+        # If so, don't bother trying to build fat.
+        #
+        if(HAVE_OPENSSL)
+          set(X86_32_BIT_SUPPORTED NO)
+          set(OSX_LIBRARY_ARCHITECTURES "x86_64")
+          message(WARNING "We're assuming the OpenSSL libraries are 64-bit only, so we're not compiling for 32-bit x86")
+        else()
+          #
+          # Now, check whether we *can* build for i386.
+          #
+          cmake_push_check_state()
+          set(CMAKE_REQUIRED_FLAGS "-arch i386")
+          check_c_source_compiles(
+"int
+main(void)
+{
+    return 0;
+}
+"
+                   X86_32_BIT_SUPPORTED)
+          cmake_pop_check_state()
+          if(X86_32_BIT_SUPPORTED)
+              set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386")
+          else()
+              set(OSX_LIBRARY_ARCHITECTURES "x86_64")
+              #
+              # We can't build fat; suggest that the user install the
+              # /usr/include headers if they want to build fat.
+              #
+              if(SYSTEM_VERSION_MAJOR LESS 18)
+                  #
+                  # Pre-Mojave; the command-line tools should be sufficient to
+                  # enable 32-bit x86 builds.
+                  #
+                  message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools")
+              else()
+                  message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package")
+              endif()
+          endif()
+        endif()
+    endif()
+    if(BUILD_SHARED_LIBS)
+        set_target_properties(${LIBRARY_NAME} PROPERTIES
+            OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+    endif(BUILD_SHARED_LIBS)
+    set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+        OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+endif()
+
 ######################################
 # Write out the config.h file
 ######################################
@@ -2027,6 +2480,12 @@
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
 ######################################
+# Write out the grammar.y file
+######################################
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/grammar.y.in ${CMAKE_CURRENT_BINARY_DIR}/grammar.y @ONLY)
+
+######################################
 # Install pcap library, include files, and man pages
 ######################################
 
@@ -2041,12 +2500,11 @@
 
 function(install_manpage_symlink SOURCE TARGET MANDIR)
     if(MINGW)
-        find_program(LINK_EXECUTABLE ln)
-            if(LINK_EXECUTABLE)
-                set(LINK_COMMAND "\"${LINK_EXECUTABLE}\" \"-s\" \"${SOURCE}\" \"${TARGET}\"")
-            else(LINK_EXECUTABLE)
-                message(FATAL_ERROR "ln (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html) not found.")
-            endif(LINK_EXECUTABLE)
+        #
+        # If we haven't found an ln executable with MinGW, we don't try
+        # generating and installing the man pages, so if we get here,
+        # we've found that executable.
+        set(LINK_COMMAND "\"${LINK_EXECUTABLE}\" \"-s\" \"${SOURCE}\" \"${TARGET}\"")
     else(MINGW)
         set(LINK_COMMAND "\"${CMAKE_COMMAND}\" \"-E\" \"create_symlink\" \"${SOURCE}\" \"${TARGET}\"")
     endif(MINGW)
@@ -2079,6 +2537,7 @@
     pcap_list_tstamp_types.3pcap.in
     pcap_open_dead.3pcap.in
     pcap_open_offline.3pcap.in
+    pcap_set_immediate_mode.3pcap.in
     pcap_set_tstamp_precision.3pcap.in
     pcap_set_tstamp_type.3pcap.in
 )
@@ -2102,6 +2561,7 @@
     pcap_get_required_select_timeout.3pcap
     pcap_get_selectable_fd.3pcap
     pcap_geterr.3pcap
+    pcap_init.3pcap
     pcap_inject.3pcap
     pcap_is_swapped.3pcap
     pcap_lib_version.3pcap
@@ -2114,7 +2574,6 @@
     pcap_open_live.3pcap
     pcap_set_buffer_size.3pcap
     pcap_set_datalink.3pcap
-    pcap_set_immediate_mode.3pcap
     pcap_set_promisc.3pcap
     pcap_set_protocol_linux.3pcap
     pcap_set_rfmon.3pcap
@@ -2144,19 +2603,19 @@
 if(WIN32)
     if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
         #
-        # Install 64-bit code built with MSVC in the amd64 subdirectories,
+        # Install 64-bit code built with MSVC in the x64 subdirectories,
         # as that's where it expects it to be.
         #
         install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC}
-                RUNTIME DESTINATION bin/amd64
-                LIBRARY DESTINATION lib/amd64
-                ARCHIVE DESTINATION lib/amd64)
+                RUNTIME DESTINATION bin/x64
+                LIBRARY DESTINATION lib/x64
+                ARCHIVE DESTINATION lib/x64)
         if(NOT MINGW)
             install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
-                    DESTINATION bin/amd64 OPTIONAL)
+                    DESTINATION bin/x64 OPTIONAL)
             if(BUILD_SHARED_LIBS)
                 install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
-                        DESTINATION bin/amd64 OPTIONAL)
+                        DESTINATION bin/x64 OPTIONAL)
             endif(BUILD_SHARED_LIBS)
         endif(NOT MINGW)
     else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -2179,7 +2638,7 @@
         endif(NOT MINGW)
     endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
 else(WIN32)
-    install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC} DESTINATION lib)
+    install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
 endif(WIN32)
 
 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pcap/ DESTINATION include/pcap)
@@ -2194,7 +2653,7 @@
     set(prefix ${CMAKE_INSTALL_PREFIX})
     set(exec_prefix "\${prefix}")
     set(includedir "\${prefix}/include")
-    set(libdir "\${exec_prefix}/lib")
+    set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
     if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
        CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
        CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
@@ -2225,8 +2684,8 @@
     foreach(LIB ${PCAP_LINK_LIBRARIES})
         set(LIBS "${LIBS} -l${LIB}")
     endforeach(LIB)
-    configure_file(${CMAKE_SOURCE_DIR}/pcap-config.in ${CMAKE_CURRENT_BINARY_DIR}/pcap-config @ONLY)
-    configure_file(${CMAKE_SOURCE_DIR}/libpcap.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc @ONLY)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcap-config.in ${CMAKE_CURRENT_BINARY_DIR}/pcap-config @ONLY)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpcap.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc @ONLY)
     install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pcap-config DESTINATION bin)
     install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc DESTINATION lib/pkgconfig)
 
@@ -2236,54 +2695,64 @@
     # For each section of the manual for which we have man pages
     # that require macro expansion, do the expansion.
     #
-    set(MAN1 "")
-    foreach(MANPAGE ${MAN1_NOEXPAND})
-        set(MAN1 ${MAN1} ${CMAKE_SOURCE_DIR}/${MANPAGE})
-    endforeach(MANPAGE)
-    install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+    # If this is MinGW, maybe we have a UN*X-style ln command and
+    # maybe we don't.  (No, we do *NOT* require MSYS!)  If we don't
+    # have it, don't do the man pages.
+    #
+    if(MINGW)
+        find_program(LINK_EXECUTABLE ln)
+    endif(MINGW)
+    if(UNIX OR (MINGW AND LINK_EXECUTABLE))
+        set(MAN1 "")
+        foreach(MANPAGE ${MAN1_NOEXPAND})
+            set(MAN1 ${MAN1} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
+        endforeach(MANPAGE)
+        install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
 
-    set(MAN3PCAP "")
-    foreach(MANPAGE ${MAN3PCAP_NOEXPAND})
-        set(MAN3PCAP ${MAN3PCAP} ${CMAKE_SOURCE_DIR}/${MANPAGE})
-    endforeach(MANPAGE)
-    foreach(TEMPLATE_MANPAGE ${MAN3PCAP_EXPAND})
-        string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
-        configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
-        set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
-    endforeach(TEMPLATE_MANPAGE)
-    install(FILES ${MAN3PCAP} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_dump_open.3pcap pcap_dump_fopen.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_findalldevs.3pcap pcap_freealldevs.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_geterr.3pcap pcap_perror.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_inject.3pcap pcap_sendpacket.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_loop.3pcap pcap_dispatch.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_major_version.3pcap pcap_minor_version.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_next_ex.3pcap pcap_next.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_open_dead.3pcap pcap_open_dead_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
-    install_manpage_symlink(pcap_setnonblock.3pcap pcap_getnonblock.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        set(MAN3PCAP "")
+        foreach(MANPAGE ${MAN3PCAP_NOEXPAND})
+            set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
+        endforeach(MANPAGE)
+        foreach(TEMPLATE_MANPAGE ${MAN3PCAP_EXPAND})
+            string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
+            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+            set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+        endforeach(TEMPLATE_MANPAGE)
+        install(FILES ${MAN3PCAP} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description_or_dlt.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_dump_open.3pcap pcap_dump_fopen.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_findalldevs.3pcap pcap_freealldevs.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_geterr.3pcap pcap_perror.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_inject.3pcap pcap_sendpacket.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_loop.3pcap pcap_dispatch.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_major_version.3pcap pcap_minor_version.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_next_ex.3pcap pcap_next.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_open_dead.3pcap pcap_open_dead_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+        install_manpage_symlink(pcap_setnonblock.3pcap pcap_getnonblock.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
 
-    set(MANFILE "")
-    foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
-        string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
-        configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
-        set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
-    endforeach(TEMPLATE_MANPAGE)
-    install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
+        set(MANFILE "")
+        foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
+            string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
+            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+            set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+        endforeach(TEMPLATE_MANPAGE)
+        install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
 
-    set(MANMISC "")
-    foreach(TEMPLATE_MANPAGE ${MANMISC_EXPAND})
-        string(REPLACE ".manmisc.in" ".${MAN_MISC_INFO}" MANPAGE ${TEMPLATE_MANPAGE})
-        configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
-        set(MANMISC ${MANMISC} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
-    endforeach(TEMPLATE_MANPAGE)
-    install(FILES ${MANMISC} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_MISC_INFO})
+        set(MANMISC "")
+        foreach(TEMPLATE_MANPAGE ${MANMISC_EXPAND})
+            string(REPLACE ".manmisc.in" ".${MAN_MISC_INFO}" MANPAGE ${TEMPLATE_MANPAGE})
+            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+            set(MANMISC ${MANMISC} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+        endforeach(TEMPLATE_MANPAGE)
+        install(FILES ${MANMISC} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_MISC_INFO})
+    endif(UNIX OR (MINGW AND LINK_EXECUTABLE))
 endif(NOT MSVC)
 
 # uninstall target
diff --git a/CREDITS b/CREDITS
index 8b7e7ce..d01e832 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3,29 +3,42 @@
 The current maintainers (in alphabetical order):
     Denis Ovsienko                <denis at ovsienko dot info>
     Francois-Xavier Le Bail       <devel dot fx dot lebail at orange dot fr>
-    Guy Harris                    <guy at alum dot mit dot edu>
+    Guy Harris                    <gharris at sonic dot net>
     Michael Richardson            <mcr at sandelman dot ottawa dot on dot ca>
 
 Additional people who have contributed patches (in alphabetical order):
+    Adrian Budau                  <adbudau at bitdefender dot com>
     Akos Vandra                   <axos88 at gmail dot com>
     Alan Bawden                   <Alan at LCS dot MIT dot EDU>
     Albert Chin                   <china at thewrittenword dot com>
+    Alexander Galanin             <al at galanin dot nnov dot ru>
     Alexander 'Leo' Bergolth      <Leo dot Bergolth at wu-wien dot ac dot at>
     Alexey Kuznetsov              <kuznet at ms2 dot inr dot ac dot ru>
+    Alex Smith                    <44322503+MadAlexUK at users dot noreply dot github dot com>
+    Alfredo Alvarez Fernandez     <alfredoalvarezernandez at gmail dot com>
     Ali Abdulkadir                <autostart dot ini at gmail dot com>
     Alon Bar-Lev                  <alonbl at sourceforge dot net>
+    Anders Broman                 <anders dot broman at ericsson dot com>
     Andres Perera                 <andres dot p at zoho dot com>
     Andrew Brown                  <atatat at atatdot dot net>
                                   <andy-1 at sourceforge dot net>
     Ani Sinha                     <ani at aristanetworks dot com>
+    Anthony Kirby                 <Anthony dot Kirby at nominet dot uk>
     Antti Kantee                  <pooka at netbsd dot org>
     Arien Vijn                    <arienvijn at sourceforge dot net>
     Arkadiusz Miskiewicz          <misiek at pld dot org dot pl>
     Armando L. Caro Jr.           <acaro at mail dot eecis dot udel dot edu>
     Assar Westerlund              <assar at sics dot se>
+    Atzm Watanabe                 <atzm at atzm dot org>
+    Baptiste Peugnez              <baptiste dot peugnez at cea dot fr>
+    Baruch Siach                  <baruch at tkos dot co dot il>
     Bill Parker                   <wp02855 at gmail dot com>
+    blazeable                     <blazeable at blazeable dot eu>
+    bleader                       <bleader at ratonland dot org>
     Brent Cook                    <brent at boundary dot com>
     Brian Ginsbach                <ginsbach at cray dot com>
+    B. Scott Michel               <scooter dot phd at gmail dot com>
+    Cedric Cellier                <rixed at happyleptic dot org>
     Charles M. Hannum             <mycroft at netbsd dot org>
     Chris G. Demetriou            <cgd at netbsd dot org>
     Chris Lightfoot               <cwrl at users dot sourceforge dot net>
@@ -34,15 +47,22 @@
     Christian Bell                <csbell at myri dot com>
     Christian Peron               <csjp at freebsd dot org>
     Christian Svensson            <blue at cmd dot nu>
+    Christopher K Lee             <christopher dot lee at cspi dot com>
+    Daniel Borkmann               <dborkman at redhat dot com>
     Daniele Orlandi               <daniele at orlandi dot com>
+    Daniel Lublin                 <daniel at lublin dot se>
+    Daniel Miller                 <dmiller at nmap dot org>
+    Dario Lombardo                <lomato at gmail dot com>
     Darren Lim                    <darren dot lim at endace dot com>
     Darren Reed                   <darrenr at sun dot com>
+    Dave Barach                   <dave at barachs dot net>
     David Clark                   <david dot clark at datasoft dot com>
     David Kaelbling               <drk at sgi dot com>
     David Ward                    <david dot ward at ll dot mit dot edu>
     David Young                   <dyoung at ojctech dot com>
     Dean Gaudet                   <dean at arctic dot org>
     dhruv                         <rsrivat at sourceforge dot net>
+    Dmytro Ovdiienko              <dmitriy dot ovdienko at gmail dot com>
     Don Ebright                   <Don dot Ebright at compuware dot com>
     Dug Song                      <dugsong at monkey dot org>
     Dustin Spicuzza               <dustin at virtualroadside dot com>
@@ -50,8 +70,12 @@
     Edward Sheldrake              <ejs1920 at sourceforge dot net>
     Eric Anderson                 <anderse at hpl dot hp dot com>
     Erik de Castro Lopo           <erik dot de dot castro dot lopo at sensorynetworks dot com>
+    Fedor Sakharov                <fedor dot sakharov at gmail dot com>
+    Felix Janda                   <felix dot janda at posteo dot de>
     Felix Obenhuber               <felix at obenhuber dot de>
     Florent Drouin                <Florent dot Drouin at alcatel-lucent dot fr>
+    Florian Fainelli              <f dot fainelli at gmail dot com>
+    François Revol                <revol at free dot fr>
     Franz Schaefer                <schaefer at mond dot at>
     frederich                     <frederich at sourceforge dot net>
     Fulko Hew                     <fulko dot hew at gmail dot com>
@@ -59,6 +83,7 @@
     Gabor Tatarka                 <gabor dot tatarka at ericsson dot com>
     Garrett Cooper                <yaberauneya at sourceforge dot net>
     George Neville-Neil           <gnn at freebsd dot org>
+    Gerald Combs                  <gerald at zing dot org>
     Gerard Garcia                 <nouboh at gmail dot com>
     Gianluca Varenni              <gianluca dot varenni at gmail dot com>
     Gilbert Hoyek                 <gil_hoyek at hotmail dot com>
@@ -71,47 +96,64 @@
     Gustavo Zacarias              <gustavo at zacarias dot com dot ar>
     Hagen Paul Pfeifer            <hagen at jauu dot net>
     Henri Doreau                  <hdoreau at sourceforge dot net>
+    Hiroaki KAWAI                 <kawai at stratosphere dot co dot jp>
     Hyung Sik Yoon                <hsyn at kr dot ibm dot com>
     Igor Khristophorov            <igor at atdot dot org>
+    Jakub Sitnicki                <jsitnicki at gmail dot com>
     Jakub Zawadzki                <darkjames at darkjames dot pl>
+    James Ko                      <jck at exegin dot com>
     Jan-Philip Velders            <jpv at veldersjes dot net>
     Jason R. Thorpe               <thorpej at netbsd dot org>
     Javier Achirica               <achirica at ttd dot net>
     Jean-Louis Charton            <Jean-Louis dot CHARTON at oikialog dot com>
     Jean Tourrilhes               <jt at hpl dot hp dot com>
     Jefferson Ogata               <jogata at nodc dot noaa dot gov>
+    Jerome Duval                  <jerome dot duval at gmail dot com>
     Jesper Dangaard Brouer        <hawk at comx dot dk>
     Jesper Peterson               <jesper at endace dot com>
     Jesse Gross                   <jesse at nicira dot com>
+    JHA                           <jon dot anderson at oracle dot com>
+    jingyu yang                   <jingleyang at users dot noreply dot github dot com>
     Jiri Slaby                    <jirislaby at gmail dot com>
+    João Valverde                 <joao dot valverde at tecnico dot ulisboa dot pt>
     Joerg Mayer                   <jmayer at loplof dot de>
     John Bankier                  <jbankier at rainfinity dot com>
     Jon Lindgren                  <jonl at yubyub dot net>
     Jon Smirl                     <jonsmirl at gmail dot com>
     Jorge Boncompte [DTI2]        <jorge at dti2 dot net>
+    jromanr                       <jromanr at hotmail dot com>
     Juergen Schoenwaelder         <schoenw at ibr dot cs dot tu-bs dot de>
     Julien Moutinho               <julm at savines dot alpes dot fr dot eu dot org>
     Jung-uk Kim                   <jkim at FreeBSD dot org>
     Kazushi Sugyo                 <sugyo at pb dot jp dot nec dot com>
+    Kevin Boulain                 <kevin dot boulain at securactive dot net>
     Klaus Klein                   <kleink at netbsd dot org>
     Koryn Grant                   <koryn at endace dot com>
     Kris Katterjohn               <katterjohn at gmail dot com>
     Krzysztof Halasa              <khc at pm dot waw dot pl>
     Lennert Buytenhek             <buytenh at wantstofly dot org>
+    lixiaoyan                     <lixiaoyan at google dot com>
     Lorenzo Cavallaro             <sullivan at sikurezza dot org>
     Loris Degioanni               <loris at netgroup-serv dot polito dot it>
     Love Hörnquist-Åstrand        <lha at stacken dot kth dot se>
     Luis MartinGarcia             <luis dot mgarc at gmail dot com>
+    lxy                           <391861737 at qq dot com>
     Maciej W. Rozycki             <macro at ds2 dot pg dot gda dot pl>
     Mansour Behabadi              <mansour at oxplot dot com>
     Marcus Felipe Pereira         <marcus at task dot com dot br>
+    Mario J. Rugiero              <mrugiero at gmail dot com>
     Mark C. Brown                 <mbrown at hp dot com>
     Mark Johnston                 <markjdb at gmail dot com>
+    Mark Marshall                 <mark dot marshall at omicronenergy dot com>
     Mark Pizzolato                <List-tcpdump-workers at subscriptions dot pizzolato dot net>
     Markus Mayer                  <markus_mayer at sourceforge dot net>
     Martin Husemann               <martin at netbsd dot org>
     Márton Németh                 <nm127 at freemail dot hu>
+    Matt Eaton                    <agnosticdev at gmail dot com>
     Matthew Luckie                <mjl at luckie dot org dot nz>
+    Matthias Hannig               <matthias at hannig dot cc>
+    Matwey V. Kornilov            <matwey dot kornilov at gmail dot com>
+    maxice8                       <thinkabit dot ukim at gmail dot com>
     Max Laier                     <max at love2party dot net>
     Michal Kubecek                <mkubecek at suse dot cz>
     Michal Labedzki               <michal dot labedzki at tieto dot com>
@@ -119,25 +161,36 @@
     Mike Frysinger                <vapier at gmail dot com>
     Mike Kershaw                  <dragorn at kismetwireless dot net>
     Mike Wiacek                   <mike at iroot dot net>
+    Milosz Kaniewski              <milosz dot kaniewski at gmail dot com>
     Miroslav Lichvar              <mlichvar at redhat dot com>
     Monroe Williams               <monroe at pobox dot com>
+    Myricom Help                  <myri at users dot noreply dot github dot com>
+    Nan Xiao                      <nan at chinadtrace dot org>
+    Nick Kelsey                   <nickk at silicondust dot com>
     Nicolas Dade                  <ndade at nsd dot dyndns dot org>
     Niko Delarich                 <niko dot delarich at gmail dot com>
     N. Leiten                     <nleiten at sourceforge dot net>
+    nnposter                      <nnposter at users dot noreply dot github dot com>
                                   <nvercamm at sourceforge dot net>
     Octavian Cerna                <tavy at ylabs dot com>
     Olaf Kirch                    <okir at caldera dot de>
     Ollie Wild                    <aaw at users dot sourceforge dot net>
+    OndÅ™ej Hošek                  <ondra dot hosek at gmail dot com>
     Onno van der Linden           <onno at simplex dot nl>
-    Paolo Abeni                   <paolo dot abeni at email dot it> and redhat dot com
+    Orgad Shaneh                  <orgad dot shaneh at audiocodes dot com>
+    Ørjan Malde                   <red at foxi dot me>
+    Paolo Abeni                   <pabeni at redhat dot com>
     Patrick Marie                 <mycroft at virgaria dot org>
     Patrick McHardy               <kaber at trash not net>
     Paul Mundt                    <lethal at linux-sh dot org>
     Pavel Kankovsky               <kan at dcit dot cz>
+    Pawel Brzezinski              <pawel dot brzezinski at harman dot com>
     Pawel Pokrywka                <publicpp at gmail dot com>
     Peter Fales                   <peter at fales-lorenz dot net>
     Peter Jeremy                  <peter dot jeremy at alcatel dot com dot au>
     Peter Volkov                  <pva at gentoo dot org>
+    Petr Vorel                    <pvorel at suse dot cz>
+    Philippe Antoine              <contact at catenacyber dot fr>
     Phil Wood                     <cpw at lanl dot gov>
     Rafal Maszkowski              <rzm at icm dot edu dot pl>
                                   <rcb-isis at users dot sourceforge dot net>
@@ -145,9 +198,9 @@
     Rick Jones                    <raj at cup dot hp dot com>
     Robert Edmonds                <stu-42 at sourceforge dot net>
     Roberto Mariani               <jelot-tcpdump at jelot dot it>
-    Rongxi Li                     <rongxi dot li at chaitin dot com>
     Roland Dreier                 <roland at purestorage dot com>
     Romain Francoise              <rfrancoise at debian dot org>
+    Rongxi Li                     <rongxi dot li at chaitin dot com>
     Sagun Shakya                  <sagun dot shakya at sun dot com>
     Scott Barron                  <sb125499 at ohiou dot edu>
     Scott Gifford                 <sgifford at tir dot com>
@@ -156,22 +209,37 @@
     Sebastien Roy                 <Sebastien dot Roy at Sun dot COM>
     Sepherosa Ziehau              <sepherosa at gmail dot com>
     Shaun Clowes                  <delius at progsoc dot uts dot edu dot au>
+    solofox                       <wensg100 at sina dot com>
     Solomon Peachy                <pizza at shaftnet dot org>
     Stefan Hudson                 <hudson at mbay dot net>
     Stephen Donnelly              <stephen at endace dot com>
+    Steve Karg                    <skarg at users dot sourceforge dot net>
+    stubbfel                      <stubbfel at gmail dot com>
     Takashi Yamamoto              <yamt at mwd dot biglobe dot ne dot jp>
     Tanaka Shin-ya                <zstanaka at archer dot livedoor dot com>
+    Thomas Habets                 <habets at google dot com>
+    Thomas Petazzoni              <thomas dot petazzoni at free-electrons dot com>
     Tobias Poschwatta             <posch at sourceforge dot net>
+    Tomasz Moń                    <desowin at gmail dot com>
+    Tommy Beadle                  <tbeadle at arbor dot net>
     Tony Li                       <tli at procket dot com>
     Torsten Landschoff            <torsten at debian dot org>
+    Tymoteusz Blazejczyk          <tymoteusz dot blazejczyk at intel dot com>
     Uns Lider                     <unslider at miranda dot org>
     Uwe Girlich                   <Uwe dot Girlich at philosys dot de>
+    Vitaly Lavrov                 <vel21ripn at gmail dot com>
+    Vivien Didelot                <vivien dot didelot at gmail dot com>
+    Vladimir Gladkov              <vovkos at gmail dot com>
+    Vladimir Marek                <vlmarek at volny dot cz>
+    Walter Schell                 <walterschell at users dot noreply dot github dot com>
     Wesley Shields                <wxs at FreeBSD dot org>
     Xianjie Zhang                 <xzhang at cup dot hp dot com>
     Xin Li                        <delphij at FreeBSD dot org>
     Xue Jiang Qing                <xuejianqing at star-net dot cn>
+    Yang Luo                      <hsluoyz at qq dot com>
     Yen Yen Lim
     Yoann Vandoorselaere          <yoann at prelude-ids dot org>
+    Yogesh Prasad                 <yogesh dot prasad at rockwellcollins dot com>
     Yvan Vanhullebus              <vanhu at sourceforge dot net>
 
 The original LBL crew:
diff --git a/INSTALL.md b/INSTALL.md
index 96c87a2..ba8b8f9 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -41,8 +41,8 @@
 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/.
+https://ftp.gnu.org/gnu/bison/ and the current version of Berkeley YACC
+can be found at https://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.
@@ -188,7 +188,7 @@
 release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS
 V1.0 or V1.1 compiler. But note that in some releases of SINIX, yacc
 emits incorrect code; if grammar.y fails to compile, change every
-occurence of:
+occurrence of:
 
 	#ifdef YYDEBUG
 
@@ -206,7 +206,7 @@
 network traffic.  SCO do not appear to provide tcpdump binaries for
 OpenServer 5 or OpenServer 6 as part of SCO Skunkware:
 
-	http://www.sco.com/skunkware/
+  http://www.sco.com/skunkware/
 
 If you use UnixWare, you might be able to build libpcap from this
 release, or you might not.  We do not have a machine running UnixWare,
@@ -221,7 +221,7 @@
 higher is recommended (1.14 is known to cause problems 1.16 is known to
 work). Either pick up a current version from:
 
-	http://ftp.gnu.org/gnu/bison/
+  https://ftp.gnu.org/gnu/bison/
 
 or hack around it by inserting the lines:
 
@@ -248,106 +248,104 @@
 
 FILES
 -----
-CHANGES		- description of differences between releases
-ChmodBPF/*	- macOS startup item to set ownership and permissions
-		  on /dev/bpf*
-CMakeLists.txt	- CMake file
-CONTRIBUTING	- guidelines for contributing
-CREDITS		- people that have helped libpcap along
-INSTALL.md	- this file
-LICENSE		- the license under which tcpdump is distributed
-Makefile.in	- compilation rules (input to the configure script)
-README.md	- description of distribution
-doc/README.aix	- notes on using libpcap on AIX
-doc/README.dag	- notes on using libpcap to capture on Endace DAG devices
-doc/README.hpux	- notes on using libpcap on HP-UX
-doc/README.linux.md - notes on using libpcap on Linux
-doc/README.macos	- notes on using libpcap on macOS
-doc/README.septel   - notes on using libpcap to capture on Intel/Septel devices
-doc/README.sita	- notes on using libpcap to capture on SITA devices
-doc/README.tru64	- notes on using libpcap on Digital/Tru64 UNIX
-doc/README.Win32	- notes on using libpcap on Win32 systems (with WinPcap)
-VERSION		- version of this release
-acconfig.h	- support for post-2.13 autoconf
-aclocal.m4	- autoconf macros
-arcnet.h	- ARCNET definitions
-atmuni31.h	- ATM Q.2931 definitions
-bpf/net		- copy of bpf_filter.c
-bpf_dump.c	- BPF program printing routines
-bpf_filter.c	- symlink to bpf/net/bpf_filter.c
-bpf_image.c	- BPF disassembly routine
-config.guess	- autoconf support
-config.h.in	- autoconf input
-config.sub	- autoconf support
-configure	- configure script (run this first)
-configure.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
-ethertype.h	- Ethernet protocol types and names definitions
-fad-getad.c	- pcap_findalldevs() for systems with getifaddrs()
-fad-gifc.c	- pcap_findalldevs() for systems with only SIOCGIFLIST
-fad-glifc.c	- pcap_findalldevs() for systems with SIOCGLIFCONF
-filtertest.c	- test program for BPF compiler
-findalldevstest.c - test program for pcap_findalldevs()
-gencode.c	- BPF code generation routines
-gencode.h	- BPF code generation definitions
-grammar.y	- filter string grammar
-ieee80211.h	- 802.11 definitions
-install-sh	- BSD style install script
-lbl/os-*.h	- OS-dependent defines and prototypes
-llc.h		- 802.2 LLC SAP definitions
-missing/*	- replacements for missing library functions
-mkdep		- construct Makefile dependency list
-msdos/*		- drivers for MS-DOS capture support
-nametoaddr.c	- hostname to address routines
-nlpid.h		- OSI network layer protocol identifier definitions
-net		- symlink to bpf/net
-optimize.c	- BPF optimization routines
-pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
-pcap/bpf.h	- BPF definitions
-pcap/namedb.h	- public libpcap name database definitions
-pcap/pcap.h	- public libpcap definitions
-pcap/sll.h	- public definition of DLT_LINUX_SLL header
-pcap/usb.h	- public definition of DLT_USB header
-pcap-bpf.c	- BSD Packet Filter support
-pcap-bpf.h	- header for backwards compatibility
-pcap-bt-linux.c	- Bluetooth capture support for Linux
-pcap-bt-linux.h	- Bluetooth capture support for Linux
-pcap-dag.c	- Endace DAG device capture support
-pcap-dag.h	- Endace DAG device capture support
-pcap-dlpi.c	- Data Link Provider Interface support
-pcap-dos.c	- MS-DOS capture support
-pcap-dos.h	- headers for MS-DOS capture support
-pcap-enet.c	- enet support
-pcap-int.h	- internal libpcap definitions
-pcap-libdlpi.c	- Data Link Provider Interface support for systems with libdlpi
-pcap-linux.c	- Linux packet socket support
-pcap-namedb.h	- header for backwards compatibility
-pcap-nit.c	- SunOS Network Interface Tap support
-pcap-nit.h	- SunOS Network Interface Tap definitions
-pcap-npf.c	- WinPcap capture support
-pcap-null.c	- dummy monitor support (allows offline use of libpcap)
-pcap-pf.c	- Ultrix and Digital/Tru64 UNIX Packet Filter support
-pcap-pf.h	- Ultrix and Digital/Tru64 UNIX Packet Filter definitions
-pcap-septel.c   - Intel/Septel device capture support
-pcap-septel.h   - Intel/Septel device capture support
-pcap-sita.c	- SITA device capture support
-pcap-sita.h	- SITA device capture support
-pcap-sita.html	- SITA device capture documentation
-pcap-stdinc.h	- includes and #defines for compiling on Win32 systems
-pcap-snit.c	- SunOS 4.x STREAMS-based Network Interface Tap support
-pcap-snoop.c	- IRIX Snoop network monitoring support
-pcap-usb-linux.c - USB capture support for Linux
-pcap-usb-linux.h - USB capture support for Linux
-pcap.3pcap	- manual entry for the library
-pcap.c		- pcap utility routines
-pcap.h		- header for backwards compatibility
-pcap_*.3pcap	- manual entries for library functions
-pcap-filter.4	- manual entry for filter syntax
-pcap-linktype.4	- manual entry for link-layer header types
-ppp.h		- Point to Point Protocol definitions
-savefile.c	- offline support
-scanner.l	- filter string scanner
-sunatmpos.h	- definitions for SunATM capturing
-Win32		- headers and routines for building on Win32 systems
+	CHANGES		    - description of differences between releases
+	ChmodBPF/*	    - macOS startup item to set ownership and permissions on /dev/bpf*
+	CMakeLists.txt	    - CMake file
+	CONTRIBUTING.md	    - guidelines for contributing
+	CREDITS		    - people that have helped libpcap along
+	INSTALL.md	    - this file
+	LICENSE		    - the license under which tcpdump is distributed
+	Makefile.in	    - compilation rules (input to the configure script)
+	README.md	    - description of distribution
+	doc/README.aix	    - notes on using libpcap on AIX
+	doc/README.dag	    - notes on using libpcap to capture on Endace DAG devices
+	doc/README.hpux	    - notes on using libpcap on HP-UX
+	doc/README.linux.md - notes on using libpcap on Linux
+	doc/README.macos    - notes on using libpcap on macOS
+	doc/README.septel   - notes on using libpcap to capture on Intel/Septel devices
+	doc/README.sita	    - notes on using libpcap to capture on SITA devices
+	doc/README.tru64    - notes on using libpcap on Digital/Tru64 UNIX
+	doc/README.Win32.md - notes on using libpcap on Win32 systems (with Npcap)
+	VERSION		    - version of this release
+	acconfig.h	    - support for post-2.13 autoconf
+	aclocal.m4	    - autoconf macros
+	arcnet.h	    - ARCNET definitions
+	atmuni31.h	    - ATM Q.2931 definitions
+	bpf_dump.c	    - BPF program printing routines
+	bpf_filter.c	    - BPF filtering routines
+	bpf_image.c	    - BPF disassembly routine
+	config.guess	    - autoconf support
+	config.h.in	    - autoconf input
+	config.sub	    - autoconf support
+	configure	    - configure script (run this first)
+	configure.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
+	ethertype.h	    - Ethernet protocol types and names definitions
+	fad-getad.c	    - pcap_findalldevs() for systems with getifaddrs()
+	fad-gifc.c	    - pcap_findalldevs() for systems with only SIOCGIFLIST
+	fad-glifc.c	    - pcap_findalldevs() for systems with SIOCGLIFCONF
+	filtertest.c	    - test program for BPF compiler
+	findalldevstest.c   - test program for pcap_findalldevs()
+	gencode.c	    - BPF code generation routines
+	gencode.h	    - BPF code generation definitions
+	grammar.y	    - filter string grammar
+	ieee80211.h	    - 802.11 definitions
+	install-sh	    - BSD style install script
+	lbl/os-*.h	    - OS-dependent defines and prototypes
+	llc.h		    - 802.2 LLC SAP definitions
+	missing/*	    - replacements for missing library functions
+	mkdep		    - construct Makefile dependency list
+	msdos/*		    - drivers for MS-DOS capture support
+	nametoaddr.c	    - hostname to address routines
+	nlpid.h		    - OSI network layer protocol identifier definitions
+	net		    - symlink to bpf/net
+	optimize.c	    - BPF optimization routines
+	pcap/bluetooth.h    - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
+	pcap/bpf.h	    - BPF definitions
+	pcap/namedb.h	    - public libpcap name database definitions
+	pcap/pcap.h	    - public libpcap definitions
+	pcap/sll.h	    - public definitions of DLT_LINUX_SLL and DLT_LINUX_SLL2 headers
+	pcap/usb.h	    - public definition of DLT_USB header
+	pcap-bpf.c	    - BSD Packet Filter support
+	pcap-bpf.h	    - header for backwards compatibility
+	pcap-bt-linux.c	    - Bluetooth capture support for Linux
+	pcap-bt-linux.h	    - Bluetooth capture support for Linux
+	pcap-dag.c	    - Endace DAG device capture support
+	pcap-dag.h	    - Endace DAG device capture support
+	pcap-dlpi.c	    - Data Link Provider Interface support
+	pcap-dos.c	    - MS-DOS capture support
+	pcap-dos.h	    - headers for MS-DOS capture support
+	pcap-enet.c	    - enet support
+	pcap-int.h	    - internal libpcap definitions
+	pcap-libdlpi.c	    - Data Link Provider Interface support for systems with libdlpi
+	pcap-linux.c	    - Linux packet socket support
+	pcap-namedb.h	    - header for backwards compatibility
+	pcap-nit.c	    - SunOS Network Interface Tap support
+	pcap-nit.h	    - SunOS Network Interface Tap definitions
+	pcap-npf.c	    - Npcap capture support
+	pcap-null.c	    - dummy monitor support (allows offline use of libpcap)
+	pcap-pf.c	    - Ultrix and Digital/Tru64 UNIX Packet Filter support
+	pcap-pf.h	    - Ultrix and Digital/Tru64 UNIX Packet Filter definitions
+	pcap-septel.c       - Intel/Septel device capture support
+	pcap-septel.h       - Intel/Septel device capture support
+	pcap-sita.c	    - SITA device capture support
+	pcap-sita.h	    - SITA device capture support
+	pcap-sita.html	    - SITA device capture documentation
+	pcap-stdinc.h	    - includes and #defines for compiling on Win32 systems
+	pcap-snit.c	    - SunOS 4.x STREAMS-based Network Interface Tap support
+	pcap-snoop.c	    - IRIX Snoop network monitoring support
+	pcap-usb-linux.c    - USB capture support for Linux
+	pcap-usb-linux.h    - USB capture support for Linux
+	pcap.3pcap	    - manual entry for the library
+	pcap.c		    - pcap utility routines
+	pcap.h		    - header for backwards compatibility
+	pcap_*.3pcap	    - manual entries for library functions
+	pcap-filter.4	    - manual entry for filter syntax
+	pcap-linktype.4	    - manual entry for link-layer header types
+	ppp.h		    - Point to Point Protocol definitions
+	savefile.c	    - offline support
+	scanner.l	    - filter string scanner
+	sunatmpos.h	    - definitions for SunATM capturing
+	Win32		    - headers and routines for building on Win32 systems
diff --git a/METADATA b/METADATA
index 36f21c3..5b6bbae 100644
--- a/METADATA
+++ b/METADATA
@@ -7,12 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://github.com/the-tcpdump-group/libpcap/archive/libpcap-1.9.0.tar.gz"
+    value: "https://github.com/the-tcpdump-group/libpcap/archive/libpcap-1.10.0.tar.gz"
   }
-  version: "libcap-1.9.0"
+  version: "libpcap-1.10.0"
+  license_type: NOTICE
   last_upgrade_date {
-    year: 2018
-    month: 7
-    day: 22
+    year: 2021
+    month: 1
+    day: 5
   }
 }
diff --git a/Makefile.in b/Makefile.in
index dff75ec..d8b8507 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -38,6 +38,7 @@
 
 # VPATH
 srcdir = @srcdir@
+top_srcdir = @top_srcdir@
 VPATH = @srcdir@
 
 #
@@ -69,7 +70,8 @@
 EXTRA_NETWORK_LIBS=@EXTRA_NETWORK_LIBS@
 
 # Standard CFLAGS for building members of a shared library
-FULL_CFLAGS = $(CCOPT) $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+FULL_CFLAGS = $(CCOPT) @V_LIB_CCOPT_FAT@ $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+CXXFLAGS = $(CCOPT) @V_LIB_CCOPT_FAT@ $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
 
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -86,21 +88,29 @@
 	@rm -f $@
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
 
-PSRC =	pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@ @NETMAP_SRC@ @RDMA_SRC@
-FSRC =  @V_FINDALLDEVS@
-SSRC =  @SSRC@
-CSRC =	pcap.c gencode.c optimize.c nametoaddr.c etherent.c \
-	fmtutils.c \
-	savefile.c sf-pcap.c sf-pcapng.c pcap-common.c \
-	bpf_image.c bpf_filter.c bpf_dump.c
-GENSRC = scanner.c grammar.c
+PLATFORM_C_SRC =	@PLATFORM_C_SRC@
+PLATFORM_CXX_SRC =	@PLATFORM_CXX_SRC@
+MODULE_C_SRC =		@MODULE_C_SRC@
+REMOTE_C_SRC =		@REMOTE_C_SRC@
+COMMON_C_SRC =	pcap.c gencode.c optimize.c nametoaddr.c etherent.c \
+		fmtutils.c \
+		savefile.c sf-pcap.c sf-pcapng.c pcap-common.c \
+		bpf_image.c bpf_filter.c bpf_dump.c
+GENERATED_C_SRC = scanner.c grammar.c
 LIBOBJS = @LIBOBJS@
 
-SRC =	$(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
+SRC =	$(PLATFORM_C_SRC) $(PLATFORM_CXX_SRC) \
+	$(MODULE_C_SRC) $(REMOTE_C_SRC) $(COMMON_C_SRC) \
+	$(GENERATED_C_SRC)
 
 # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
-# hack the extra indirection
-OBJ =	$(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
+# hack the extra indirection, and we have to handle PLATFORM_CXX_SRC
+# differently from the defines for C source
+OBJ =	$(PLATFORM_C_SRC:.c=.o) $(PLATFORM_CXX_SRC:.cpp=.o) \
+	$(MODULE_C_SRC:.c=.o) $(REMOTE_C_SRC:.c=.o) $(COMMON_C_SRC:.c=.o) \
+	$(GENERATED_C_SRC:.c=.o) \
+	$(LIBOBJS)
+
 PUBHDR = \
 	pcap.h \
 	pcap-bpf.h \
@@ -117,6 +127,7 @@
 	pcap/nflog.h \
 	pcap/pcap.h \
 	pcap/sll.h \
+	pcap/socket.h \
 	pcap/vlan.h \
 	pcap/usb.h
 
@@ -153,7 +164,7 @@
 	$(SRC) $(HDR)
 
 CLEANFILES = $(OBJ) libpcap.a libpcap.so.`cat $(srcdir)/VERSION` \
-	$(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
+	$(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENERATED_C_SRC) $(GENHDR) \
 	lex.yy.c pcap-config libpcap.pc
 
 MAN1 = pcap-config.1
@@ -168,6 +179,7 @@
 	pcap_list_tstamp_types.3pcap.in \
 	pcap_open_dead.3pcap.in \
 	pcap_open_offline.3pcap.in \
+	pcap_set_immediate_mode.3pcap.in \
 	pcap_set_tstamp_precision.3pcap.in \
 	pcap_set_tstamp_type.3pcap.in
 
@@ -191,6 +203,7 @@
 	pcap_get_required_select_timeout.3pcap \
 	pcap_get_selectable_fd.3pcap \
 	pcap_geterr.3pcap \
+	pcap_init.3pcap \
 	pcap_inject.3pcap \
 	pcap_is_swapped.3pcap \
 	pcap_lib_version.3pcap \
@@ -203,7 +216,6 @@
 	pcap_open_live.3pcap \
 	pcap_set_buffer_size.3pcap \
 	pcap_set_datalink.3pcap \
-	pcap_set_immediate_mode.3pcap \
 	pcap_set_promisc.3pcap \
 	pcap_set_protocol_linux.3pcap \
 	pcap_set_rfmon.3pcap \
@@ -245,10 +257,13 @@
 	TODO \
 	VERSION \
 	aclocal.m4 \
+	charconv.c \
+	charconv.h \
 	chmod_bpf \
 	cmake_uninstall.cmake.in \
 	cmakeconfig.h.in \
 	cmake/Modules/FindDAG.cmake \
+	cmake/Modules/Finddpdk.cmake \
 	cmake/Modules/FindFseeko.cmake \
 	cmake/Modules/FindLFS.cmake \
 	cmake/Modules/FindPacket.cmake \
@@ -265,7 +280,7 @@
 	fad-getad.c \
 	fad-gifc.c \
 	fad-glifc.c \
-	grammar.y \
+	grammar.y.in \
 	install-sh \
 	lbl/os-aix4.h \
 	lbl/os-aix7.h \
@@ -276,11 +291,13 @@
 	lbl/os-sunos4.h \
 	lbl/os-ultrix4.h \
 	libpcap.pc.in \
+	missing/asprintf.c \
 	missing/getopt.c \
 	missing/getopt.h \
-	missing/snprintf.c \
+	missing/strlcat.c \
+	missing/strlcpy.c \
 	missing/strtok_r.c \
-	missing/win_snprintf.c \
+	missing/win_asprintf.c \
 	mkdep \
 	msdos/bin2c.c \
 	msdos/makefile \
@@ -293,6 +310,8 @@
 	msdos/readme.dos \
 	nomkdep \
 	org.tcpdump.chmod_bpf.plist \
+	pcap-airpcap.c \
+	pcap-airpcap.h \
 	pcap-bpf.c \
 	pcap-bt-linux.c \
 	pcap-bt-linux.h \
@@ -307,7 +326,10 @@
 	pcap-dlpi.c \
 	pcap-dos.c \
 	pcap-dos.h \
+	pcap-dpdk.c \
+	pcap-dpdk.h \
 	pcap-enet.c \
+	pcap-haiku.cpp \
 	pcap-int.h \
 	pcap-libdlpi.c \
 	pcap-linux.c \
@@ -347,12 +369,13 @@
 	rpcapd/fileconf.c \
 	rpcapd/fileconf.h \
 	rpcapd/log.h \
-	rpcapd/log-stderr.c \
+	rpcapd/log.c \
 	rpcapd/org.tcpdump.rpcapd.plist \
 	rpcapd/rpcapd.c \
 	rpcapd/rpcapd.h \
 	rpcapd/rpcapd.inetd.conf \
 	rpcapd/rpcapd.manadmin.in \
+	rpcapd/rpcapd-config.manfile.in \
 	rpcapd/rpcapd.rc \
 	rpcapd/rpcapd.socket \
 	rpcapd/rpcapd.xinetd.conf \
@@ -361,6 +384,8 @@
 	rpcapd/win32-svc.h \
 	sockutils.c \
 	sockutils.h \
+	sslutils.c \
+	sslutils.h \
 	scanner.l \
 	testprogs/CMakeLists.txt \
 	testprogs/Makefile.in \
@@ -368,12 +393,23 @@
 	testprogs/capturetest.c \
 	testprogs/filtertest.c \
 	testprogs/findalldevstest.c \
+	testprogs/findalldevstest-perf.c \
+	testprogs/fuzz/CMakeLists.txt \
+	testprogs/fuzz/fuzz_both.c \
+	testprogs/fuzz/fuzz_both.options \
+	testprogs/fuzz/fuzz_filter.c \
+	testprogs/fuzz/fuzz_filter.options \
+	testprogs/fuzz/fuzz_pcap.c \
+	testprogs/fuzz/fuzz_pcap.options \
+	testprogs/fuzz/onefile.c \
 	testprogs/opentest.c \
 	testprogs/reactivatetest.c \
 	testprogs/selpolltest.c \
 	testprogs/threadsignaltest.c \
 	testprogs/unix.h \
 	testprogs/valgrindtest.c \
+	testprogs/visopts.py \
+	testprogs/writecaptest.c \
 	tests/shb-option-too-long.pcapng \
 	Win32/Prj/wpcap.sln \
 	Win32/Prj/wpcap.vcxproj \
@@ -417,7 +453,7 @@
 	MAJOR_VER=A; \
 	COMPAT_VER=1; \
 	CURRENT_VER=`sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`; \
-	$(CC) -dynamiclib -undefined error $(LDFLAGS) \
+	$(CC) -dynamiclib -undefined error $(LDFLAGS) @V_LIB_LDFLAGS_FAT@ \
 	    -o libpcap.$$VER.dylib $(OBJ) $(ADDLOBJS) $(LIBS) \
 	    -install_name $(libdir)/libpcap.$$MAJOR_VER.dylib \
 	    -compatibility_version $$COMPAT_VER \
@@ -474,7 +510,26 @@
 scanner.o: scanner.c grammar.h
 	$(CC) $(FULL_CFLAGS) -c scanner.c
 
-grammar.c: $(srcdir)/grammar.y
+#
+# Generate the grammar.y file.
+#
+# Some Makes, e.g. AIX Make and Solaris Make, can't handle "--file=$@.tmp:$<";
+# for example, the Solaris 9 make man page says
+#
+#	Because make assigns $< and $* as it would for implicit rules
+#	(according to the suffixes list and the directory contents),
+#	they may be unreliable when used within explicit target entries.
+#
+# and this is an explicit target entry.
+#
+# Therefore, instead of using $<, we explicitly put in $(srcdir)/libpcap.pc.in.
+#
+grammar.y: $(srcdir)/grammar.y.in ./config.status
+	@rm -f $@ $@.tmp
+	./config.status --file=$@.tmp:$(srcdir)/grammar.y.in
+	mv $@.tmp $@
+
+grammar.c: grammar.y
 	$(YACC) -p pcap_ -o grammar.c -d $<
 grammar.h: grammar.c
 ## Recover from the removal of $@
@@ -489,9 +544,18 @@
 gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
 
+asprintf.o: $(srcdir)/missing/asprintf.c
+	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
+
 snprintf.o: $(srcdir)/missing/snprintf.c
 	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
 
+strlcat.o: $(srcdir)/missing/strlcat.c
+	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcat.c
+
+strlcpy.o: $(srcdir)/missing/strlcpy.c
+	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcpy.c
+
 strtok_r.o: $(srcdir)/missing/strtok_r.c
 	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
 
@@ -513,7 +577,6 @@
 	@rm -f $@ $@.tmp
 	./config.status --file=$@.tmp:$(srcdir)/libpcap.pc.in
 	mv $@.tmp $@
-	chmod a+x $@
 
 #
 # Generate the pcap-config script.  See above.
@@ -575,6 +638,9 @@
 	rm -f pcap_datalink_val_to_description.3pcap && \
 	$(LN_S) pcap_datalink_val_to_name.3pcap \
 		 pcap_datalink_val_to_description.3pcap && \
+	rm -f pcap_datalink_val_to_description_or_dlt.3pcap && \
+	$(LN_S) pcap_datalink_val_to_name.3pcap \
+		 pcap_datalink_val_to_description_or_dlt.3pcap && \
 	rm -f pcap_dump_fopen.3pcap && \
 	$(LN_S) pcap_dump_open.3pcap pcap_dump_fopen.3pcap && \
 	rm -f pcap_freealldevs.3pcap && \
@@ -677,6 +743,7 @@
 	for i in $(MAN3PCAP); do \
 		rm -f $(DESTDIR)$(mandir)/man3/$$i; done
 	rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+	rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description_or_dlt.3pcap
 	rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
 	rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
 	rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
@@ -727,7 +794,7 @@
 	cd testprogs; $(MAKE) clean
 
 distclean: clean
-	rm -f Makefile config.cache config.log config.status \
+	rm -f Makefile grammar.y config.cache config.log config.status \
 	    config.h gnuc.h net os-proto.h libpcap.pc \
 	    pcap-config stamp-h stamp-h.in
 	rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
@@ -742,15 +809,23 @@
 	ctags -wtd $(TAGFILES)
 
 releasetar:
-	@cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
+	@autoreconf -f; \
+	name=$(PROG)-`cat VERSION` ; \
 	   mkdir $$name; \
-	   tar -c --exclude='*~' -f - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
-	      $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
+	   tar -c --exclude='*~' -f - $(COMMON_C_SRC) $(HDR) $(MAN1) \
+	      $(MAN3PCAP_EXPAND) $(MAN3PCAP_NOEXPAND) $(MANFILE) \
+	      $(MANMISC) $(EXTRA_DIST) | \
 	      (cd $$name; tar xf -); \
 	   tar -c -z -f $$name.tar.gz $$name; \
 	   rm -rf $$name
 
-depend:	$(GENSRC) $(GENHDR)
-	$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+rc1 rc2 rc3 rc4 rc5:
+	@VER=`cat $(srcdir)/VERSION`; \
+	sed -i "s/$$VER/$${VER}$@/" VERSION ; \
+	make releasetar; \
+	git checkout VERSION
+
+depend:	$(GENERATED_C_SRC) $(GENHDR)
+	$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
 	cd rpcapd; $(MAKE) depend
 	cd testprogs; $(MAKE) depend
diff --git a/README.md b/README.md
index 78cc3c4..1e3a245 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,31 @@
-To report a security issue please send an e-mail to security@tcpdump.org.
-
-To report bugs and other problems, contribute patches, request a
-feature, provide generic feedback etc please see the file
-[CONTRIBUTING](CONTRIBUTING.md) in the libpcap source tree root.
-
-The directory doc/ has README files about specific operating systems and
-options.
-
 LIBPCAP 1.x.y
-Now maintained by "The Tcpdump Group"
-https://www.tcpdump.org
+=============
 
-Anonymous Git is available via:
-        https://github.com/the-tcpdump-group/libpcap.git
+[![Build Status](https://travis-ci.org/the-tcpdump-group/tcpdump.svg?branch=master)](https://travis-ci.org/the-tcpdump-group/libpcap)
+
+[![Build Status](https://ci.appveyor.com/api/projects/status/github/the-tcpdump-group/tcpdump?branch=master&svg=true)](https://ci.appveyor.com/project/guyharris/libpcap)
+
+Now maintained by "The Tcpdump Group"
+
+  https://www.tcpdump.org
 
 formerly from 	Lawrence Berkeley National Laboratory
 		Network Research Group <libpcap@ee.lbl.gov>
 		ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
 
+To report a security issue please send an e-mail to security@tcpdump.org.
+
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+[CONTRIBUTING.md](CONTRIBUTING.md) in the libpcap source tree root.
+
+The directory doc/ has README files about specific operating systems and
+options.
+
+Anonymous Git is available via:
+
+  https://github.com/the-tcpdump-group/libpcap.git
+
 This directory contains source code for libpcap, a system-independent
 interface for user-level packet capture.  libpcap provides a portable
 framework for low-level network monitoring.  Applications include
@@ -39,19 +47,15 @@
 User-level Packet Capture''.  A compressed PostScript version can be
 found at
 
-	ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z
-
-or
-
-	https://www.tcpdump.org/papers/bpf-usenix93.ps.Z
+  https://www.tcpdump.org/papers/bpf-usenix93.ps.Z
 
 and a gzipped version can be found at
 
-	https://www.tcpdump.org/papers/bpf-usenix93.ps.gz
+  https://www.tcpdump.org/papers/bpf-usenix93.ps.gz
 
 A PDF version can be found at
 
-	https://www.tcpdump.org/papers/bpf-usenix93.pdf
+  https://www.tcpdump.org/papers/bpf-usenix93.pdf
 
 Although most packet capture interfaces support in-kernel filtering,
 libpcap utilizes in-kernel filtering only for the BPF interface.
@@ -68,7 +72,7 @@
 utilizes).  Also, you can add BPF filter support to Ultrix using the
 kernel source and/or object patches available in:
 
-	https://www.tcpdump.org/other/bpfext42.tar.Z
+  https://www.tcpdump.org/other/bpfext42.tar.Z
 
 Linux has a number of BPF based systems, and libpcap does not support
 any of the eBPF mechanisms as yet, although it supports many of the
@@ -87,7 +91,3 @@
 We've been maintaining binary compatibility between libpcap releases for
 quite a while; there's no reason to tie a binary linked with libpcap to
 a particular release of libpcap.
-
-Current versions can be found at https://www.tcpdump.org.
-
- - The TCPdump group
diff --git a/VERSION b/VERSION
index f8e233b..81c871d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.9.0
+1.10.0
diff --git a/Win32/Prj/wpcap.vcxproj.filters b/Win32/Prj/wpcap.vcxproj.filters
index 6e06ccb..879bb05 100644
--- a/Win32/Prj/wpcap.vcxproj.filters
+++ b/Win32/Prj/wpcap.vcxproj.filters
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <ClCompile Include="..\..\bpf_dump.c">
       <Filter>Source Files</Filter>
diff --git a/aclocal.m4 b/aclocal.m4
index ac163d4..786423b 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -271,7 +271,7 @@
 dnl set, and don't add the flag to the first argument if the compile
 dnl fails; this is for warning options cause problems that can't be
 dnl worked around.  If a third argument is supplied, a fourth argument
-dnl should also be supplied; it's a message desribing what the test
+dnl should also be supplied; it's a message describing what the test
 dnl program is checking.
 dnl
 AC_DEFUN(AC_LBL_CHECK_COMPILER_OPT,
@@ -425,14 +425,14 @@
 		if AC_RUN_LOG([eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1"]); then
 			AC_MSG_RESULT([yes, with $ac_lbl_dependency_flag])
 			DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
-			MKDEP='${srcdir}/mkdep'
+			MKDEP='${top_srcdir}/mkdep'
 		else
 			AC_MSG_RESULT([no])
 			#
 			# We can't run mkdep, so have "make depend" do
 			# nothing.
 			#
-			MKDEP='${srcdir}/nomkdep'
+			MKDEP='${top_srcdir}/nomkdep'
 		fi
 		rm -rf conftest*
 	else
@@ -441,7 +441,7 @@
 		# We can't run mkdep, so have "make depend" do
 		# nothing.
 		#
-		MKDEP='${srcdir}/nomkdep'
+		MKDEP='${top_srcdir}/nomkdep'
 	fi
 	AC_SUBST(DEPENDENCY_CFLAG)
 	AC_SUBST(MKDEP)
@@ -484,8 +484,8 @@
 	    aix*)
 		    ;;
 
-	    freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
-	    	    #
+	    freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|haiku*|midipix*)
+		    #
 		    # Platforms where the linker is the GNU linker
 		    # or accepts command-line arguments like
 		    # those the GNU linker accepts.
@@ -501,7 +501,7 @@
 		    sparc64*)
 			case "$host_os" in
 
-			freebsd*|openbsd*)
+			freebsd*|openbsd*|linux*)
 			    PIC_OPT=-fPIC
 			    ;;
 			esac
@@ -514,7 +514,7 @@
 
 	    hpux*)
 		    V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
-	    	    #
+		    #
 		    # XXX - this assumes GCC is using the HP linker,
 		    # rather than the GNU linker, and that the "+h"
 		    # option is used on all HP-UX platforms, both .sl
@@ -522,7 +522,7 @@
 		    #
 		    V_SONAME_OPT="-Wl,+h,"
 		    #
-		    # By default, directories specifed with -L
+		    # By default, directories specified with -L
 		    # are added to the run-time search path, so
 		    # we don't add them in pcap-config.
 		    #
@@ -583,14 +583,14 @@
 		    V_SHLIB_OPT="-b"
 		    V_SONAME_OPT="+h "
 		    #
-		    # By default, directories specifed with -L
+		    # By default, directories specified with -L
 		    # are added to the run-time search path, so
 		    # we don't add them in pcap-config.
 		    #
 		    ;;
 
 	    osf*)
-	    	    #
+		    #
 		    # Presumed to be DEC OSF/1, Digital UNIX, or
 		    # Tru64 UNIX.
 		    #
@@ -753,106 +753,6 @@
     ])
 
 dnl
-dnl Checks to see if unaligned memory accesses fail
-dnl
-dnl usage:
-dnl
-dnl	AC_LBL_UNALIGNED_ACCESS
-dnl
-dnl results:
-dnl
-dnl	LBL_ALIGN (DEFINED)
-dnl
-AC_DEFUN(AC_LBL_UNALIGNED_ACCESS,
-    [AC_MSG_CHECKING(if unaligned accesses fail)
-    AC_CACHE_VAL(ac_cv_lbl_unaligned_fail,
-	[case "$host_cpu" in
-
-	#
-	# These are CPU types where:
-	#
-	#	the CPU faults on an unaligned access, but at least some
-	#	OSes that support that CPU catch the fault and simulate
-	#	the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
-	#	the simulation is slow, so we don't want to use it;
-	#
-	#	the CPU, I infer (from the old
-	#
-	# XXX: should also check that they don't do weird things (like on arm)
-	#
-	#	comment) doesn't fault on unaligned accesses, but doesn't
-	#	do a normal unaligned fetch, either (e.g., presumably, ARM);
-	#
-	#	for whatever reason, the test program doesn't work
-	#	(this has been claimed to be the case for several of those
-	#	CPUs - I don't know what the problem is; the problem
-	#	was reported as "the test program dumps core" for SuperH,
-	#	but that's what the test program is *supposed* to do -
-	#	it dumps core before it writes anything, so the test
-	#	for an empty output file should find an empty output
-	#	file and conclude that unaligned accesses don't work).
-	#
-	# This run-time test won't work if you're cross-compiling, so
-	# in order to support cross-compiling for a particular CPU,
-	# we have to wire in the list of CPU types anyway, as far as
-	# I know, so perhaps we should just have a set of CPUs on
-	# which we know it doesn't work, a set of CPUs on which we
-	# know it does work, and have the script just fail on other
-	# cpu types and update it when such a failure occurs.
-	#
-	alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
-		ac_cv_lbl_unaligned_fail=yes
-		;;
-
-	*)
-		cat >conftest.c <<EOF
-#		include <sys/types.h>
-#		include <sys/wait.h>
-#		include <stdio.h>
-		unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
-		main() {
-		unsigned int i;
-		pid_t pid;
-		int status;
-		/* avoid "core dumped" message */
-		pid = fork();
-		if (pid <  0)
-			exit(2);
-		if (pid > 0) {
-			/* parent */
-			pid = waitpid(pid, &status, 0);
-			if (pid < 0)
-				exit(3);
-			exit(!WIFEXITED(status));
-		}
-		/* child */
-		i = *(unsigned int *)&a[[1]];
-		printf("%d\n", i);
-		exit(0);
-		}
-EOF
-		${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
-		    conftest.c $LIBS >/dev/null 2>&1
-		if test ! -x conftest ; then
-			dnl failed to compile for some reason
-			ac_cv_lbl_unaligned_fail=yes
-		else
-			./conftest >conftest.out
-			if test ! -s conftest.out ; then
-				ac_cv_lbl_unaligned_fail=yes
-			else
-				ac_cv_lbl_unaligned_fail=no
-			fi
-		fi
-		rm -f -r conftest* core core.conftest
-		;;
-	esac])
-    AC_MSG_RESULT($ac_cv_lbl_unaligned_fail)
-    if test $ac_cv_lbl_unaligned_fail = yes ; then
-	    AC_DEFINE(LBL_ALIGN,1,[if unaligned access fails])
-    fi])
-
-dnl
 dnl If the file .devel exists:
 dnl	Add some warning flags if the compiler supports them
 dnl	If an os prototype include exists, symlink os-proto.h to it
@@ -878,22 +778,24 @@
 	    #
 	    if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
 		    AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR()
+		    AC_LBL_CHECK_COMPILER_OPT($1, -W)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wall)
-		    AC_LBL_CHECK_COMPILER_OPT($1, -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)
-		    AC_LBL_CHECK_COMPILER_OPT($1, -Wdocumentation)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wcomma)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wdocumentation)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wformat-nonliteral)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-noreturn)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-prototypes)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-variable-declarations)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wpointer-arith)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wpointer-sign)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wshadow)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wsign-compare)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wstrict-prototypes)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wunused-parameter)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wused-but-marked-unused)
 		    # Warns about safeguards added in case the enums are
 		    # extended
 		    # AC_LBL_CHECK_COMPILER_OPT($1, -Wcovered-switch-default)
-		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-variable-declarations)
-		    AC_LBL_CHECK_COMPILER_OPT($1, -Wunused-parameter)
-		    AC_LBL_CHECK_COMPILER_OPT($1, -Wformat-nonliteral)
 		    #
 		    # This can cause problems with ntohs(), ntohl(),
 		    # htons(), and htonl() on some platforms, such
@@ -929,6 +831,7 @@
 }
 		      ],
 		      [generates warnings from ntohs()])
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wshorten-64-to-32)
 	    fi
 	    AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT()
 	    #
@@ -1055,10 +958,19 @@
 	    LIBS="-lsocket -lnsl $LIBS"
 	],
 	[
-	    #
-	    # We didn't find it.
-	    #
-	    AC_MSG_ERROR([getaddrinfo is required, but wasn't found])
+		AC_CHECK_LIB(network, getaddrinfo,
+		[
+		    #
+		    # OK, we found it in libnetwork on Haiku.
+		    #
+		    LIBS="-lnetwork $LIBS"
+		],
+		[
+		    #
+		    # We didn't find it.
+		    #
+		    AC_MSG_ERROR([getaddrinfo is required, but wasn't found])
+		])
 	], -lnsl)
 
 	#
@@ -1076,3 +988,281 @@
     # DLPI needs putmsg under HPUX so test for -lstr while we're at it
     AC_SEARCH_LIBS(putmsg, str)
 ])
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+dnl pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+dnl serial 11 (pkg-config-0.29)
+dnl
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurrence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes ],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+   	AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+	m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+     	AC_MSG_RESULT([no])
+	m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <https://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+	$3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
diff --git a/atmuni31.h b/atmuni31.h
index 0f85430..7d4f270 100644
--- a/atmuni31.h
+++ b/atmuni31.h
@@ -76,7 +76,7 @@
 #define PROTO_POS       0	/* offset of protocol discriminator */
 #define CALL_REF_POS    2	/* offset of call reference value */
 #define MSG_TYPE_POS    5	/* offset of message type */
-#define MSG_LEN_POS     7	/* offset of mesage length */
+#define MSG_LEN_POS     7	/* offset of message length */
 #define IE_BEGIN_POS    9	/* offset of first information element */
 
 /* format of signalling messages */
diff --git a/bpf_filter.c b/bpf_filter.c
index 615ed3f..22d2558 100644
--- a/bpf_filter.c
+++ b/bpf_filter.c
@@ -44,6 +44,11 @@
 
 #include <pcap/pcap-inttypes.h>
 #include "pcap-types.h"
+#include "extract.h"
+#include "diag-control.h"
+
+#define EXTRACT_SHORT	EXTRACT_BE_U_2
+#define EXTRACT_LONG	EXTRACT_BE_U_4
 
 #ifndef _WIN32
 #include <sys/param.h>
@@ -51,46 +56,10 @@
 #include <sys/time.h>
 #endif /* _WIN32 */
 
-#include <pcap/bpf.h>
+#include <pcap-int.h>
 
 #include <stdlib.h>
 
-#define int32 bpf_int32
-#define u_int32 bpf_u_int32
-
-#ifndef LBL_ALIGN
-/*
- * XXX - IA-64?  If not, this probably won't work on Win64 IA-64
- * systems, unless LBL_ALIGN is defined elsewhere for them.
- * XXX - SuperH?  If not, this probably won't work on WinCE SuperH
- * systems, unless LBL_ALIGN is defined elsewhere for them.
- */
-#if defined(sparc) || defined(__sparc__) || defined(mips) || \
-    defined(ibm032) || defined(__alpha) || defined(__hpux) || \
-    defined(__arm__)
-#define LBL_ALIGN
-#endif
-#endif
-
-#ifndef LBL_ALIGN
-#ifndef _WIN32
-#include <netinet/in.h>
-#endif
-
-#define EXTRACT_SHORT(p)	((u_short)ntohs(*(u_short *)p))
-#define EXTRACT_LONG(p)		(ntohl(*(u_int32 *)p))
-#else
-#define EXTRACT_SHORT(p)\
-	((u_short)\
-		((u_short)*((u_char *)p+0)<<8|\
-		 (u_short)*((u_char *)p+1)<<0))
-#define EXTRACT_LONG(p)\
-		((u_int32)*((u_char *)p+0)<<24|\
-		 (u_int32)*((u_char *)p+1)<<16|\
-		 (u_int32)*((u_char *)p+2)<<8|\
-		 (u_int32)*((u_char *)p+3)<<0)
-#endif
-
 #ifdef __linux__
 #include <linux/types.h>
 #include <linux/if_packet.h>
@@ -115,13 +84,19 @@
  *
  * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
  */
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
 u_int
-bpf_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
+pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
     u_int wirelen, u_int buflen, const struct bpf_aux_data *aux_data)
+#else
+u_int
+pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
+    u_int wirelen, u_int buflen, const struct bpf_aux_data *aux_data _U_)
+#endif
 {
-	register u_int32 A, X;
+	register uint32_t A, X;
 	register bpf_u_int32 k;
-	u_int32 mem[BPF_MEMWORDS];
+	uint32_t mem[BPF_MEMWORDS];
 
 	if (pc == 0)
 		/*
@@ -160,6 +135,13 @@
 			continue;
 
 		case BPF_LD|BPF_B|BPF_ABS:
+			/*
+			 * Yes, we know, this switch doesn't do
+			 * anything unless we're building for
+			 * a Linux kernel with removed VLAN
+			 * tags available as meta-data.
+			 */
+DIAG_OFF_DEFAULT_ONLY_SWITCH
 			switch (pc->k) {
 
 #if defined(SKF_AD_VLAN_TAG_PRESENT)
@@ -183,6 +165,7 @@
 				A = p[k];
 				break;
 			}
+DIAG_ON_DEFAULT_ONLY_SWITCH
 			continue;
 
 		case BPF_LD|BPF_W|BPF_LEN:
@@ -328,11 +311,17 @@
 			continue;
 
 		case BPF_ALU|BPF_LSH|BPF_X:
-			A <<= X;
+			if (X < 32)
+				A <<= X;
+			else
+				A = 0;
 			continue;
 
 		case BPF_ALU|BPF_RSH|BPF_X:
-			A >>= X;
+			if (X < 32)
+				A >>= X;
+			else
+				A = 0;
 			continue;
 
 		case BPF_ALU|BPF_ADD|BPF_K:
@@ -378,10 +367,13 @@
 		case BPF_ALU|BPF_NEG:
 			/*
 			 * Most BPF arithmetic is unsigned, but negation
-			 * can't be unsigned; throw some casts to
-			 * specify what we're trying to do.
+			 * can't be unsigned; respecify it as subtracting
+			 * the accumulator from 0U, so that 1) we don't
+			 * get compiler warnings about negating an unsigned
+			 * value and 2) don't get UBSan warnings about
+			 * the result of negating 0x80000000 being undefined.
 			 */
-			A = (u_int32)(-(int32)A);
+			A = (0U - A);
 			continue;
 
 		case BPF_MISC|BPF_TAX:
@@ -396,13 +388,12 @@
 }
 
 u_int
-bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
+pcap_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
     u_int buflen)
 {
-	return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
+	return pcap_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
 }
 
-
 /*
  * Return true if the 'fcode' is a valid filter program.
  * The constraints are that each jump be forward and to a valid
@@ -415,7 +406,7 @@
  * Otherwise, a bogus program could easily crash the system.
  */
 int
-bpf_validate(const struct bpf_insn *f, int len)
+pcap_validate_filter(const struct bpf_insn *f, int len)
 {
 	u_int i, from;
 	const struct bpf_insn *p;
@@ -537,3 +528,19 @@
 	}
 	return BPF_CLASS(f[len - 1].code) == BPF_RET;
 }
+
+/*
+ * Exported because older versions of libpcap exported them.
+ */
+u_int
+bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
+    u_int buflen)
+{
+	return pcap_filter(pc, p, wirelen, buflen);
+}
+
+int
+bpf_validate(const struct bpf_insn *f, int len)
+{
+	return pcap_validate_filter(f, len);
+}
diff --git a/bpf_image.c b/bpf_image.c
index ab41d1e..e48c76d 100644
--- a/bpf_image.c
+++ b/bpf_image.c
@@ -28,12 +28,104 @@
 #include <stdio.h>
 #include <string.h>
 
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+
+/*
+ * We want our versions of these #defines, not Linux's version.
+ * (The two should be the same; if not, we have a problem; all BPF
+ * implementations *should* be source-compatible supersets of ours.)
+ */
+#undef BPF_STMT
+#undef BPF_JUMP
+#endif
+
 #include "pcap-int.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
 #endif
 
+#ifdef SKF_AD_OFF
+/*
+ * Symbolic names for offsets that refer to the special Linux BPF locations.
+ */
+static const char *offsets[SKF_AD_MAX] = {
+#ifdef SKF_AD_PROTOCOL
+	[SKF_AD_PROTOCOL] = "proto",
+#endif
+#ifdef SKF_AD_PKTTYPE
+	[SKF_AD_PKTTYPE] = "type",
+#endif
+#ifdef SKF_AD_IFINDEX
+	[SKF_AD_IFINDEX] = "ifidx",
+#endif
+#ifdef SKF_AD_NLATTR
+	[SKF_AD_NLATTR] = "nla",
+#endif
+#ifdef SKF_AD_NLATTR_NEST
+	[SKF_AD_NLATTR_NEST] = "nlan",
+#endif
+#ifdef SKF_AD_MARK
+	[SKF_AD_MARK] = "mark",
+#endif
+#ifdef SKF_AD_QUEUE
+	[SKF_AD_QUEUE] = "queue",
+#endif
+#ifdef SKF_AD_HATYPE
+	[SKF_AD_HATYPE] = "hatype",
+#endif
+#ifdef SKF_AD_RXHASH
+	[SKF_AD_RXHASH] = "rxhash",
+#endif
+#ifdef SKF_AD_CPU
+	[SKF_AD_CPU] = "cpu",
+#endif
+#ifdef SKF_AD_ALU_XOR_X
+	[SKF_AD_ALU_XOR_X] = "xor_x",
+#endif
+#ifdef SKF_AD_VLAN_TAG
+	[SKF_AD_VLAN_TAG] = "vlan_tci",
+#endif
+#ifdef SKF_AD_VLAN_TAG_PRESENT
+	[SKF_AD_VLAN_TAG_PRESENT] = "vlanp",
+#endif
+#ifdef SKF_AD_PAY_OFFSET
+	[SKF_AD_PAY_OFFSET] = "poff",
+#endif
+#ifdef SKF_AD_RANDOM
+	[SKF_AD_RANDOM] = "random",
+#endif
+#ifdef SKF_AD_VLAN_TPID
+	[SKF_AD_VLAN_TPID] = "vlan_tpid"
+#endif
+};
+#endif
+
+static void
+bpf_print_abs_load_operand(char *buf, size_t bufsize, const struct bpf_insn *p)
+{
+#ifdef SKF_AD_OFF
+	const char *sym;
+
+	/*
+	 * It's an absolute load.
+	 * Is the offset a special Linux offset that we know about?
+	 */
+	if (p->k >= (bpf_u_int32)SKF_AD_OFF &&
+	    p->k < (bpf_u_int32)(SKF_AD_OFF + SKF_AD_MAX) &&
+	    (sym = offsets[p->k - (bpf_u_int32)SKF_AD_OFF]) != NULL) {
+		/*
+		 * Yes.  Print the offset symbolically.
+		 */
+		(void)snprintf(buf, bufsize, "[%s]", sym);
+	} else
+#endif
+		(void)snprintf(buf, bufsize, "[%d]", p->k);
+}
+
 char *
 bpf_image(const struct bpf_insn *p, int n)
 {
@@ -46,13 +138,13 @@
 
 	default:
 		op = "unimp";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
+		(void)snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
 		operand = operand_buf;
 		break;
 
 	case BPF_RET|BPF_K:
 		op = "ret";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
@@ -63,19 +155,19 @@
 
 	case BPF_LD|BPF_W|BPF_ABS:
 		op = "ld";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+		bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_H|BPF_ABS:
 		op = "ldh";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+		bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_B|BPF_ABS:
 		op = "ldb";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+		bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p);
 		operand = operand_buf;
 		break;
 
@@ -86,91 +178,91 @@
 
 	case BPF_LD|BPF_W|BPF_IND:
 		op = "ld";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_H|BPF_IND:
 		op = "ldh";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_B|BPF_IND:
 		op = "ldb";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_IMM:
 		op = "ld";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LDX|BPF_IMM:
 		op = "ldx";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LDX|BPF_MSH|BPF_B:
 		op = "ldxb";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LD|BPF_MEM:
 		op = "ld";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_LDX|BPF_MEM:
 		op = "ldx";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ST:
 		op = "st";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_STX:
 		op = "stx";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_JMP|BPF_JA:
 		op = "ja";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_JMP|BPF_JGT|BPF_K:
 		op = "jgt";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_JMP|BPF_JGE|BPF_K:
 		op = "jge";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_JMP|BPF_JEQ|BPF_K:
 		op = "jeq";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_JMP|BPF_JSET|BPF_K:
 		op = "jset";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
@@ -246,61 +338,61 @@
 
 	case BPF_ALU|BPF_ADD|BPF_K:
 		op = "add";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_SUB|BPF_K:
 		op = "sub";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_MUL|BPF_K:
 		op = "mul";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_DIV|BPF_K:
 		op = "div";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_MOD|BPF_K:
 		op = "mod";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_AND|BPF_K:
 		op = "and";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_OR|BPF_K:
 		op = "or";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_XOR|BPF_K:
 		op = "xor";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_LSH|BPF_K:
 		op = "lsh";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
 	case BPF_ALU|BPF_RSH|BPF_K:
 		op = "rsh";
-		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+		(void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
 		operand = operand_buf;
 		break;
 
@@ -320,11 +412,11 @@
 		break;
 	}
 	if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
-		(void)pcap_snprintf(image, sizeof image,
+		(void)snprintf(image, sizeof image,
 			      "(%03d) %-8s %-16s jt %d\tjf %d",
 			      n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
 	} else {
-		(void)pcap_snprintf(image, sizeof image,
+		(void)snprintf(image, sizeof image,
 			      "(%03d) %-8s %s",
 			      n, op, operand);
 	}
diff --git a/charconv.c b/charconv.c
new file mode 100644
index 0000000..4ede572
--- /dev/null
+++ b/charconv.c
@@ -0,0 +1,216 @@
+/* -*- 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.
+ */
+
+#ifdef _WIN32
+#include <stdio.h>
+
+#include <pcap/pcap.h>	/* Needed for PCAP_ERRBUF_SIZE */
+
+#include "charconv.h"
+
+wchar_t *
+cp_to_utf_16le(UINT codepage, const char *cp_string, DWORD flags)
+{
+	int utf16le_len;
+	wchar_t *utf16le_string;
+
+	/*
+	 * Map from the specified code page to UTF-16LE.
+	 * First, find out how big a buffer we'll need.
+	 */
+	utf16le_len = MultiByteToWideChar(codepage, flags, cp_string, -1,
+	    NULL, 0);
+	if (utf16le_len == 0) {
+		/*
+		 * Error.  Fail with EINVAL.
+		 */
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/*
+	 * Now attempt to allocate a buffer for that.
+	 */
+	utf16le_string = malloc(utf16le_len * sizeof (wchar_t));
+	if (utf16le_string == NULL) {
+		/*
+		 * Not enough memory; assume errno has been
+		 * set, and fail.
+		 */
+		return (NULL);
+	}
+
+	/*
+	 * Now convert.
+	 */
+	utf16le_len = MultiByteToWideChar(codepage, flags, cp_string, -1,
+	    utf16le_string, utf16le_len);
+	if (utf16le_len == 0) {
+		/*
+		 * Error.  Fail with EINVAL.
+		 * XXX - should this ever happen, given that
+		 * we already ran the string through
+		 * MultiByteToWideChar() to find out how big
+		 * a buffer we needed?
+		 */
+		free(utf16le_string);
+		errno = EINVAL;
+		return (NULL);
+	}
+	return (utf16le_string);
+}
+
+char *
+utf_16le_to_cp(UINT codepage, const wchar_t *utf16le_string)
+{
+	int cp_len;
+	char *cp_string;
+
+	/*
+	 * Map from UTF-16LE to the specified code page.
+	 * First, find out how big a buffer we'll need.
+	 * We convert composite characters to precomposed characters,
+	 * as that's what Windows expects.
+	 */
+	cp_len = WideCharToMultiByte(codepage, WC_COMPOSITECHECK,
+	    utf16le_string, -1, NULL, 0, NULL, NULL);
+	if (cp_len == 0) {
+		/*
+		 * Error.  Fail with EINVAL.
+		 */
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/*
+	 * Now attempt to allocate a buffer for that.
+	 */
+	cp_string = malloc(cp_len * sizeof (char));
+	if (cp_string == NULL) {
+		/*
+		 * Not enough memory; assume errno has been
+		 * set, and fail.
+		 */
+		return (NULL);
+	}
+
+	/*
+	 * Now convert.
+	 */
+	cp_len = WideCharToMultiByte(codepage, WC_COMPOSITECHECK,
+	    utf16le_string, -1, cp_string, cp_len, NULL, NULL);
+	if (cp_len == 0) {
+		/*
+		 * Error.  Fail with EINVAL.
+		 * XXX - should this ever happen, given that
+		 * we already ran the string through
+		 * WideCharToMultiByte() to find out how big
+		 * a buffer we needed?
+		 */
+		free(cp_string);
+		errno = EINVAL;
+		return (NULL);
+	}
+	return (cp_string);
+}
+
+/*
+ * Convert an error message string from UTF-8 to the local code page, as
+ * best we can.
+ *
+ * The buffer is assumed to be PCAP_ERRBUF_SIZE bytes long; we truncate
+ * if it doesn't fit.
+ */
+void
+utf_8_to_acp_truncated(char *errbuf)
+{
+	wchar_t *utf_16_errbuf;
+	int retval;
+	DWORD err;
+
+	/*
+	 * Do this by converting to UTF-16LE and then to the local
+	 * code page.  That means we get to use Microsoft's
+	 * conversion routines, rather than having to understand
+	 * all the code pages ourselves, *and* that this routine
+	 * can convert in place.
+	 */
+
+	/*
+	 * Map from UTF-8 to UTF-16LE.
+	 * First, find out how big a buffer we'll need.
+	 * Convert any invalid characters to REPLACEMENT CHARACTER.
+	 */
+	utf_16_errbuf = cp_to_utf_16le(CP_UTF8, errbuf, 0);
+	if (utf_16_errbuf == NULL) {
+		/*
+		 * Error.  Give up.
+		 */
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Can't convert error string to the local code page");
+		return;
+	}
+
+	/*
+	 * Now, convert that to the local code page.
+	 * Use the current thread's code page.  For unconvertable
+	 * characters, let it pick the "best fit" character.
+	 *
+	 * XXX - we'd like some way to do what utf_16le_to_utf_8_truncated()
+	 * does if the buffer isn't big enough, but we don't want to have
+	 * to handle all local code pages ourselves; doing so requires
+	 * knowledge of all those code pages, including knowledge of how
+	 * characters are formed in thoe code pages so that we can avoid
+	 * cutting a multi-byte character into pieces.
+	 *
+	 * Converting to an un-truncated string using Windows APIs, and
+	 * then copying to the buffer, still requires knowledge of how
+	 * characters are formed in the target code page.
+	 */
+	retval = WideCharToMultiByte(CP_THREAD_ACP, 0, utf_16_errbuf, -1,
+	    errbuf, PCAP_ERRBUF_SIZE, NULL, NULL);
+	if (retval == 0) {
+		err = GetLastError();
+		free(utf_16_errbuf);
+		if (err == ERROR_INSUFFICIENT_BUFFER)
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "The error string, in the local code page, didn't fit in the buffer");
+		else
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "Can't convert error string to the local code page");
+		return;
+	}
+	free(utf_16_errbuf);
+}
+#endif
diff --git a/charconv.h b/charconv.h
new file mode 100644
index 0000000..a37d424
--- /dev/null
+++ b/charconv.h
@@ -0,0 +1,44 @@
+/* -*- 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 charonv_h
+#define charonv_h
+
+#ifdef _WIN32
+extern wchar_t *cp_to_utf_16le(UINT codepage, const char *cp_string, DWORD flags);
+extern char *utf_16le_to_cp(UINT codepage, const wchar_t *utf16le_string);
+extern void utf_8_to_acp_truncated(char *);
+#endif
+
+#endif
diff --git a/cmake/Modules/FindAirPcap.cmake b/cmake/Modules/FindAirPcap.cmake
new file mode 100644
index 0000000..8198f70
--- /dev/null
+++ b/cmake/Modules/FindAirPcap.cmake
@@ -0,0 +1,69 @@
+#
+# FindAirPcap
+# ==========
+#
+# Find the AirPcap library and include files.
+#
+# This module defines the following variables:
+#
+# AIRPCAP_INCLUDE_DIR     - absolute path to the directory containing airpcap.h.
+#
+# AIRPCAP_LIBRARY         - relative or absolute path to the AirPcap library to
+#                          link with. An absolute path is will be used if the
+#                          AirPcap library is not located in the compiler's
+#                          default search path.
+
+# AIRPCAP_FOUND           - TRUE if the AirPcap library *and* header are found.
+#
+# Hints and Backward Compatibility
+# ================================
+#
+# To tell this module where to look, a user may set the environment variable
+# AirPcap_ROOT to point cmake to the *root* of a directory with include and
+# lib subdirectories for airpcap.dll (e.g Airpcap_Devpack).
+# Alternatively, AirPcap_ROOT may also be set from the CMake command
+# line or GUI (e.g cmake -DAirPcap_ROOT=C:\path\to\airpcap_sdk [...])
+#
+
+# The 64-bit airpcap.lib is located under /x64
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  #
+  # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level
+  # directory contains 32-bit libraries; the 64-bit libraries are in the
+  # Lib/x64 directory.
+  #
+  # The only way to *FORCE* CMake to look in the Lib/x64 directory
+  # without searching in the Lib directory first appears to be to set
+  # CMAKE_LIBRARY_ARCHITECTURE to "x64".
+  #
+  # In newer versions of CMake, CMAKE_LIBRARY_ARCHITECTURE is set according to
+  # the language, e.g., CMAKE_<LANG>_LIBRARY_ARCHITECTURE. So, set the new
+  # variable, CMAKE_C_LIBRARY_ARCHITECTURE, so that CMAKE_LIBRARY_ARCHITECTURE
+  # inherits the correct value.
+  #
+  set(CMAKE_C_LIBRARY_ARCHITECTURE "x64")
+  set(CMAKE_LIBRARY_ARCHITECTURE "x64")
+endif()
+
+# Find the header
+find_path(AIRPCAP_INCLUDE_DIR airpcap.h
+  PATH_SUFFIXES include
+)
+
+# Find the library
+find_library(AIRPCAP_LIBRARY
+  NAMES airpcap
+)
+
+# Set AIRPCAP_FOUND to TRUE if AIRPCAP_INCLUDE_DIR and AIRPCAP_LIBRARY are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(AIRPCAP
+  DEFAULT_MSG
+  AIRPCAP_INCLUDE_DIR
+  AIRPCAP_LIBRARY
+)
+
+mark_as_advanced(AIRPCAP_INCLUDE_DIR AIRPCAP_LIBRARY)
+
+set(AIRPCAP_INCLUDE_DIRS ${AIRPCAP_INCLUDE_DIR})
+set(AIRPCAP_LIBRARIES ${AIRPCAP_LIBRARY})
diff --git a/cmake/Modules/FindPacket.cmake b/cmake/Modules/FindPacket.cmake
index 1311cdb..900c8e3 100644
--- a/cmake/Modules/FindPacket.cmake
+++ b/cmake/Modules/FindPacket.cmake
@@ -33,8 +33,7 @@
 # PACKET_LIBRARY         - relative or absolute path to the Packet library to
 #                          link with. An absolute path is will be used if the
 #                          Packet library is not located in the compiler's
-#                          default search path. See e.g. PACKET_DLL_DIR
-#                          variable below.
+#                          default search path.
 
 # PACKET_FOUND           - TRUE if the Packet library *and* header are found.
 #
@@ -42,29 +41,40 @@
 # ================================
 #
 # To tell this module where to look, a user may set the environment variable
-# PACKET_DLL_DIR to point cmake to the *root* of a directory with include and
-# lib subdirectories for packet.dll (e.g WpdPack/npcap-sdk).
-# Alternatively, PACKET_DLL_DIR may also be set from cmake command line or GUI
-# (e.g cmake -DPACKET_DLL_DIR=/path/to/packet [...])
+# Packet_ROOT to point cmake to the *root* of a directory with include and
+# lib subdirectories for packet.dll (e.g WpdPack or npcap-sdk).
+# Alternatively, Packet_ROOT may also be set from cmake command line or GUI
+# (e.g cmake -DPacket_ROOT=C:\path\to\packet [...])
 #
 
 # The 64-bit Packet.lib is located under /x64
-set(64BIT_SUBDIR "")
 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-  set(64BIT_SUBDIR "/x64")
+  #
+  # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level
+  # directory contains 32-bit libraries; the 64-bit libraries are in the
+  # Lib/x64 directory.
+  #
+  # The only way to *FORCE* CMake to look in the Lib/x64 directory
+  # without searching in the Lib directory first appears to be to set
+  # CMAKE_LIBRARY_ARCHITECTURE to "x64".
+  #
+  # In newer versions of CMake, CMAKE_LIBRARY_ARCHITECTURE is set according to
+  # the language, e.g., CMAKE_<LANG>_LIBRARY_ARCHITECTURE. So, set the new
+  # variable, CMAKE_C_LIBRARY_ARCHITECTURE, so that CMAKE_LIBRARY_ARCHITECTURE
+  # inherits the correct value.
+  #
+  set(CMAKE_C_LIBRARY_ARCHITECTURE "x64")
+  set(CMAKE_LIBRARY_ARCHITECTURE "x64")
 endif()
 
 # Find the header
 find_path(PACKET_INCLUDE_DIR Packet32.h
-  HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
   PATH_SUFFIXES include Include
 )
 
 # Find the library
 find_library(PACKET_LIBRARY
   NAMES Packet packet
-  HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
-  PATH_SUFFIXES Lib${64BIT_SUBDIR} lib${64BIT_SUBDIR}
 )
 
 # Set PACKET_FOUND to TRUE if PACKET_INCLUDE_DIR and PACKET_LIBRARY are TRUE.
diff --git a/cmake/Modules/Finddpdk.cmake b/cmake/Modules/Finddpdk.cmake
new file mode 100644
index 0000000..50eafd9
--- /dev/null
+++ b/cmake/Modules/Finddpdk.cmake
@@ -0,0 +1,123 @@
+# Try to find dpdk
+#
+# Once done, this will define
+#
+# dpdk_FOUND
+# dpdk_INCLUDE_DIRS
+# dpdk_LIBRARIES
+
+if(PKG_CONFIG_FOUND)
+  pkg_check_modules(dpdk QUIET libdpdk)
+endif()
+message(STATUS "Executing Finddpdk")
+if(NOT dpdk_INCLUDE_DIRS)
+  message(STATUS "Executing find_path")
+  find_path(dpdk_config_INCLUDE_DIR rte_config.h
+    HINTS
+      ENV DPDK_DIR
+    PATH_SUFFIXES
+      dpdk
+      include
+)
+  find_path(dpdk_common_INCLUDE_DIR rte_common.h
+    HINTS
+      ENC DPDK_DIR
+    PATH_SUFFIXES
+      dpdk
+      include
+)
+  set(dpdk_INCLUDE_DIRS "${dpdk_config_INCLUDE_DIR}")
+  if(NOT dpdk_config_INCLUDE_DIR EQUAL dpdk_common_INCLUDE_DIR)
+    list(APPEND dpdk_INCLUDE_DIRS "${dpdk_common_INCLUDE_DIR}")
+  endif()
+
+  set(components
+    bus_pci
+    cmdline
+    eal
+    ethdev
+    hash
+    kvargs
+    mbuf
+    mempool
+    mempool_ring
+    mempool_stack
+    pci
+    pmd_af_packet
+    pmd_bond
+    pmd_i40e
+    pmd_ixgbe
+    pmd_mlx5
+    pmd_ring
+    pmd_vmxnet3_uio
+    ring)
+
+  set(dpdk_LIBRARIES)
+
+  foreach(c ${components})
+    find_library(DPDK_rte_${c}_LIBRARY rte_${c}
+      HINTS
+        ENV DPDK_DIR
+        ${dpdk_LIBRARY_DIRS}
+      PATH_SUFFIXES lib)
+    if(DPDK_rte_${c}_LIBRARY)
+      set(dpdk_lib dpdk::${c})
+      if (NOT TARGET ${dpdk_lib})
+        add_library(${dpdk_lib} UNKNOWN IMPORTED)
+        set_target_properties(${dpdk_lib} PROPERTIES
+          INTERFACE_INCLUDE_DIRECTORIES "${dpdk_INCLUDE_DIRS}"
+          IMPORTED_LOCATION "${DPDK_rte_${c}_LIBRARY}")
+        if(c STREQUAL pmd_mlx5)
+          find_package(verbs QUIET)
+          if(verbs_FOUND)
+            target_link_libraries(${dpdk_lib} INTERFACE IBVerbs::verbs)
+          endif()
+        endif()
+      endif()
+      list(APPEND dpdk_LIBRARIES ${dpdk_lib})
+    endif()
+  endforeach()
+
+  #
+  # Where the heck did this list come from?  libdpdk on Ubuntu 20.04,
+  # for example, doesn't even *have* -ldpdk; that's why we go with
+  # pkg-config, in the hopes that it provides a correct set of flags
+  # for this tangled mess.
+  #
+  list(APPEND dpdk_LIBRARIES dpdk rt m numo dl)
+endif()
+
+mark_as_advanced(dpdk_INCLUDE_DIRS ${dpdk_LIBRARIES})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(dpdk DEFAULT_MSG
+  dpdk_INCLUDE_DIRS
+  dpdk_LIBRARIES)
+
+if(dpdk_FOUND)
+  if(NOT TARGET dpdk::cflags)
+     if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64")
+      set(rte_cflags "-march=core2")
+    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM")
+      set(rte_cflags "-march=armv7-a")
+    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64")
+      set(rte_cflags "-march=armv8-a+crc")
+    endif()
+    add_library(dpdk::cflags INTERFACE IMPORTED)
+    if (rte_cflags)
+      set_target_properties(dpdk::cflags PROPERTIES
+        INTERFACE_COMPILE_OPTIONS "${rte_cflags}")
+    endif()
+  endif()
+
+  if(NOT TARGET dpdk::dpdk)
+    add_library(dpdk::dpdk INTERFACE IMPORTED)
+    find_package(Threads QUIET)
+    list(APPEND dpdk_LIBRARIES
+      Threads::Threads
+      dpdk::cflags)
+    set_target_properties(dpdk::dpdk PROPERTIES
+      INTERFACE_LINK_LIBRARIES "${dpdk_LIBRARIES}"
+      INTERFACE_INCLUDE_DIRECTORIES "${dpdk_INCLUDE_DIRS}")
+  endif()
+endif()
diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in
index 6760cec..192209c 100644
--- a/cmakeconfig.h.in
+++ b/cmakeconfig.h.in
@@ -15,6 +15,15 @@
 /* define if we have the AIX getprotobyname_r() */
 #cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
 
+/* define if you have the AirPcap API */
+#cmakedefine HAVE_AIRPCAP_API 1
+
+/* Define to 1 if you have the `asprintf' function. */
+#cmakedefine HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the <config/HaikuConfig.h> header file. */
+#cmakedefine HAVE_CONFIG_HAIKUCONFIG_H 1
+
 /* define if you have the DAG API */
 #cmakedefine HAVE_DAG_API 1
 
@@ -48,6 +57,9 @@
 /* Define to 1 if you have the `getspnam' function. */
 #cmakedefine HAVE_GETSPNAM 1
 
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#cmakedefine HAVE_GNU_STRERROR_R 1
+
 /* on HP-UX 10.20 or later */
 #cmakedefine HAVE_HPUX10_20_OR_LATER 1
 
@@ -63,45 +75,21 @@
 /* if libnl exists */
 #cmakedefine HAVE_LIBNL 1
 
-/* if libnl exists and is version 2.x */
-#cmakedefine HAVE_LIBNL_2_x 1
-
-/* if libnl exists and is version 3.x */
-#cmakedefine HAVE_LIBNL_3_x 1
-
-/* libnl has NLE_FAILURE */
-#cmakedefine HAVE_LIBNL_NLE 1
-
-/* libnl has new-style socket api */
-#cmakedefine HAVE_LIBNL_SOCKETS 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#cmakedefine HAVE_LIMITS_H 1
-
 /* Define to 1 if you have the <linux/compiler.h> header file. */
 #cmakedefine HAVE_LINUX_COMPILER_H 1
 
-/* Define to 1 if you have the <linux/ethtool.h> header file. */
-#cmakedefine HAVE_LINUX_ETHTOOL_H 1
-
 /* define if we have the Linux getnetbyname_r() */
 #cmakedefine HAVE_LINUX_GETNETBYNAME_R 1
 
 /* define if we have the Linux getprotobyname_r() */
 #cmakedefine HAVE_LINUX_GETPROTOBYNAME_R 1
 
-/* Define to 1 if you have the <linux/if_bonding.h> header file. */
-#cmakedefine HAVE_LINUX_IF_BONDING_H 1
-
 /* Define to 1 if you have the <linux/net_tstamp.h> header file. */
 #cmakedefine HAVE_LINUX_NET_TSTAMP_H 1
 
 /* Define to 1 if you have the <linux/socket.h> header file. */
 #cmakedefine HAVE_LINUX_SOCKET_H 1
 
-/* Define to 1 if you have the <linux/sockios.h> header file. */
-#cmakedefine HAVE_LINUX_SOCKIOS_H 1
-
 /* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
 #cmakedefine HAVE_LINUX_USBDEVICE_FS_H 1
 
@@ -135,12 +123,21 @@
 /* Define to 1 if you have the <net/raw.h> header file. */
 #cmakedefine HAVE_NET_RAW_H 1
 
+/* Use OpenSSL */
+#cmakedefine HAVE_OPENSSL 1
+
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 #cmakedefine HAVE_OS_PROTO_H 1
 
-/* Define to 1 if Packet32 API (WinPcap NPF driver) is available */
+/* Define to 1 if Packet32 API (Npcap driver) is available */
 #cmakedefine HAVE_PACKET32 1
 
+/* Define to 1 if NPcap's version.h is available */
+#cmakedefine HAVE_VERSION_H 1
+
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#cmakedefine HAVE_POSIX_STRERROR_R 1
+
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
 
@@ -174,12 +171,6 @@
 /* Define to 1 if you have the `strerror' function. */
 #cmakedefine HAVE_STRERROR 1
 
-/* Define to 1 if you have the `strerror_r' function. */
-#cmakedefine HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `strerror_s' function. */
-#cmakedefine HAVE_STRERROR_S 1
-
 /* Define to 1 if you have the <strings.h> header file. */
 #cmakedefine HAVE_STRINGS_H 1
 
@@ -207,6 +198,9 @@
 /* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
 #cmakedefine HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
 
+/* Define to 1 if the system has the type `struct rte_ether_addr'. */
+#cmakedefine HAVE_STRUCT_RTE_ETHER_ADDR 1
+
 /* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
 #cmakedefine HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL 1
 
@@ -219,9 +213,6 @@
 /* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
 #cmakedefine HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
 
-/* Define to 1 if the system has the type `struct tpacket_stats'. */
-#cmakedefine HAVE_STRUCT_TPACKET_STATS 1
-
 /* Define to 1 if `bRequestType' is a member of `struct
    usbdevfs_ctrltransfer'. */
 #cmakedefine HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
@@ -256,18 +247,27 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #cmakedefine HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the `vasprintf' function. */
+#cmakedefine HAVE_VASPRINTF 1
+
 /* Define to 1 if you have the `vsnprintf' function. */
 #cmakedefine HAVE_VSNPRINTF 1
 
+/* Define to 1 if you have the `vsyslog' function. */
+#cmakedefine HAVE_VSYSLOG 1
+
+/* Define to 1 if you have the `_wcserror_s' function. */
+#cmakedefine HAVE__WCSERROR_S 1
+
+/* Define to 1 if you have the `PacketGetTimestampModes' function. */
+#cmakedefine HAVE_PACKET_GET_TIMESTAMP_MODES 1
+
 /* Define to 1 if you have the `PacketIsLoopbackAdapter' function. */
 #cmakedefine HAVE_PACKET_IS_LOOPBACK_ADAPTER 1
 
 /* IPv6 */
 #cmakedefine INET6 1
 
-/* if unaligned access fails */
-#cmakedefine LBL_ALIGN 1
-
 /* path for device for USB sniffing */
 #cmakedefine LINUX_USB_MON_DEV "@LINUX_USB_MON_DEV@"
 
@@ -286,7 +286,7 @@
 /* Define to the address where bug reports for this package should be sent. */
 #cmakedefine PACKAGE_BUGREPORT 1
 
-/* Define to the DLL-preferred version string of of this package. */
+/* Define to the DLL-preferred version string of this package. */
 #cmakedefine PACKAGE_VERSION_DLL @PACKAGE_VERSION_DLL@
 
 /* Define to the full name of this package. */
@@ -313,24 +313,21 @@
 /* support D-Bus sniffing */
 #cmakedefine PCAP_SUPPORT_DBUS 1
 
+/* target host supports DPDK */
+#cmakedefine PCAP_SUPPORT_DPDK 1
+
+/* target host supports Linux usbmon for USB sniffing */
+#cmakedefine PCAP_SUPPORT_LINUX_USBMON 1
+
 /* target host supports netfilter sniffing */
 #cmakedefine PCAP_SUPPORT_NETFILTER 1
 
 /* target host supports netmap */
 #cmakedefine PCAP_SUPPORT_NETMAP 1
 
-/* use packet ring capture support on Linux if available */
-#cmakedefine PCAP_SUPPORT_PACKET_RING 1
-
 /* target host supports RDMA sniffing */
 #cmakedefine PCAP_SUPPORT_RDMASNIFF 1
 
-/* target host supports USB sniffing */
-#cmakedefine PCAP_SUPPORT_USB 1
-
-/* include ACN support */
-#cmakedefine SITA 1
-
 /* Define to 1 if you have the ANSI C header files. */
 #cmakedefine STDC_HEADERS 1
 
diff --git a/config.guess b/config.guess
index 2b79f6d..7f74817 100755
--- a/config.guess
+++ b/config.guess
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2018 Free Software Foundation, Inc.
+#   Copyright 1992-2020 Free Software Foundation, Inc.
 
-timestamp='2018-07-06'
+timestamp='2020-12-22'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -27,12 +27,12 @@
 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
 #
 # Please send patches to <config-patches@gnu.org>.
 
 
-me=`echo "$0" | sed -e 's,.*/,,'`
+me=$(echo "$0" | sed -e 's,.*/,,')
 
 usage="\
 Usage: $0 [OPTION]
@@ -50,7 +50,7 @@
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2018 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -84,8 +84,6 @@
   exit 1
 fi
 
-trap 'exit 1' 1 2 15
-
 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a
 # compiler to aid in system detection is discouraged as it requires
 # temporary files to be created and, as you can see below, it is a
@@ -96,66 +94,82 @@
 
 # Portable tmp directory creation inspired by the Autoconf team.
 
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
- ,,)    echo "int x;" > "$dummy.c" ;
-	for c in cc gcc c89 c99 ; do
-	  if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
-	     CC_FOR_BUILD="$c"; break ;
-	  fi ;
-	done ;
-	if test x"$CC_FOR_BUILD" = x ; then
-	  CC_FOR_BUILD=no_compiler_found ;
-	fi
-	;;
- ,,*)   CC_FOR_BUILD=$CC ;;
- ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+    # prevent multiple calls if $tmp is already set
+    test "$tmp" && return 0
+    : "${TMPDIR=/tmp}"
+    # shellcheck disable=SC2039
+    { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } ||
+	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+	{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+    dummy=$tmp/dummy
+    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+	,,)    echo "int x;" > "$dummy.c"
+	       for driver in cc gcc c89 c99 ; do
+		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+		       CC_FOR_BUILD="$driver"
+		       break
+		   fi
+	       done
+	       if test x"$CC_FOR_BUILD" = x ; then
+		   CC_FOR_BUILD=no_compiler_found
+	       fi
+	       ;;
+	,,*)   CC_FOR_BUILD=$CC ;;
+	,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+    esac
+}
 
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 # (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+if test -f /.attbin/uname ; then
 	PATH=$PATH:/.attbin ; export PATH
 fi
 
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
+UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
+UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
+UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
 
 case "$UNAME_SYSTEM" in
 Linux|GNU|GNU/*)
-	# If the system lacks a compiler, then just pick glibc.
-	# We could probably try harder.
-	LIBC=gnu
+	LIBC=unknown
 
-	eval "$set_cc_for_build"
+	set_cc_for_build
 	cat <<-EOF > "$dummy.c"
 	#include <features.h>
 	#if defined(__UCLIBC__)
 	LIBC=uclibc
 	#elif defined(__dietlibc__)
 	LIBC=dietlibc
-	#else
+	#elif defined(__GLIBC__)
 	LIBC=gnu
+	#else
+	#include <stdarg.h>
+	/* First heuristic to detect musl libc.  */
+	#ifdef __DEFINED_va_list
+	LIBC=musl
+	#endif
 	#endif
 	EOF
-	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+	eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
 
-	# If ldd exists, use it to detect musl libc.
-	if command -v ldd >/dev/null && \
-		ldd --version 2>&1 | grep -q ^musl
-	then
-	    LIBC=musl
+	# Second heuristic to detect musl libc.
+	if [ "$LIBC" = unknown ] &&
+	   command -v ldd >/dev/null &&
+	   ldd --version 2>&1 | grep -q ^musl; then
+		LIBC=musl
+	fi
+
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	if [ "$LIBC" = unknown ]; then
+		LIBC=gnu
 	fi
 	;;
 esac
@@ -175,19 +189,20 @@
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
 	sysctl="sysctl -n hw.machine_arch"
-	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
 	    "/sbin/$sysctl" 2>/dev/null || \
 	    "/usr/sbin/$sysctl" 2>/dev/null || \
-	    echo unknown)`
+	    echo unknown))
 	case "$UNAME_MACHINE_ARCH" in
+	    aarch64eb) machine=aarch64_be-unknown ;;
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh5el) machine=sh5le-unknown ;;
 	    earmv*)
-		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
-		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+		arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
+		endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
 		machine="${arch}${endian}"-unknown
 		;;
 	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
@@ -199,7 +214,7 @@
 		os=netbsdelf
 		;;
 	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
-		eval "$set_cc_for_build"
+		set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 			| grep -q __ELF__
 		then
@@ -218,7 +233,7 @@
 	case "$UNAME_MACHINE_ARCH" in
 	    earm*)
 		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
-		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+		abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
 		;;
 	esac
 	# The OS release
@@ -231,7 +246,7 @@
 		release='-gnu'
 		;;
 	    *)
-		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+		release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2)
 		;;
 	esac
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
@@ -240,15 +255,15 @@
 	echo "$machine-${os}${release}${abi-}"
 	exit ;;
     *:Bitrig:*:*)
-	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
 	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
 	exit ;;
     *:OpenBSD:*:*)
-	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
 	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
 	exit ;;
     *:LibertyBSD:*:*)
-	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
 	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
 	exit ;;
     *:MidnightBSD:*:*)
@@ -260,6 +275,9 @@
     *:SolidBSD:*:*)
 	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
 	exit ;;
+    *:OS108:*:*)
+	echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
+	exit ;;
     macppc:MirBSD:*:*)
 	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
 	exit ;;
@@ -269,26 +287,29 @@
     *:Sortix:*:*)
 	echo "$UNAME_MACHINE"-unknown-sortix
 	exit ;;
+    *:Twizzler:*:*)
+	echo "$UNAME_MACHINE"-unknown-twizzler
+	exit ;;
     *:Redox:*:*)
 	echo "$UNAME_MACHINE"-unknown-redox
 	exit ;;
     mips:OSF1:*.*)
-        echo mips-dec-osf1
-        exit ;;
+	echo mips-dec-osf1
+	exit ;;
     alpha:OSF1:*:*)
 	case $UNAME_RELEASE in
 	*4.0)
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
 		;;
 	*5.*)
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
 	# OSF/1 and Tru64 systems produced since 1995.  I hope that
 	# covers most systems running today.  This code pipes the CPU
 	# types through head -n 1, so we only detect the type of CPU 0.
-	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1)
 	case "$ALPHA_CPU_TYPE" in
 	    "EV4 (21064)")
 		UNAME_MACHINE=alpha ;;
@@ -326,7 +347,7 @@
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
+	echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)"
 	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
 	exitcode=$?
 	trap '' 0
@@ -360,7 +381,7 @@
 	exit ;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
 	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+	if test "$( (/bin/universe) 2>/dev/null)" = att ; then
 		echo pyramid-pyramid-sysv3
 	else
 		echo pyramid-pyramid-bsd
@@ -373,28 +394,28 @@
 	echo sparc-icl-nx6
 	exit ;;
     DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
-	case `/usr/bin/uname -p` in
+	case $(/usr/bin/uname -p) in
 	    sparc) echo sparc-icl-nx7; exit ;;
 	esac ;;
     s390x:SunOS:*:*)
-	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+	echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
 	exit ;;
     sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
 	exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+	echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
 	exit ;;
     i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
 	echo i386-pc-auroraux"$UNAME_RELEASE"
 	exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-	eval "$set_cc_for_build"
+	set_cc_for_build
 	SUN_ARCH=i386
 	# If there is a compiler, see if it is configured for 64-bit objects.
 	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
 	# This test works for both compilers.
-	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
 	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
 		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
 		grep IS_64BIT_ARCH >/dev/null
@@ -402,30 +423,30 @@
 		SUN_ARCH=x86_64
 	    fi
 	fi
-	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
 	exit ;;
     sun4*:SunOS:6*:*)
 	# According to config.sub, this is the proper way to canonicalize
 	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
 	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
 	exit ;;
     sun4*:SunOS:*:*)
-	case "`/usr/bin/arch -k`" in
+	case "$(/usr/bin/arch -k)" in
 	    Series*|S4*)
-		UNAME_RELEASE=`uname -v`
+		UNAME_RELEASE=$(uname -v)
 		;;
 	esac
 	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
+	echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')"
 	exit ;;
     sun3*:SunOS:*:*)
 	echo m68k-sun-sunos"$UNAME_RELEASE"
 	exit ;;
     sun*:*:4.2BSD:*)
-	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)
 	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
-	case "`/bin/arch`" in
+	case "$(/bin/arch)" in
 	    sun3)
 		echo m68k-sun-sunos"$UNAME_RELEASE"
 		;;
@@ -482,7 +503,7 @@
 	echo clipper-intergraph-clix"$UNAME_RELEASE"
 	exit ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
-	eval "$set_cc_for_build"
+	set_cc_for_build
 	sed 's/^	//' << EOF > "$dummy.c"
 #ifdef __cplusplus
 #include <stdio.h>  /* for printf() prototype */
@@ -505,8 +526,8 @@
 	}
 EOF
 	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
-	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+	  dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
+	  SYSTEM_NAME=$("$dummy" "$dummyarg") &&
 	    { echo "$SYSTEM_NAME"; exit; }
 	echo mips-mips-riscos"$UNAME_RELEASE"
 	exit ;;
@@ -533,11 +554,11 @@
 	exit ;;
     AViiON:dgux:*:*)
 	# DG/UX returns AViiON for all architectures
-	UNAME_PROCESSOR=`/usr/bin/uname -p`
-	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+	UNAME_PROCESSOR=$(/usr/bin/uname -p)
+	if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
 	then
-	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
-	       [ "$TARGET_BINARY_INTERFACE"x = x ]
+	    if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+	       test "$TARGET_BINARY_INTERFACE"x = x
 	    then
 		echo m88k-dg-dgux"$UNAME_RELEASE"
 	    else
@@ -561,17 +582,17 @@
 	echo m68k-tektronix-bsd
 	exit ;;
     *:IRIX*:*:*)
-	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
+	echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
 	exit ;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
 	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
-	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+	exit ;;               # Note that: echo "'$(uname -s)'" gives 'AIX '
     i*86:AIX:*:*)
 	echo i386-ibm-aix
 	exit ;;
     ia64:AIX:*:*)
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
+	if test -x /usr/bin/oslevel ; then
+		IBM_REV=$(/usr/bin/oslevel)
 	else
 		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
 	fi
@@ -579,7 +600,7 @@
 	exit ;;
     *:AIX:2:3)
 	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-		eval "$set_cc_for_build"
+		set_cc_for_build
 		sed 's/^		//' << EOF > "$dummy.c"
 		#include <sys/systemcfg.h>
 
@@ -591,7 +612,7 @@
 			exit(0);
 			}
 EOF
-		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
 		then
 			echo "$SYSTEM_NAME"
 		else
@@ -604,15 +625,15 @@
 	fi
 	exit ;;
     *:AIX:*:[4567])
-	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')
 	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/lslpp ] ; then
-		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
-			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+	if test -x /usr/bin/lslpp ; then
+		IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
 	else
 		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
 	fi
@@ -640,14 +661,14 @@
 	echo m68k-hp-bsd4.4
 	exit ;;
     9000/[34678]??:HP-UX:*:*)
-	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+	HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
 	case "$UNAME_MACHINE" in
 	    9000/31?)            HP_ARCH=m68000 ;;
 	    9000/[34]??)         HP_ARCH=m68k ;;
 	    9000/[678][0-9][0-9])
-		if [ -x /usr/bin/getconf ]; then
-		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		if test -x /usr/bin/getconf; then
+		    sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)
+		    sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)
 		    case "$sc_cpu_version" in
 		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
 		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
@@ -659,8 +680,8 @@
 			esac ;;
 		    esac
 		fi
-		if [ "$HP_ARCH" = "" ]; then
-		    eval "$set_cc_for_build"
+		if test "$HP_ARCH" = ""; then
+		    set_cc_for_build
 		    sed 's/^		//' << EOF > "$dummy.c"
 
 		#define _HPUX_SOURCE
@@ -694,13 +715,13 @@
 		    exit (0);
 		}
 EOF
-		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy")
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
 		fi ;;
 	esac
-	if [ "$HP_ARCH" = hppa2.0w ]
+	if test "$HP_ARCH" = hppa2.0w
 	then
-	    eval "$set_cc_for_build"
+	    set_cc_for_build
 
 	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
 	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
@@ -722,11 +743,11 @@
 	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
 	exit ;;
     ia64:HP-UX:*:*)
-	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+	HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
 	echo ia64-hp-hpux"$HPUX_REV"
 	exit ;;
     3050*:HI-UX:*:*)
-	eval "$set_cc_for_build"
+	set_cc_for_build
 	sed 's/^	//' << EOF > "$dummy.c"
 	#include <unistd.h>
 	int
@@ -752,7 +773,7 @@
 	  exit (0);
 	}
 EOF
-	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") &&
 		{ echo "$SYSTEM_NAME"; exit; }
 	echo unknown-hitachi-hiuxwe2
 	exit ;;
@@ -772,7 +793,7 @@
 	echo hppa1.0-hp-osf
 	exit ;;
     i*86:OSF1:*:*)
-	if [ -x /usr/sbin/sysversion ] ; then
+	if test -x /usr/sbin/sysversion ; then
 	    echo "$UNAME_MACHINE"-unknown-osf1mk
 	else
 	    echo "$UNAME_MACHINE"-unknown-osf1
@@ -821,14 +842,14 @@
 	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
-	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
-	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+	FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
+	FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
+	FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
 	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     5000:UNIX_System_V:4.*:*)
-	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
-	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+	FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
+	FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')
 	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@@ -840,15 +861,26 @@
     *:BSD/OS:*:*)
 	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
 	exit ;;
+    arm:FreeBSD:*:*)
+	UNAME_PROCESSOR=$(uname -p)
+	set_cc_for_build
+	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_PCS_VFP
+	then
+	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
+	else
+	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
+	fi
+	exit ;;
     *:FreeBSD:*:*)
-	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	UNAME_PROCESSOR=$(/usr/bin/uname -p)
 	case "$UNAME_PROCESSOR" in
 	    amd64)
 		UNAME_PROCESSOR=x86_64 ;;
 	    i386)
 		UNAME_PROCESSOR=i586 ;;
 	esac
-	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+	echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
 	exit ;;
     i*:CYGWIN*:*)
 	echo "$UNAME_MACHINE"-pc-cygwin
@@ -881,18 +913,18 @@
 	echo "$UNAME_MACHINE"-pc-uwin
 	exit ;;
     amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
-	echo x86_64-unknown-cygwin
+	echo x86_64-pc-cygwin
 	exit ;;
     prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
 	exit ;;
     *:GNU:*:*)
 	# the GNU system
-	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
+	echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')"
 	exit ;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
+	echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
 	exit ;;
     *:Minix:*:*)
 	echo "$UNAME_MACHINE"-unknown-minix
@@ -905,7 +937,7 @@
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     alpha:Linux:*:*)
-	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in
 	  EV5)   UNAME_MACHINE=alphaev5 ;;
 	  EV56)  UNAME_MACHINE=alphaev56 ;;
 	  PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -922,7 +954,7 @@
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     arm*:Linux:*:*)
-	eval "$set_cc_for_build"
+	set_cc_for_build
 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_EABI__
 	then
@@ -964,6 +996,9 @@
     k1om:Linux:*:*)
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
+    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
     m32r*:Linux:*:*)
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
@@ -971,23 +1006,51 @@
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
-	eval "$set_cc_for_build"
+	set_cc_for_build
+	IS_GLIBC=0
+	test x"${LIBC}" = xgnu && IS_GLIBC=1
 	sed 's/^	//' << EOF > "$dummy.c"
 	#undef CPU
-	#undef ${UNAME_MACHINE}
-	#undef ${UNAME_MACHINE}el
+	#undef mips
+	#undef mipsel
+	#undef mips64
+	#undef mips64el
+	#if ${IS_GLIBC} && defined(_ABI64)
+	LIBCABI=gnuabi64
+	#else
+	#if ${IS_GLIBC} && defined(_ABIN32)
+	LIBCABI=gnuabin32
+	#else
+	LIBCABI=${LIBC}
+	#endif
+	#endif
+
+	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa64r6
+	#else
+	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+	CPU=mipsisa32r6
+	#else
+	#if defined(__mips64)
+	CPU=mips64
+	#else
+	CPU=mips
+	#endif
+	#endif
+	#endif
+
 	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=${UNAME_MACHINE}el
+	MIPS_ENDIAN=el
 	#else
 	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=${UNAME_MACHINE}
+	MIPS_ENDIAN=
 	#else
-	CPU=
+	MIPS_ENDIAN=
 	#endif
 	#endif
 EOF
-	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
-	test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+	eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
+	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
 	;;
     mips64el:Linux:*:*)
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
@@ -1006,7 +1069,7 @@
 	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
-	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in
 	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
 	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
 	  *)    echo hppa-unknown-linux-"$LIBC" ;;
@@ -1046,7 +1109,17 @@
 	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
 	exit ;;
     x86_64:Linux:*:*)
-	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+	set_cc_for_build
+	LIBCABI=$LIBC
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_X32 >/dev/null
+	    then
+		LIBCABI="$LIBC"x32
+	    fi
+	fi
+	echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
 	exit ;;
     xtensa*:Linux:*:*)
 	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
@@ -1086,7 +1159,7 @@
 	echo "$UNAME_MACHINE"-pc-msdosdjgpp
 	exit ;;
     i*86:*:4.*:*)
-	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+	UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//')
 	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
 		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
 	else
@@ -1095,19 +1168,19 @@
 	exit ;;
     i*86:*:5:[678]*)
 	# UnixWare 7.x, OpenUNIX and OpenServer 6.
-	case `/bin/uname -X | grep "^Machine"` in
+	case $(/bin/uname -X | grep "^Machine") in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
 	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
 	esac
-	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
+	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
 	exit ;;
     i*86:*:3.2:*)
 	if test -f /usr/options/cb.name; then
-		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name)
 		echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
 	elif /bin/uname -X 2>/dev/null >/dev/null ; then
-		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))
 		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
 		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
 			&& UNAME_MACHINE=i586
@@ -1157,7 +1230,7 @@
     3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
 	OS_REL=''
 	test -r /etc/.relid \
-	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
 	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
 	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@@ -1168,7 +1241,7 @@
     NCR*:*:4.2:* | MPRAS*:*:4.2:*)
 	OS_REL='.3'
 	test -r /etc/.relid \
-	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	    && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
 	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
 	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@@ -1201,7 +1274,7 @@
 	exit ;;
     *:SINIX-*:*:*)
 	if uname -p 2>/dev/null >/dev/null ; then
-		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		UNAME_MACHINE=$( (uname -p) 2>/dev/null)
 		echo "$UNAME_MACHINE"-sni-sysv4
 	else
 		echo ns32k-sni-sysv
@@ -1235,7 +1308,7 @@
 	echo mips-sony-newsos6
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if [ -d /usr/nec ]; then
+	if test -d /usr/nec; then
 		echo mips-nec-sysv"$UNAME_RELEASE"
 	else
 		echo mips-unknown-sysv"$UNAME_RELEASE"
@@ -1283,44 +1356,48 @@
     *:Rhapsody:*:*)
 	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
 	exit ;;
+    arm64:Darwin:*:*)
+	echo aarch64-apple-darwin"$UNAME_RELEASE"
+	exit ;;
     *:Darwin:*:*)
-	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	eval "$set_cc_for_build"
-	if test "$UNAME_PROCESSOR" = unknown ; then
-	    UNAME_PROCESSOR=powerpc
+	UNAME_PROCESSOR=$(uname -p)
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	if command -v xcode-select > /dev/null 2> /dev/null && \
+		! xcode-select --print-path > /dev/null 2> /dev/null ; then
+	    # Avoid executing cc if there is no toolchain installed as
+	    # cc will be a stub that puts up a graphical alert
+	    # prompting the user to install developer tools.
+	    CC_FOR_BUILD=no_compiler_found
+	else
+	    set_cc_for_build
 	fi
-	if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
-	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
-		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		       grep IS_64BIT_ARCH >/dev/null
-		then
-		    case $UNAME_PROCESSOR in
-			i386) UNAME_PROCESSOR=x86_64 ;;
-			powerpc) UNAME_PROCESSOR=powerpc64 ;;
-		    esac
-		fi
-		# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
-		if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
-		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		       grep IS_PPC >/dev/null
-		then
-		    UNAME_PROCESSOR=powerpc
-		fi
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_64BIT_ARCH >/dev/null
+	    then
+		case $UNAME_PROCESSOR in
+		    i386) UNAME_PROCESSOR=x86_64 ;;
+		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		esac
+	    fi
+	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		   grep IS_PPC >/dev/null
+	    then
+		UNAME_PROCESSOR=powerpc
 	    fi
 	elif test "$UNAME_PROCESSOR" = i386 ; then
-	    # Avoid executing cc on OS X 10.9, as it ships with a stub
-	    # that puts up a graphical alert prompting to install
-	    # developer tools.  Any system running Mac OS X 10.7 or
-	    # later (Darwin 11 and later) is required to have a 64-bit
-	    # processor. This is not true of the ARM version of Darwin
-	    # that Apple uses in portable devices.
-	    UNAME_PROCESSOR=x86_64
+	    # uname -m returns i386 or x86_64
+	    UNAME_PROCESSOR=$UNAME_MACHINE
 	fi
 	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
-	UNAME_PROCESSOR=`uname -p`
+	UNAME_PROCESSOR=$(uname -p)
 	if test "$UNAME_PROCESSOR" = x86; then
 		UNAME_PROCESSOR=i386
 		UNAME_MACHINE=pc
@@ -1358,6 +1435,7 @@
 	# "uname -m" is not consistent, so use $cputype instead. 386
 	# is converted to i386 for consistency with other x86
 	# operating systems.
+	# shellcheck disable=SC2154
 	if test "$cputype" = 386; then
 	    UNAME_MACHINE=i386
 	else
@@ -1387,10 +1465,10 @@
 	echo mips-sei-seiux"$UNAME_RELEASE"
 	exit ;;
     *:DragonFly:*:*)
-	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+	echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
 	exit ;;
     *:*VMS:*:*)
-	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=$( (uname -p) 2>/dev/null)
 	case "$UNAME_MACHINE" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
@@ -1400,7 +1478,7 @@
 	echo i386-pc-xenix
 	exit ;;
     i*86:skyos:*:*)
-	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
+	echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')"
 	exit ;;
     i*86:rdos:*:*)
 	echo "$UNAME_MACHINE"-pc-rdos
@@ -1414,8 +1492,148 @@
     amd64:Isilon\ OneFS:*:*)
 	echo x86_64-unknown-onefs
 	exit ;;
+    *:Unleashed:*:*)
+	echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
+	exit ;;
 esac
 
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+  "4"
+#else
+  ""
+#endif
+  ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null);
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+  struct utsname un;
+
+  uname(&un);
+  if (strncmp(un.version, "V2", 2) == 0) {
+    printf ("i386-sequent-ptx2\n"); exit (0);
+  }
+  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+    printf ("i386-sequent-ptx1\n"); exit (0);
+  }
+  printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+  printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+  printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+  printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname un;
+  uname (&un);
+  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+  struct utsname *un;
+  uname (&un);
+  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+  printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
 echo "$0: unable to guess system type" >&2
 
 case "$UNAME_MACHINE:$UNAME_SYSTEM" in
@@ -1435,9 +1653,15 @@
 operating system you are using. If your script is old, overwrite *all*
 copies of config.guess and config.sub with the latest versions from:
 
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
 and
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+year=$(echo $timestamp | sed 's,-.*,,')
+# shellcheck disable=SC2003
+if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
+   cat >&2 <<EOF
 
 If $0 has already been updated, send the following data and any
 information you think might be pertinent to config-patches@gnu.org to
@@ -1445,26 +1669,27 @@
 
 config.guess timestamp = $timestamp
 
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
+uname -m = $( (uname -m) 2>/dev/null || echo unknown)
+uname -r = $( (uname -r) 2>/dev/null || echo unknown)
+uname -s = $( (uname -s) 2>/dev/null || echo unknown)
+uname -v = $( (uname -v) 2>/dev/null || echo unknown)
 
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)
+/bin/uname -X     = $( (/bin/uname -X) 2>/dev/null)
 
-hostinfo               = `(hostinfo) 2>/dev/null`
-/bin/universe          = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch              = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+hostinfo               = $( (hostinfo) 2>/dev/null)
+/bin/universe          = $( (/bin/universe) 2>/dev/null)
+/usr/bin/arch -k       = $( (/usr/bin/arch -k) 2>/dev/null)
+/bin/arch              = $( (/bin/arch) 2>/dev/null)
+/usr/bin/oslevel       = $( (/usr/bin/oslevel) 2>/dev/null)
+/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
 
 UNAME_MACHINE = "$UNAME_MACHINE"
 UNAME_RELEASE = "$UNAME_RELEASE"
 UNAME_SYSTEM  = "$UNAME_SYSTEM"
 UNAME_VERSION = "$UNAME_VERSION"
 EOF
+fi
 
 exit 1
 
diff --git a/config.h b/config.h
index 4bae2ec..aa23c6a 100644
--- a/config.h
+++ b/config.h
@@ -16,6 +16,9 @@
 /* define if we have the AIX getprotobyname_r() */
 /* #undef HAVE_AIX_GETPROTOBYNAME_R */
 
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
 /* Define to 1 if you have the <dagapi.h> header file. */
 /* #undef HAVE_DAGAPI_H */
 
@@ -55,6 +58,9 @@
 /* Define to 1 if you have the `getspnam' function. */
 /* #undef HAVE_GETSPNAM */
 
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#define HAVE_GNU_STRERROR_R /**/
+
 /* on HP-UX 10.20 or later */
 /* #undef HAVE_HPUX10_20_OR_LATER */
 
@@ -151,6 +157,9 @@
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 /* #undef HAVE_PF_NAT_THROUGH_PF_NORDR */
 
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#define HAVE_POSIX_STRERROR_R 1
+
 /* define if you have the Septel API */
 /* #undef HAVE_SEPTEL_API */
 
@@ -181,9 +190,6 @@
 /* Define to 1 if you have the `strerror' function. */
 #define HAVE_STRERROR 1
 
-/* Define to 1 if you have the `strerror_r' function. */
-#define HAVE_STRERROR_R 1
-
 /* Define to 1 if you have the `strerror_s' function. */
 /* #undef HAVE_STRERROR_S */
 
@@ -267,9 +273,15 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
 /* Define to 1 if you have the `vsnprintf' function. */
 #define HAVE_VSNPRINTF 1
 
+/* Define to 1 if you have the `vsyslog' function. */
+#define HAVE_VSYSLOG 1
+
 /* IPv6 */
 #define INET6 1
 
@@ -298,7 +310,7 @@
 #define PACKAGE_NAME "pcap"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "pcap 1.9.0-PRE-GIT"
+#define PACKAGE_STRING "pcap 1.9.1"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "pcap"
@@ -307,7 +319,7 @@
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "1.9.0-PRE-GIT"
+#define PACKAGE_VERSION "1.9.1"
 
 /* target host supports Bluetooth sniffing */
 /* #undef PCAP_SUPPORT_BT */
diff --git a/config.h.in b/config.h.in
index b1a20a4..00618ae 100644
--- a/config.h.in
+++ b/config.h.in
@@ -15,6 +15,12 @@
 /* define if we have the AIX getprotobyname_r() */
 #undef HAVE_AIX_GETPROTOBYNAME_R
 
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the <config/HaikuConfig.h> header file. */
+#undef HAVE_CONFIG_HAIKUCONFIG_H
+
 /* Define to 1 if you have the <dagapi.h> header file. */
 #undef HAVE_DAGAPI_H
 
@@ -54,6 +60,9 @@
 /* Define to 1 if you have the `getspnam' function. */
 #undef HAVE_GETSPNAM
 
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#undef HAVE_GNU_STRERROR_R
+
 /* on HP-UX 10.20 or later */
 #undef HAVE_HPUX10_20_OR_LATER
 
@@ -72,45 +81,21 @@
 /* if libnl exists */
 #undef HAVE_LIBNL
 
-/* if libnl exists and is version 2.x */
-#undef HAVE_LIBNL_2_x
-
-/* if libnl exists and is version 3.x */
-#undef HAVE_LIBNL_3_x
-
-/* libnl has NLE_FAILURE */
-#undef HAVE_LIBNL_NLE
-
-/* libnl has new-style socket api */
-#undef HAVE_LIBNL_SOCKETS
-
-/* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
 /* Define to 1 if you have the <linux/compiler.h> header file. */
 #undef HAVE_LINUX_COMPILER_H
 
-/* Define to 1 if you have the <linux/ethtool.h> header file. */
-#undef HAVE_LINUX_ETHTOOL_H
-
 /* define if we have the Linux getnetbyname_r() */
 #undef HAVE_LINUX_GETNETBYNAME_R
 
 /* define if we have the Linux getprotobyname_r() */
 #undef HAVE_LINUX_GETPROTOBYNAME_R
 
-/* Define to 1 if you have the <linux/if_bonding.h> header file. */
-#undef HAVE_LINUX_IF_BONDING_H
-
 /* Define to 1 if you have the <linux/net_tstamp.h> header file. */
 #undef HAVE_LINUX_NET_TSTAMP_H
 
 /* Define to 1 if you have the <linux/socket.h> header file. */
 #undef HAVE_LINUX_SOCKET_H
 
-/* Define to 1 if you have the <linux/sockios.h> header file. */
-#undef HAVE_LINUX_SOCKIOS_H
-
 /* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
 #undef HAVE_LINUX_USBDEVICE_FS_H
 
@@ -129,9 +114,18 @@
 /* Define to 1 if you have the <net/enet.h> header file. */
 #undef HAVE_NET_ENET_H
 
+/* Define to 1 if you have the <net/if_dl.h> header file. */
+#undef HAVE_NET_IF_DL_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
 /* Define to 1 if you have the <net/if_media.h> header file. */
 #undef HAVE_NET_IF_MEDIA_H
 
+/* Define to 1 if you have the <net/if_types.h> header file. */
+#undef HAVE_NET_IF_TYPES_H
+
 /* Define to 1 if you have the <net/nit.h> header file. */
 #undef HAVE_NET_NIT_H
 
@@ -144,21 +138,24 @@
 /* Define to 1 if you have the <net/raw.h> header file. */
 #undef HAVE_NET_RAW_H
 
+/* Use OpenSSL */
+#undef HAVE_OPENSSL
+
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 #undef HAVE_OS_PROTO_H
 
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #undef HAVE_PF_NAT_THROUGH_PF_NORDR
 
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#undef HAVE_POSIX_STRERROR_R
+
 /* define if you have the Septel API */
 #undef HAVE_SEPTEL_API
 
 /* define if you have the Myricom SNF API */
 #undef HAVE_SNF_API
 
-/* Define to 1 if you have the `snprintf' function. */
-#undef HAVE_SNPRINTF
-
 /* Define to 1 if the system has the type `socklen_t'. */
 #undef HAVE_SOCKLEN_T
 
@@ -180,12 +177,6 @@
 /* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
-/* Define to 1 if you have the `strerror_r' function. */
-#undef HAVE_STRERROR_R
-
-/* Define to 1 if you have the `strerror_s' function. */
-#undef HAVE_STRERROR_S
-
 /* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
 
@@ -213,6 +204,9 @@
 /* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
 #undef HAVE_STRUCT_MSGHDR_MSG_FLAGS
 
+/* Define to 1 if the system has the type `struct rte_ether_addr'. */
+#undef HAVE_STRUCT_RTE_ETHER_ADDR
+
 /* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
 #undef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL
 
@@ -225,9 +219,6 @@
 /* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
 #undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI
 
-/* Define to 1 if the system has the type `struct tpacket_stats'. */
-#undef HAVE_STRUCT_TPACKET_STATS
-
 /* Define to 1 if `bRequestType' is a member of `struct
    usbdevfs_ctrltransfer'. */
 #undef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
@@ -262,15 +253,18 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
-/* Define to 1 if you have the `vsnprintf' function. */
-#undef HAVE_VSNPRINTF
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Define to 1 if you have the `_wcserror_s' function. */
+#undef HAVE__WCSERROR_S
 
 /* IPv6 */
 #undef INET6
 
-/* if unaligned access fails */
-#undef LBL_ALIGN
-
 /* path for device for USB sniffing */
 #undef LINUX_USB_MON_DEV
 
@@ -313,24 +307,21 @@
 /* support D-Bus sniffing */
 #undef PCAP_SUPPORT_DBUS
 
+/* target host supports DPDK */
+#undef PCAP_SUPPORT_DPDK
+
+/* target host supports Linux usbmon for USB sniffing */
+#undef PCAP_SUPPORT_LINUX_USBMON
+
 /* target host supports netfilter sniffing */
 #undef PCAP_SUPPORT_NETFILTER
 
 /* target host supports netmap */
 #undef PCAP_SUPPORT_NETMAP
 
-/* use packet ring capture support on Linux if available */
-#undef PCAP_SUPPORT_PACKET_RING
-
 /* target host supports RDMA sniffing */
 #undef PCAP_SUPPORT_RDMASNIFF
 
-/* target host supports USB sniffing */
-#undef PCAP_SUPPORT_USB
-
-/* include ACN support */
-#undef SITA
-
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
diff --git a/config.sub b/config.sub
index c95acc6..90bb8ae 100755
--- a/config.sub
+++ b/config.sub
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2018 Free Software Foundation, Inc.
+#   Copyright 1992-2020 Free Software Foundation, Inc.
 
-timestamp='2018-07-03'
+timestamp='2020-12-22'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -50,7 +50,7 @@
 #	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
 # It is wrong to echo any other type of specification.
 
-me=`echo "$0" | sed -e 's,.*/,,'`
+me=$(echo "$0" | sed -e 's,.*/,,')
 
 usage="\
 Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
@@ -67,7 +67,7 @@
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2018 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -89,7 +89,7 @@
     - )	# Use stdin as input.
        break ;;
     -* )
-       echo "$me: invalid option $1$help"
+       echo "$me: invalid option $1$help" >&2
        exit 1 ;;
 
     *local*)
@@ -111,7 +111,8 @@
 esac
 
 # Split fields of configuration type
-IFS="-" read -r field1 field2 field3 field4 <<EOF
+# shellcheck disable=SC2162
+IFS="-" read field1 field2 field3 field4 <<EOF
 $1
 EOF
 
@@ -123,55 +124,64 @@
 		;;
 	*-*-*-*)
 		basic_machine=$field1-$field2
-		os=$field3-$field4
+		basic_os=$field3-$field4
 		;;
 	*-*-*)
 		# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
 		# parts
 		maybe_os=$field2-$field3
 		case $maybe_os in
-			nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
-			| linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+			nto-qnx* | linux-* | uclinux-uclibc* \
 			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
 			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
 			| storm-chaos* | os2-emx* | rtmk-nova*)
 				basic_machine=$field1
-				os=$maybe_os
+				basic_os=$maybe_os
 				;;
 			android-linux)
 				basic_machine=$field1-unknown
-				os=linux-android
+				basic_os=linux-android
 				;;
 			*)
 				basic_machine=$field1-$field2
-				os=$field3
+				basic_os=$field3
 				;;
 		esac
 		;;
 	*-*)
-		# Second component is usually, but not always the OS
-		case $field2 in
-			# Prevent following clause from handling this valid os
-			sun*os*)
-				basic_machine=$field1
-				os=$field2
+		# A lone config we happen to match not fitting any pattern
+		case $field1-$field2 in
+			decstation-3100)
+				basic_machine=mips-dec
+				basic_os=
 				;;
-			# Manufacturers
-			dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \
-			| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
-			| unicom* | ibm* | next | hp | isi* | apollo | altos* \
-			| convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \
-			| c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \
-			| harris | dolphin | highlevel | gould | cbm | ns | masscomp \
-			| apple | axis | knuth | cray | microblaze* \
-			| sim | cisco | oki | wec | wrs | winbond)
-				basic_machine=$field1-$field2
-				os=
-				;;
-			*)
-				basic_machine=$field1
-				os=$field2
-				;;
+			*-*)
+				# Second component is usually, but not always the OS
+				case $field2 in
+					# Prevent following clause from handling this valid os
+					sun*os*)
+						basic_machine=$field1
+						basic_os=$field2
+						;;
+					# Manufacturers
+					dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+					| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+					| unicom* | ibm* | next | hp | isi* | apollo | altos* \
+					| convergent* | ncr* | news | 32* | 3600* | 3100* \
+					| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+					| ultra | tti* | harris | dolphin | highlevel | gould \
+					| cbm | ns | masscomp | apple | axis | knuth | cray \
+					| microblaze* | sim | cisco \
+					| oki | wec | wrs | winbond)
+						basic_machine=$field1-$field2
+						basic_os=
+						;;
+					*)
+						basic_machine=$field1
+						basic_os=$field2
+						;;
+				esac
+			;;
 		esac
 		;;
 	*)
@@ -180,1105 +190,1089 @@
 		case $field1 in
 			386bsd)
 				basic_machine=i386-pc
-				os=bsd
+				basic_os=bsd
 				;;
 			a29khif)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			adobe68k)
 				basic_machine=m68010-adobe
-				os=scout
+				basic_os=scout
+				;;
+			alliant)
+				basic_machine=fx80-alliant
+				basic_os=
+				;;
+			altos | altos3068)
+				basic_machine=m68k-altos
+				basic_os=
 				;;
 			am29k)
 				basic_machine=a29k-none
-				os=bsd
+				basic_os=bsd
 				;;
 			amdahl)
 				basic_machine=580-amdahl
-				os=sysv
+				basic_os=sysv
+				;;
+			amiga)
+				basic_machine=m68k-unknown
+				basic_os=
 				;;
 			amigaos | amigados)
 				basic_machine=m68k-unknown
-				os=amigaos
+				basic_os=amigaos
 				;;
 			amigaunix | amix)
 				basic_machine=m68k-unknown
-				os=sysv4
+				basic_os=sysv4
 				;;
 			apollo68)
 				basic_machine=m68k-apollo
-				os=sysv
+				basic_os=sysv
 				;;
 			apollo68bsd)
 				basic_machine=m68k-apollo
-				os=bsd
+				basic_os=bsd
 				;;
 			aros)
 				basic_machine=i386-pc
-				os=aros
+				basic_os=aros
 				;;
 			aux)
 				basic_machine=m68k-apple
-				os=aux
+				basic_os=aux
 				;;
 			balance)
 				basic_machine=ns32k-sequent
-				os=dynix
+				basic_os=dynix
 				;;
 			blackfin)
 				basic_machine=bfin-unknown
-				os=linux
+				basic_os=linux
 				;;
 			cegcc)
 				basic_machine=arm-unknown
-				os=cegcc
+				basic_os=cegcc
+				;;
+			convex-c1)
+				basic_machine=c1-convex
+				basic_os=bsd
+				;;
+			convex-c2)
+				basic_machine=c2-convex
+				basic_os=bsd
+				;;
+			convex-c32)
+				basic_machine=c32-convex
+				basic_os=bsd
+				;;
+			convex-c34)
+				basic_machine=c34-convex
+				basic_os=bsd
+				;;
+			convex-c38)
+				basic_machine=c38-convex
+				basic_os=bsd
 				;;
 			cray)
 				basic_machine=j90-cray
-				os=unicos
+				basic_os=unicos
 				;;
-			craynv)
-				basic_machine=craynv-cray
-				os=unicosmp
+			crds | unos)
+				basic_machine=m68k-crds
+				basic_os=
+				;;
+			da30)
+				basic_machine=m68k-da30
+				basic_os=
+				;;
+			decstation | pmax | pmin | dec3100 | decstatn)
+				basic_machine=mips-dec
+				basic_os=
 				;;
 			delta88)
 				basic_machine=m88k-motorola
-				os=sysv3
+				basic_os=sysv3
 				;;
 			dicos)
 				basic_machine=i686-pc
-				os=dicos
+				basic_os=dicos
 				;;
 			djgpp)
 				basic_machine=i586-pc
-				os=msdosdjgpp
+				basic_os=msdosdjgpp
 				;;
 			ebmon29k)
 				basic_machine=a29k-amd
-				os=ebmon
+				basic_os=ebmon
 				;;
 			es1800 | OSE68k | ose68k | ose | OSE)
 				basic_machine=m68k-ericsson
-				os=ose
+				basic_os=ose
 				;;
 			gmicro)
 				basic_machine=tron-gmicro
-				os=sysv
+				basic_os=sysv
 				;;
 			go32)
 				basic_machine=i386-pc
-				os=go32
+				basic_os=go32
 				;;
 			h8300hms)
 				basic_machine=h8300-hitachi
-				os=hms
+				basic_os=hms
 				;;
 			h8300xray)
 				basic_machine=h8300-hitachi
-				os=xray
+				basic_os=xray
 				;;
 			h8500hms)
 				basic_machine=h8500-hitachi
-				os=hms
+				basic_os=hms
 				;;
 			harris)
 				basic_machine=m88k-harris
-				os=sysv3
+				basic_os=sysv3
+				;;
+			hp300 | hp300hpux)
+				basic_machine=m68k-hp
+				basic_os=hpux
 				;;
 			hp300bsd)
 				basic_machine=m68k-hp
-				os=bsd
-				;;
-			hp300hpux)
-				basic_machine=m68k-hp
-				os=hpux
+				basic_os=bsd
 				;;
 			hppaosf)
 				basic_machine=hppa1.1-hp
-				os=osf
+				basic_os=osf
 				;;
 			hppro)
 				basic_machine=hppa1.1-hp
-				os=proelf
+				basic_os=proelf
 				;;
 			i386mach)
 				basic_machine=i386-mach
-				os=mach
-				;;
-			vsta)
-				basic_machine=i386-unknown
-				os=vsta
+				basic_os=mach
 				;;
 			isi68 | isi)
 				basic_machine=m68k-isi
-				os=sysv
+				basic_os=sysv
 				;;
 			m68knommu)
 				basic_machine=m68k-unknown
-				os=linux
+				basic_os=linux
 				;;
 			magnum | m3230)
 				basic_machine=mips-mips
-				os=sysv
+				basic_os=sysv
 				;;
 			merlin)
 				basic_machine=ns32k-utek
-				os=sysv
+				basic_os=sysv
 				;;
 			mingw64)
 				basic_machine=x86_64-pc
-				os=mingw64
+				basic_os=mingw64
 				;;
 			mingw32)
 				basic_machine=i686-pc
-				os=mingw32
+				basic_os=mingw32
 				;;
 			mingw32ce)
 				basic_machine=arm-unknown
-				os=mingw32ce
+				basic_os=mingw32ce
 				;;
 			monitor)
 				basic_machine=m68k-rom68k
-				os=coff
+				basic_os=coff
 				;;
 			morphos)
 				basic_machine=powerpc-unknown
-				os=morphos
+				basic_os=morphos
 				;;
 			moxiebox)
 				basic_machine=moxie-unknown
-				os=moxiebox
+				basic_os=moxiebox
 				;;
 			msdos)
 				basic_machine=i386-pc
-				os=msdos
+				basic_os=msdos
 				;;
 			msys)
 				basic_machine=i686-pc
-				os=msys
+				basic_os=msys
 				;;
 			mvs)
 				basic_machine=i370-ibm
-				os=mvs
+				basic_os=mvs
 				;;
 			nacl)
 				basic_machine=le32-unknown
-				os=nacl
+				basic_os=nacl
 				;;
 			ncr3000)
 				basic_machine=i486-ncr
-				os=sysv4
+				basic_os=sysv4
 				;;
 			netbsd386)
-				basic_machine=i386-unknown
-				os=netbsd
+				basic_machine=i386-pc
+				basic_os=netbsd
 				;;
 			netwinder)
 				basic_machine=armv4l-rebel
-				os=linux
+				basic_os=linux
 				;;
 			news | news700 | news800 | news900)
 				basic_machine=m68k-sony
-				os=newsos
+				basic_os=newsos
 				;;
 			news1000)
 				basic_machine=m68030-sony
-				os=newsos
+				basic_os=newsos
 				;;
 			necv70)
 				basic_machine=v70-nec
-				os=sysv
+				basic_os=sysv
 				;;
 			nh3000)
 				basic_machine=m68k-harris
-				os=cxux
+				basic_os=cxux
 				;;
 			nh[45]000)
 				basic_machine=m88k-harris
-				os=cxux
+				basic_os=cxux
 				;;
 			nindy960)
 				basic_machine=i960-intel
-				os=nindy
+				basic_os=nindy
 				;;
 			mon960)
 				basic_machine=i960-intel
-				os=mon960
+				basic_os=mon960
 				;;
 			nonstopux)
 				basic_machine=mips-compaq
-				os=nonstopux
+				basic_os=nonstopux
 				;;
 			os400)
 				basic_machine=powerpc-ibm
-				os=os400
+				basic_os=os400
 				;;
 			OSE68000 | ose68000)
 				basic_machine=m68000-ericsson
-				os=ose
+				basic_os=ose
 				;;
 			os68k)
 				basic_machine=m68k-none
-				os=os68k
+				basic_os=os68k
 				;;
 			paragon)
 				basic_machine=i860-intel
-				os=osf
+				basic_os=osf
 				;;
 			parisc)
 				basic_machine=hppa-unknown
-				os=linux
+				basic_os=linux
+				;;
+			psp)
+				basic_machine=mipsallegrexel-sony
+				basic_os=psp
 				;;
 			pw32)
 				basic_machine=i586-unknown
-				os=pw32
+				basic_os=pw32
 				;;
 			rdos | rdos64)
 				basic_machine=x86_64-pc
-				os=rdos
+				basic_os=rdos
 				;;
 			rdos32)
 				basic_machine=i386-pc
-				os=rdos
+				basic_os=rdos
 				;;
 			rom68k)
 				basic_machine=m68k-rom68k
-				os=coff
+				basic_os=coff
 				;;
 			sa29200)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			sei)
 				basic_machine=mips-sei
-				os=seiux
+				basic_os=seiux
+				;;
+			sequent)
+				basic_machine=i386-sequent
+				basic_os=
 				;;
 			sps7)
 				basic_machine=m68k-bull
-				os=sysv2
+				basic_os=sysv2
+				;;
+			st2000)
+				basic_machine=m68k-tandem
+				basic_os=
 				;;
 			stratus)
 				basic_machine=i860-stratus
-				os=sysv4
+				basic_os=sysv4
+				;;
+			sun2)
+				basic_machine=m68000-sun
+				basic_os=
 				;;
 			sun2os3)
 				basic_machine=m68000-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun2os4)
 				basic_machine=m68000-sun
-				os=sunos4
+				basic_os=sunos4
+				;;
+			sun3)
+				basic_machine=m68k-sun
+				basic_os=
 				;;
 			sun3os3)
 				basic_machine=m68k-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun3os4)
 				basic_machine=m68k-sun
-				os=sunos4
+				basic_os=sunos4
+				;;
+			sun4)
+				basic_machine=sparc-sun
+				basic_os=
 				;;
 			sun4os3)
 				basic_machine=sparc-sun
-				os=sunos3
+				basic_os=sunos3
 				;;
 			sun4os4)
 				basic_machine=sparc-sun
-				os=sunos4
+				basic_os=sunos4
 				;;
 			sun4sol2)
 				basic_machine=sparc-sun
-				os=solaris2
+				basic_os=solaris2
+				;;
+			sun386 | sun386i | roadrunner)
+				basic_machine=i386-sun
+				basic_os=
 				;;
 			sv1)
 				basic_machine=sv1-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			symmetry)
 				basic_machine=i386-sequent
-				os=dynix
+				basic_os=dynix
 				;;
 			t3e)
 				basic_machine=alphaev5-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			t90)
 				basic_machine=t90-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			toad1)
 				basic_machine=pdp10-xkl
-				os=tops20
+				basic_os=tops20
 				;;
 			tpf)
 				basic_machine=s390x-ibm
-				os=tpf
+				basic_os=tpf
 				;;
 			udi29k)
 				basic_machine=a29k-amd
-				os=udi
+				basic_os=udi
 				;;
 			ultra3)
 				basic_machine=a29k-nyu
-				os=sym1
+				basic_os=sym1
 				;;
 			v810 | necv810)
 				basic_machine=v810-nec
-				os=none
+				basic_os=none
 				;;
 			vaxv)
 				basic_machine=vax-dec
-				os=sysv
+				basic_os=sysv
 				;;
 			vms)
 				basic_machine=vax-dec
-				os=vms
+				basic_os=vms
+				;;
+			vsta)
+				basic_machine=i386-pc
+				basic_os=vsta
 				;;
 			vxworks960)
 				basic_machine=i960-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			vxworks68)
 				basic_machine=m68k-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			vxworks29k)
 				basic_machine=a29k-wrs
-				os=vxworks
+				basic_os=vxworks
 				;;
 			xbox)
 				basic_machine=i686-pc
-				os=mingw32
+				basic_os=mingw32
 				;;
 			ymp)
 				basic_machine=ymp-cray
-				os=unicos
+				basic_os=unicos
 				;;
 			*)
 				basic_machine=$1
-				os=
+				basic_os=
 				;;
 		esac
 		;;
 esac
 
-# Decode aliases for certain CPU-COMPANY combinations.
+# Decode 1-component or ad-hoc basic machines
 case $basic_machine in
-	# Recognize the basic CPU types without company name.
-	# Some are omitted here because they have special meanings below.
-	1750a | 580 \
-	| a29k \
-	| aarch64 | aarch64_be \
-	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
-	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
-	| am33_2.0 \
-	| arc | arceb \
-	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \
-	| avr | avr32 \
-	| ba \
-	| be32 | be64 \
-	| bfin \
-	| c4x | c8051 | clipper | csky \
-	| d10v | d30v | dlx | dsp16xx \
-	| e2k | epiphany \
-	| fido | fr30 | frv | ft32 \
-	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
-	| hexagon \
-	| i370 | i860 | i960 | ia16 | ia64 \
-	| ip2k | iq2000 \
-	| k1om \
-	| le32 | le64 \
-	| lm32 \
-	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
-	| mips | mipsbe | mipseb | mipsel | mipsle \
-	| mips16 \
-	| mips64 | mips64el \
-	| mips64octeon | mips64octeonel \
-	| mips64orion | mips64orionel \
-	| mips64r5900 | mips64r5900el \
-	| mips64vr | mips64vrel \
-	| mips64vr4100 | mips64vr4100el \
-	| mips64vr4300 | mips64vr4300el \
-	| mips64vr5000 | mips64vr5000el \
-	| mips64vr5900 | mips64vr5900el \
-	| mipsisa32 | mipsisa32el \
-	| mipsisa32r2 | mipsisa32r2el \
-	| mipsisa32r6 | mipsisa32r6el \
-	| mipsisa64 | mipsisa64el \
-	| mipsisa64r2 | mipsisa64r2el \
-	| mipsisa64r6 | mipsisa64r6el \
-	| mipsisa64sb1 | mipsisa64sb1el \
-	| mipsisa64sr71k | mipsisa64sr71kel \
-	| mipsr5900 | mipsr5900el \
-	| mipstx39 | mipstx39el \
-	| mn10200 | mn10300 \
-	| moxie \
-	| mt \
-	| msp430 \
-	| nds32 | nds32le | nds32be \
-	| nfp \
-	| nios | nios2 | nios2eb | nios2el \
-	| ns16k | ns32k \
-	| open8 | or1k | or1knd | or32 \
-	| pdp10 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle \
-	| pru \
-	| pyramid \
-	| riscv | riscv32 | riscv64 \
-	| rl78 | rx \
-	| score \
-	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
-	| sh64 | sh64le \
-	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
-	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu \
-	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
-	| ubicom32 \
-	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
-	| visium \
-	| wasm32 \
-	| x86 | xc16x | xstormy16 | xtensa \
-	| z8k | z80)
-		basic_machine=$basic_machine-unknown
+	# Here we handle the default manufacturer of certain CPU types.  It is in
+	# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		cpu=hppa1.1
+		vendor=winbond
 		;;
-	c54x)
-		basic_machine=tic54x-unknown
+	op50n)
+		cpu=hppa1.1
+		vendor=oki
 		;;
-	c55x)
-		basic_machine=tic55x-unknown
+	op60c)
+		cpu=hppa1.1
+		vendor=oki
 		;;
-	c6x)
-		basic_machine=tic6x-unknown
+	ibm*)
+		cpu=i370
+		vendor=ibm
 		;;
-	leon|leon[3-9])
-		basic_machine=sparc-$basic_machine
+	orion105)
+		cpu=clipper
+		vendor=highlevel
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
-		basic_machine=$basic_machine-unknown
-		os=${os:-none}
+	mac | mpw | mac-mpw)
+		cpu=m68k
+		vendor=apple
 		;;
-	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
-		;;
-	m9s12z | m68hcs12z | hcs12z | s12z)
-		basic_machine=s12z-unknown
-		os=${os:-none}
-		;;
-	ms1)
-		basic_machine=mt-unknown
-		;;
-	strongarm | thumb | xscale)
-		basic_machine=arm-unknown
-		;;
-	xgate)
-		basic_machine=$basic_machine-unknown
-		os=${os:-none}
-		;;
-	xscaleeb)
-		basic_machine=armeb-unknown
+	pmac | pmac-mpw)
+		cpu=powerpc
+		vendor=apple
 		;;
 
-	xscaleel)
-		basic_machine=armel-unknown
-		;;
-
-	# We use `pc' rather than `unknown'
-	# because (1) that's what they normally are, and
-	# (2) the word "unknown" tends to confuse beginning users.
-	i*86 | x86_64)
-	  basic_machine=$basic_machine-pc
-	  ;;
-	# Recognize the basic CPU types with company name.
-	580-* \
-	| a29k-* \
-	| aarch64-* | aarch64_be-* \
-	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
-	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
-	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
-	| avr-* | avr32-* \
-	| ba-* \
-	| be32-* | be64-* \
-	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-	| c8051-* | clipper-* | craynv-* | csky-* | cydra-* \
-	| d10v-* | d30v-* | dlx-* \
-	| e2k-* | elxsi-* \
-	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
-	| h8300-* | h8500-* \
-	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
-	| hexagon-* \
-	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
-	| ip2k-* | iq2000-* \
-	| k1om-* \
-	| le32-* | le64-* \
-	| lm32-* \
-	| m32c-* | m32r-* | m32rle-* \
-	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
-	| microblaze-* | microblazeel-* \
-	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
-	| mips16-* \
-	| mips64-* | mips64el-* \
-	| mips64octeon-* | mips64octeonel-* \
-	| mips64orion-* | mips64orionel-* \
-	| mips64r5900-* | mips64r5900el-* \
-	| mips64vr-* | mips64vrel-* \
-	| mips64vr4100-* | mips64vr4100el-* \
-	| mips64vr4300-* | mips64vr4300el-* \
-	| mips64vr5000-* | mips64vr5000el-* \
-	| mips64vr5900-* | mips64vr5900el-* \
-	| mipsisa32-* | mipsisa32el-* \
-	| mipsisa32r2-* | mipsisa32r2el-* \
-	| mipsisa32r6-* | mipsisa32r6el-* \
-	| mipsisa64-* | mipsisa64el-* \
-	| mipsisa64r2-* | mipsisa64r2el-* \
-	| mipsisa64r6-* | mipsisa64r6el-* \
-	| mipsisa64sb1-* | mipsisa64sb1el-* \
-	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
-	| mipsr5900-* | mipsr5900el-* \
-	| mipstx39-* | mipstx39el-* \
-	| mmix-* \
-	| mt-* \
-	| msp430-* \
-	| nds32-* | nds32le-* | nds32be-* \
-	| nfp-* \
-	| nios-* | nios2-* | nios2eb-* | nios2el-* \
-	| none-* | np1-* | ns16k-* | ns32k-* \
-	| open8-* \
-	| or1k*-* \
-	| orion-* \
-	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
-	| pru-* \
-	| pyramid-* \
-	| riscv-* | riscv32-* | riscv64-* \
-	| rl78-* | romp-* | rs6000-* | rx-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
-	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
-	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
-	| tahoe-* \
-	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
-	| tile*-* \
-	| tron-* \
-	| ubicom32-* \
-	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
-	| vax-* \
-	| visium-* \
-	| wasm32-* \
-	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* \
-	| xstormy16-* | xtensa*-* \
-	| ymp-* \
-	| z8k-* | z80-*)
-		;;
-	# Recognize the basic CPU types without company name, with glob match.
-	xtensa*)
-		basic_machine=$basic_machine-unknown
-		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
 	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-		basic_machine=m68000-att
+		cpu=m68000
+		vendor=att
 		;;
 	3b*)
-		basic_machine=we32k-att
-		;;
-	abacus)
-		basic_machine=abacus-unknown
-		;;
-	alliant | fx80)
-		basic_machine=fx80-alliant
-		;;
-	altos | altos3068)
-		basic_machine=m68k-altos
-		;;
-	amd64)
-		basic_machine=x86_64-pc
-		;;
-	amd64-*)
-		basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	amiga | amiga-*)
-		basic_machine=m68k-unknown
-		;;
-	asmjs)
-		basic_machine=asmjs-unknown
-		;;
-	blackfin-*)
-		basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		os=linux
+		cpu=we32k
+		vendor=att
 		;;
 	bluegene*)
-		basic_machine=powerpc-ibm
-		os=cnk
-		;;
-	c54x-*)
-		basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	c55x-*)
-		basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	c6x-*)
-		basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	c90)
-		basic_machine=c90-cray
-		os=${os:-unicos}
-		;;
-	convex-c1)
-		basic_machine=c1-convex
-		os=bsd
-		;;
-	convex-c2)
-		basic_machine=c2-convex
-		os=bsd
-		;;
-	convex-c32)
-		basic_machine=c32-convex
-		os=bsd
-		;;
-	convex-c34)
-		basic_machine=c34-convex
-		os=bsd
-		;;
-	convex-c38)
-		basic_machine=c38-convex
-		os=bsd
-		;;
-	cr16 | cr16-*)
-		basic_machine=cr16-unknown
-		os=${os:-elf}
-		;;
-	crds | unos)
-		basic_machine=m68k-crds
-		;;
-	crisv32 | crisv32-* | etraxfs*)
-		basic_machine=crisv32-axis
-		;;
-	cris | cris-* | etrax*)
-		basic_machine=cris-axis
-		;;
-	crx)
-		basic_machine=crx-unknown
-		os=${os:-elf}
-		;;
-	da30 | da30-*)
-		basic_machine=m68k-da30
-		;;
-	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
-		basic_machine=mips-dec
+		cpu=powerpc
+		vendor=ibm
+		basic_os=cnk
 		;;
 	decsystem10* | dec10*)
-		basic_machine=pdp10-dec
-		os=tops10
+		cpu=pdp10
+		vendor=dec
+		basic_os=tops10
 		;;
 	decsystem20* | dec20*)
-		basic_machine=pdp10-dec
-		os=tops20
+		cpu=pdp10
+		vendor=dec
+		basic_os=tops20
 		;;
 	delta | 3300 | motorola-3300 | motorola-delta \
 	      | 3300-motorola | delta-motorola)
-		basic_machine=m68k-motorola
-		;;
-	dpx20 | dpx20-*)
-		basic_machine=rs6000-bull
-		os=${os:-bosx}
+		cpu=m68k
+		vendor=motorola
 		;;
 	dpx2*)
-		basic_machine=m68k-bull
-		os=sysv3
-		;;
-	e500v[12])
-		basic_machine=powerpc-unknown
-		os=$os"spe"
-		;;
-	e500v[12]-*)
-		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		os=$os"spe"
+		cpu=m68k
+		vendor=bull
+		basic_os=sysv3
 		;;
 	encore | umax | mmax)
-		basic_machine=ns32k-encore
+		cpu=ns32k
+		vendor=encore
 		;;
 	elxsi)
-		basic_machine=elxsi-elxsi
-		os=${os:-bsd}
+		cpu=elxsi
+		vendor=elxsi
+		basic_os=${basic_os:-bsd}
 		;;
 	fx2800)
-		basic_machine=i860-alliant
+		cpu=i860
+		vendor=alliant
 		;;
 	genix)
-		basic_machine=ns32k-ns
+		cpu=ns32k
+		vendor=ns
 		;;
 	h3050r* | hiux*)
-		basic_machine=hppa1.1-hitachi
-		os=hiuxwe2
-		;;
-	hp300-*)
-		basic_machine=m68k-hp
+		cpu=hppa1.1
+		vendor=hitachi
+		basic_os=hiuxwe2
 		;;
 	hp3k9[0-9][0-9] | hp9[0-9][0-9])
-		basic_machine=hppa1.0-hp
+		cpu=hppa1.0
+		vendor=hp
 		;;
 	hp9k2[0-9][0-9] | hp9k31[0-9])
-		basic_machine=m68000-hp
+		cpu=m68000
+		vendor=hp
 		;;
 	hp9k3[2-9][0-9])
-		basic_machine=m68k-hp
+		cpu=m68k
+		vendor=hp
 		;;
 	hp9k6[0-9][0-9] | hp6[0-9][0-9])
-		basic_machine=hppa1.0-hp
+		cpu=hppa1.0
+		vendor=hp
 		;;
 	hp9k7[0-79][0-9] | hp7[0-79][0-9])
-		basic_machine=hppa1.1-hp
+		cpu=hppa1.1
+		vendor=hp
 		;;
 	hp9k78[0-9] | hp78[0-9])
 		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
+		cpu=hppa1.1
+		vendor=hp
 		;;
 	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
 		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
+		cpu=hppa1.1
+		vendor=hp
 		;;
 	hp9k8[0-9][13679] | hp8[0-9][13679])
-		basic_machine=hppa1.1-hp
+		cpu=hppa1.1
+		vendor=hp
 		;;
 	hp9k8[0-9][0-9] | hp8[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	i370-ibm* | ibm*)
-		basic_machine=i370-ibm
+		cpu=hppa1.0
+		vendor=hp
 		;;
 	i*86v32)
-		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
-		os=sysv32
+		cpu=$(echo "$1" | sed -e 's/86.*/86/')
+		vendor=pc
+		basic_os=sysv32
 		;;
 	i*86v4*)
-		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
-		os=sysv4
+		cpu=$(echo "$1" | sed -e 's/86.*/86/')
+		vendor=pc
+		basic_os=sysv4
 		;;
 	i*86v)
-		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
-		os=sysv
+		cpu=$(echo "$1" | sed -e 's/86.*/86/')
+		vendor=pc
+		basic_os=sysv
 		;;
 	i*86sol2)
-		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
-		os=solaris2
+		cpu=$(echo "$1" | sed -e 's/86.*/86/')
+		vendor=pc
+		basic_os=solaris2
 		;;
 	j90 | j90-cray)
-		basic_machine=j90-cray
-		os=${os:-unicos}
+		cpu=j90
+		vendor=cray
+		basic_os=${basic_os:-unicos}
 		;;
 	iris | iris4d)
-		basic_machine=mips-sgi
-		case $os in
+		cpu=mips
+		vendor=sgi
+		case $basic_os in
 		    irix*)
 			;;
 		    *)
-			os=irix4
+			basic_os=irix4
 			;;
 		esac
 		;;
-	leon-*|leon[3-9]-*)
-		basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
-		;;
-	m68knommu-*)
-		basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		os=linux
-		;;
-	microblaze*)
-		basic_machine=microblaze-xilinx
-		;;
 	miniframe)
-		basic_machine=m68000-convergent
+		cpu=m68000
+		vendor=convergent
 		;;
 	*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
-		basic_machine=m68k-atari
-		os=mint
-		;;
-	mips3*-*)
-		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
-		;;
-	mips3*)
-		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
-		;;
-	ms1-*)
-		basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
+		cpu=m68k
+		vendor=atari
+		basic_os=mint
 		;;
 	news-3600 | risc-news)
-		basic_machine=mips-sony
-		os=newsos
+		cpu=mips
+		vendor=sony
+		basic_os=newsos
 		;;
 	next | m*-next)
-		basic_machine=m68k-next
-		case $os in
-		    nextstep* )
+		cpu=m68k
+		vendor=next
+		case $basic_os in
+		    openstep*)
+		        ;;
+		    nextstep*)
 			;;
 		    ns2*)
-		      os=nextstep2
+		      basic_os=nextstep2
 			;;
 		    *)
-		      os=nextstep3
+		      basic_os=nextstep3
 			;;
 		esac
 		;;
 	np1)
-		basic_machine=np1-gould
-		;;
-	neo-tandem)
-		basic_machine=neo-tandem
-		;;
-	nse-tandem)
-		basic_machine=nse-tandem
-		;;
-	nsr-tandem)
-		basic_machine=nsr-tandem
-		;;
-	nsv-tandem)
-		basic_machine=nsv-tandem
-		;;
-	nsx-tandem)
-		basic_machine=nsx-tandem
+		cpu=np1
+		vendor=gould
 		;;
 	op50n-* | op60c-*)
-		basic_machine=hppa1.1-oki
-		os=proelf
-		;;
-	openrisc | openrisc-*)
-		basic_machine=or32-unknown
+		cpu=hppa1.1
+		vendor=oki
+		basic_os=proelf
 		;;
 	pa-hitachi)
-		basic_machine=hppa1.1-hitachi
-		os=hiuxwe2
-		;;
-	parisc-*)
-		basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		os=linux
+		cpu=hppa1.1
+		vendor=hitachi
+		basic_os=hiuxwe2
 		;;
 	pbd)
-		basic_machine=sparc-tti
+		cpu=sparc
+		vendor=tti
 		;;
 	pbb)
-		basic_machine=m68k-tti
+		cpu=m68k
+		vendor=tti
 		;;
-	pc532 | pc532-*)
-		basic_machine=ns32k-pc532
-		;;
-	pc98)
-		basic_machine=i386-pc
-		;;
-	pc98-*)
-		basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	pentium | p5 | k5 | k6 | nexgen | viac3)
-		basic_machine=i586-pc
-		;;
-	pentiumpro | p6 | 6x86 | athlon | athlon_*)
-		basic_machine=i686-pc
-		;;
-	pentiumii | pentium2 | pentiumiii | pentium3)
-		basic_machine=i686-pc
-		;;
-	pentium4)
-		basic_machine=i786-pc
-		;;
-	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-		basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	pentiumpro-* | p6-* | 6x86-* | athlon-*)
-		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	pentium4-*)
-		basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+	pc532)
+		cpu=ns32k
+		vendor=pc532
 		;;
 	pn)
-		basic_machine=pn-gould
+		cpu=pn
+		vendor=gould
 		;;
-	power)	basic_machine=power-ibm
-		;;
-	ppc | ppcbe)	basic_machine=powerpc-unknown
-		;;
-	ppc-* | ppcbe-*)
-		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	ppcle | powerpclittle)
-		basic_machine=powerpcle-unknown
-		;;
-	ppcle-* | powerpclittle-*)
-		basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	ppc64)	basic_machine=powerpc64-unknown
-		;;
-	ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	ppc64le | powerpc64little)
-		basic_machine=powerpc64le-unknown
-		;;
-	ppc64le-* | powerpc64little-*)
-		basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+	power)
+		cpu=power
+		vendor=ibm
 		;;
 	ps2)
-		basic_machine=i386-ibm
+		cpu=i386
+		vendor=ibm
 		;;
 	rm[46]00)
-		basic_machine=mips-siemens
+		cpu=mips
+		vendor=siemens
 		;;
 	rtpc | rtpc-*)
-		basic_machine=romp-ibm
-		;;
-	s390 | s390-*)
-		basic_machine=s390-ibm
-		;;
-	s390x | s390x-*)
-		basic_machine=s390x-ibm
-		;;
-	sb1)
-		basic_machine=mipsisa64sb1-unknown
-		;;
-	sb1el)
-		basic_machine=mipsisa64sb1el-unknown
+		cpu=romp
+		vendor=ibm
 		;;
 	sde)
-		basic_machine=mipsisa32-sde
-		os=${os:-elf}
-		;;
-	sequent)
-		basic_machine=i386-sequent
-		;;
-	sh5el)
-		basic_machine=sh5le-unknown
+		cpu=mipsisa32
+		vendor=sde
+		basic_os=${basic_os:-elf}
 		;;
 	simso-wrs)
-		basic_machine=sparclite-wrs
-		os=vxworks
-		;;
-	spur)
-		basic_machine=spur-unknown
-		;;
-	st2000)
-		basic_machine=m68k-tandem
-		;;
-	strongarm-* | thumb-*)
-		basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
-		;;
-	sun2)
-		basic_machine=m68000-sun
-		;;
-	sun3 | sun3-*)
-		basic_machine=m68k-sun
-		;;
-	sun4)
-		basic_machine=sparc-sun
-		;;
-	sun386 | sun386i | roadrunner)
-		basic_machine=i386-sun
-		;;
-	tile*)
-		basic_machine=$basic_machine-unknown
-		os=linux-gnu
-		;;
-	tx39)
-		basic_machine=mipstx39-unknown
-		;;
-	tx39el)
-		basic_machine=mipstx39el-unknown
+		cpu=sparclite
+		vendor=wrs
+		basic_os=vxworks
 		;;
 	tower | tower-32)
-		basic_machine=m68k-ncr
+		cpu=m68k
+		vendor=ncr
 		;;
 	vpp*|vx|vx-*)
-		basic_machine=f301-fujitsu
+		cpu=f301
+		vendor=fujitsu
 		;;
-	w65*)
-		basic_machine=w65-wdc
-		os=none
+	w65)
+		cpu=w65
+		vendor=wdc
 		;;
 	w89k-*)
-		basic_machine=hppa1.1-winbond
-		os=proelf
-		;;
-	x64)
-		basic_machine=x86_64-pc
-		;;
-	xps | xps100)
-		basic_machine=xps100-honeywell
-		;;
-	xscale-* | xscalee[bl]-*)
-		basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
+		cpu=hppa1.1
+		vendor=winbond
+		basic_os=proelf
 		;;
 	none)
-		basic_machine=none-none
-		os=${os:-none}
+		cpu=none
+		vendor=none
+		;;
+	leon|leon[3-9])
+		cpu=sparc
+		vendor=$basic_machine
+		;;
+	leon-*|leon[3-9]-*)
+		cpu=sparc
+		vendor=$(echo "$basic_machine" | sed 's/-.*//')
 		;;
 
-# Here we handle the default manufacturer of certain CPU types.  It is in
-# some cases the only manufacturer, in others, it is the most popular.
-	w89k)
-		basic_machine=hppa1.1-winbond
+	*-*)
+		# shellcheck disable=SC2162
+		IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
 		;;
-	op50n)
-		basic_machine=hppa1.1-oki
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+		cpu=$basic_machine
+		vendor=pc
 		;;
-	op60c)
-		basic_machine=hppa1.1-oki
+	# These rules are duplicated from below for sake of the special case above;
+	# i.e. things that normalized to x86 arches should also default to "pc"
+	pc98)
+		cpu=i386
+		vendor=pc
 		;;
-	romp)
-		basic_machine=romp-ibm
+	x64 | amd64)
+		cpu=x86_64
+		vendor=pc
 		;;
-	mmix)
-		basic_machine=mmix-knuth
-		;;
-	rs6000)
-		basic_machine=rs6000-ibm
-		;;
-	vax)
-		basic_machine=vax-dec
-		;;
-	pdp11)
-		basic_machine=pdp11-dec
-		;;
-	we32k)
-		basic_machine=we32k-att
-		;;
-	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
-		basic_machine=sh-unknown
-		;;
-	cydra)
-		basic_machine=cydra-cydrome
-		;;
-	orion)
-		basic_machine=orion-highlevel
-		;;
-	orion105)
-		basic_machine=clipper-highlevel
-		;;
-	mac | mpw | mac-mpw)
-		basic_machine=m68k-apple
-		;;
-	pmac | pmac-mpw)
-		basic_machine=powerpc-apple
-		;;
-	*-unknown)
-		# Make sure to match an already-canonicalized machine name.
-		;;
+	# Recognize the basic CPU types without company name.
 	*)
-		echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
-		exit 1
+		cpu=$basic_machine
+		vendor=unknown
+		;;
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+	# Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+	# some cases the only manufacturer, in others, it is the most popular.
+	craynv-unknown)
+		vendor=cray
+		basic_os=${basic_os:-unicosmp}
+		;;
+	c90-unknown | c90-cray)
+		vendor=cray
+		basic_os=${Basic_os:-unicos}
+		;;
+	fx80-unknown)
+		vendor=alliant
+		;;
+	romp-unknown)
+		vendor=ibm
+		;;
+	mmix-unknown)
+		vendor=knuth
+		;;
+	microblaze-unknown | microblazeel-unknown)
+		vendor=xilinx
+		;;
+	rs6000-unknown)
+		vendor=ibm
+		;;
+	vax-unknown)
+		vendor=dec
+		;;
+	pdp11-unknown)
+		vendor=dec
+		;;
+	we32k-unknown)
+		vendor=att
+		;;
+	cydra-unknown)
+		vendor=cydrome
+		;;
+	i370-ibm*)
+		vendor=ibm
+		;;
+	orion-unknown)
+		vendor=highlevel
+		;;
+	xps-unknown | xps100-unknown)
+		cpu=xps100
+		vendor=honeywell
+		;;
+
+	# Here we normalize CPU types with a missing or matching vendor
+	dpx20-unknown | dpx20-bull)
+		cpu=rs6000
+		vendor=bull
+		basic_os=${basic_os:-bosx}
+		;;
+
+	# Here we normalize CPU types irrespective of the vendor
+	amd64-*)
+		cpu=x86_64
+		;;
+	blackfin-*)
+		cpu=bfin
+		basic_os=linux
+		;;
+	c54x-*)
+		cpu=tic54x
+		;;
+	c55x-*)
+		cpu=tic55x
+		;;
+	c6x-*)
+		cpu=tic6x
+		;;
+	e500v[12]-*)
+		cpu=powerpc
+		basic_os=${basic_os}"spe"
+		;;
+	mips3*-*)
+		cpu=mips64
+		;;
+	ms1-*)
+		cpu=mt
+		;;
+	m68knommu-*)
+		cpu=m68k
+		basic_os=linux
+		;;
+	m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+		cpu=s12z
+		;;
+	openrisc-*)
+		cpu=or32
+		;;
+	parisc-*)
+		cpu=hppa
+		basic_os=linux
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		cpu=i586
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+		cpu=i686
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		cpu=i686
+		;;
+	pentium4-*)
+		cpu=i786
+		;;
+	pc98-*)
+		cpu=i386
+		;;
+	ppc-* | ppcbe-*)
+		cpu=powerpc
+		;;
+	ppcle-* | powerpclittle-*)
+		cpu=powerpcle
+		;;
+	ppc64-*)
+		cpu=powerpc64
+		;;
+	ppc64le-* | powerpc64little-*)
+		cpu=powerpc64le
+		;;
+	sb1-*)
+		cpu=mipsisa64sb1
+		;;
+	sb1el-*)
+		cpu=mipsisa64sb1el
+		;;
+	sh5e[lb]-*)
+		cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
+		;;
+	spur-*)
+		cpu=spur
+		;;
+	strongarm-* | thumb-*)
+		cpu=arm
+		;;
+	tx39-*)
+		cpu=mipstx39
+		;;
+	tx39el-*)
+		cpu=mipstx39el
+		;;
+	x64-*)
+		cpu=x86_64
+		;;
+	xscale-* | xscalee[bl]-*)
+		cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
+		;;
+	arm64-*)
+		cpu=aarch64
+		;;
+
+	# Recognize the canonical CPU Types that limit and/or modify the
+	# company names they are paired with.
+	cr16-*)
+		basic_os=${basic_os:-elf}
+		;;
+	crisv32-* | etraxfs*-*)
+		cpu=crisv32
+		vendor=axis
+		;;
+	cris-* | etrax*-*)
+		cpu=cris
+		vendor=axis
+		;;
+	crx-*)
+		basic_os=${basic_os:-elf}
+		;;
+	neo-tandem)
+		cpu=neo
+		vendor=tandem
+		;;
+	nse-tandem)
+		cpu=nse
+		vendor=tandem
+		;;
+	nsr-tandem)
+		cpu=nsr
+		vendor=tandem
+		;;
+	nsv-tandem)
+		cpu=nsv
+		vendor=tandem
+		;;
+	nsx-tandem)
+		cpu=nsx
+		vendor=tandem
+		;;
+	mipsallegrexel-sony)
+		cpu=mipsallegrexel
+		vendor=sony
+		;;
+	tile*-*)
+		basic_os=${basic_os:-linux-gnu}
+		;;
+
+	*)
+		# Recognize the canonical CPU types that are allowed with any
+		# company name.
+		case $cpu in
+			1750a | 580 \
+			| a29k \
+			| aarch64 | aarch64_be \
+			| abacus \
+			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+			| alphapca5[67] | alpha64pca5[67] \
+			| am33_2.0 \
+			| amdgcn \
+			| arc | arceb \
+			| arm | arm[lb]e | arme[lb] | armv* \
+			| avr | avr32 \
+			| asmjs \
+			| ba \
+			| be32 | be64 \
+			| bfin | bpf | bs2000 \
+			| c[123]* | c30 | [cjt]90 | c4x \
+			| c8051 | clipper | craynv | csky | cydra \
+			| d10v | d30v | dlx | dsp16xx \
+			| e2k | elxsi | epiphany \
+			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+			| h8300 | h8500 \
+			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+			| hexagon \
+			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
+			| ip2k | iq2000 \
+			| k1om \
+			| le32 | le64 \
+			| lm32 \
+			| loongarch32 | loongarch64 | loongarchx32 \
+			| m32c | m32r | m32rle \
+			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+			| m88110 | m88k | maxq | mb | mcore | mep | metag \
+			| microblaze | microblazeel \
+			| mips | mipsbe | mipseb | mipsel | mipsle \
+			| mips16 \
+			| mips64 | mips64eb | mips64el \
+			| mips64octeon | mips64octeonel \
+			| mips64orion | mips64orionel \
+			| mips64r5900 | mips64r5900el \
+			| mips64vr | mips64vrel \
+			| mips64vr4100 | mips64vr4100el \
+			| mips64vr4300 | mips64vr4300el \
+			| mips64vr5000 | mips64vr5000el \
+			| mips64vr5900 | mips64vr5900el \
+			| mipsisa32 | mipsisa32el \
+			| mipsisa32r2 | mipsisa32r2el \
+			| mipsisa32r6 | mipsisa32r6el \
+			| mipsisa64 | mipsisa64el \
+			| mipsisa64r2 | mipsisa64r2el \
+			| mipsisa64r6 | mipsisa64r6el \
+			| mipsisa64sb1 | mipsisa64sb1el \
+			| mipsisa64sr71k | mipsisa64sr71kel \
+			| mipsr5900 | mipsr5900el \
+			| mipstx39 | mipstx39el \
+			| mmix \
+			| mn10200 | mn10300 \
+			| moxie \
+			| mt \
+			| msp430 \
+			| nds32 | nds32le | nds32be \
+			| nfp \
+			| nios | nios2 | nios2eb | nios2el \
+			| none | np1 | ns16k | ns32k | nvptx \
+			| open8 \
+			| or1k* \
+			| or32 \
+			| orion \
+			| picochip \
+			| pdp10 | pdp11 | pj | pjl | pn | power \
+			| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+			| pru \
+			| pyramid \
+			| riscv | riscv32 | riscv64 \
+			| rl78 | romp | rs6000 | rx \
+			| s390 | s390x \
+			| score \
+			| sh | shl \
+			| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+			| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+			| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+			| sparclite \
+			| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+			| spu \
+			| tahoe \
+			| thumbv7* \
+			| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+			| tron \
+			| ubicom32 \
+			| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+			| vax \
+			| visium \
+			| w65 \
+			| wasm32 | wasm64 \
+			| we32k \
+			| x86 | x86_64 | xc16x | xgate | xps100 \
+			| xstormy16 | xtensa* \
+			| ymp \
+			| z8k | z80)
+				;;
+
+			*)
+				echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+				exit 1
+				;;
+		esac
 		;;
 esac
 
 # Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
-	*-digital*)
-		basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
+case $vendor in
+	digital*)
+		vendor=dec
 		;;
-	*-commodore*)
-		basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
+	commodore*)
+		vendor=cbm
 		;;
 	*)
 		;;
@@ -1286,8 +1280,47 @@
 
 # Decode manufacturer-specific aliases for certain operating systems.
 
-if [ x$os != x ]
+if test x$basic_os != x
 then
+
+# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+	gnu/linux*)
+		kernel=linux
+		os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
+		;;
+	os2-emx)
+		kernel=os2
+		os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
+		;;
+	nto-qnx*)
+		kernel=nto
+		os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
+		;;
+	*-*)
+		# shellcheck disable=SC2162
+		IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+		;;
+	# Default OS when just kernel was specified
+	nto*)
+		kernel=nto
+		os=$(echo $basic_os | sed -e 's|nto|qnx|')
+		;;
+	linux*)
+		kernel=linux
+		os=$(echo $basic_os | sed -e 's|linux|gnu|')
+		;;
+	*)
+		kernel=
+		os=$basic_os
+		;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
 case $os in
 	# First match some system type aliases that might get confused
 	# with valid system types.
@@ -1299,7 +1332,7 @@
 		os=cnk
 		;;
 	solaris1 | solaris1.*)
-		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		os=$(echo $os | sed -e 's|solaris1|sunos4|')
 		;;
 	solaris)
 		os=solaris2
@@ -1307,9 +1340,6 @@
 	unixware*)
 		os=sysv4.2uw
 		;;
-	gnu/linux*)
-		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
-		;;
 	# es1800 is here to avoid being matched by es* (a different OS)
 	es1800*)
 		os=ose
@@ -1331,12 +1361,9 @@
 		os=sco3.2v4
 		;;
 	sco3.2.[4-9]*)
-		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		os=$(echo $os | sed -e 's/sco3.2./sco3.2v/')
 		;;
-	sco3.2v[4-9]* | sco5v6*)
-		# Don't forget version if it is 3.2v4 or newer.
-		;;
-	scout)
+	sco*v* | scout)
 		# Don't match below
 		;;
 	sco*)
@@ -1345,78 +1372,26 @@
 	psos*)
 		os=psos
 		;;
-	# Now accept the basic system types.
-	# The portable systems comes first.
-	# Each alternative MUST end in a * to match a version number.
-	# sysv* is not here because it comes later, after sysvr4.
-	gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
-	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
-	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
-	     | sym* | kopensolaris* | plan9* \
-	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
-	     | aos* | aros* | cloudabi* | sortix* \
-	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
-	     | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \
-	     | knetbsd* | mirbsd* | netbsd* \
-	     | bitrig* | openbsd* | solidbsd* | libertybsd* \
-	     | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
-	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
-	     | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
-	     | chorusrdb* | cegcc* | glidix* \
-	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
-	     | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
-	     | linux-newlib* | linux-musl* | linux-uclibc* \
-	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
-	     | interix* | uwin* | mks* | rhapsody* | darwin* \
-	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
-	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
-	     | os2* | vos* | palmos* | uclinux* | nucleus* \
-	     | morphos* | superux* | rtmk* | windiss* \
-	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
-	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
-	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
-	     | midnightbsd*)
-	# Remember, each alternative MUST END IN *, to match a version number.
-		;;
 	qnx*)
-		case $basic_machine in
-		    x86-* | i*86-*)
-			;;
-		    *)
-			os=nto-$os
-			;;
-		esac
+		os=qnx
 		;;
 	hiux*)
 		os=hiuxwe2
 		;;
-	nto-qnx*)
-		;;
-	nto*)
-		os=`echo $os | sed -e 's|nto|nto-qnx|'`
-		;;
-	sim | xray | os68k* | v88r* \
-	    | windows* | osx | abug | netware* | os9* \
-	    | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
-		;;
-	linux-dietlibc)
-		os=linux-dietlibc
-		;;
-	linux*)
-		os=`echo $os | sed -e 's|linux|linux-gnu|'`
-		;;
 	lynx*178)
 		os=lynxos178
 		;;
 	lynx*5)
 		os=lynxos5
 		;;
+	lynxos*)
+		# don't get caught up in next wildcard
+		;;
 	lynx*)
 		os=lynxos
 		;;
-	mac*)
-		os=`echo "$os" | sed -e 's|mac|macos|'`
+	mac[0-9]*)
+		os=$(echo "$os" | sed -e 's|mac|macos|')
 		;;
 	opened*)
 		os=openedition
@@ -1425,10 +1400,10 @@
 		os=os400
 		;;
 	sunos5*)
-		os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+		os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
 		;;
 	sunos6*)
-		os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+		os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
 		;;
 	wince*)
 		os=wince
@@ -1460,12 +1435,9 @@
 	ns2)
 		os=nextstep2
 		;;
-	nsk*)
-		os=nsk
-		;;
 	# Preserve the version number of sinix5.
 	sinix5.*)
-		os=`echo $os | sed -e 's|sinix|sysv|'`
+		os=$(echo $os | sed -e 's|sinix|sysv|')
 		;;
 	sinix*)
 		os=sysv4
@@ -1488,18 +1460,12 @@
 	sysvr4)
 		os=sysv4
 		;;
-	# This must come after sysvr4.
-	sysv*)
-		;;
 	ose*)
 		os=ose
 		;;
 	*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
 		os=mint
 		;;
-	zvmoe)
-		os=zvmoe
-		;;
 	dicos*)
 		os=dicos
 		;;
@@ -1507,7 +1473,7 @@
 		# Until real need of OS specific support for
 		# particular features comes up, bare metal
 		# configurations are quite functional.
-		case $basic_machine in
+		case $cpu in
 		    arm*)
 			os=eabi
 			;;
@@ -1516,19 +1482,11 @@
 			;;
 		esac
 		;;
-	nacl*)
-		;;
-	ios)
-		;;
-	none)
-		;;
-	*-eabi)
-		;;
 	*)
-		echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
-		exit 1
+		# No normalization, but not necessarily accepted, that comes below.
 		;;
 esac
+
 else
 
 # Here we handle the default operating systems that come with various machines.
@@ -1541,7 +1499,8 @@
 # will signal an error saying that MANUFACTURER isn't an operating
 # system, and we'll never get to this point.
 
-case $basic_machine in
+kernel=
+case $cpu-$vendor in
 	score-*)
 		os=elf
 		;;
@@ -1552,7 +1511,8 @@
 		os=riscix1.2
 		;;
 	arm*-rebel)
-		os=linux
+		kernel=linux
+		os=gnu
 		;;
 	arm*-semi)
 		os=aout
@@ -1718,86 +1678,173 @@
 		os=none
 		;;
 esac
+
 fi
 
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer.  We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
-	*-unknown)
-		case $os in
-			riscix*)
-				vendor=acorn
-				;;
-			sunos*)
-				vendor=sun
-				;;
-			cnk*|-aix*)
-				vendor=ibm
-				;;
-			beos*)
-				vendor=be
-				;;
-			hpux*)
-				vendor=hp
-				;;
-			mpeix*)
-				vendor=hp
-				;;
-			hiux*)
-				vendor=hitachi
-				;;
-			unos*)
-				vendor=crds
-				;;
-			dgux*)
-				vendor=dg
-				;;
-			luna*)
-				vendor=omron
-				;;
-			genix*)
-				vendor=ns
-				;;
-			clix*)
-				vendor=intergraph
-				;;
-			mvs* | opened*)
-				vendor=ibm
-				;;
-			os400*)
-				vendor=ibm
-				;;
-			ptx*)
-				vendor=sequent
-				;;
-			tpf*)
-				vendor=ibm
-				;;
-			vxsim* | vxworks* | windiss*)
-				vendor=wrs
-				;;
-			aux*)
-				vendor=apple
-				;;
-			hms*)
-				vendor=hitachi
-				;;
-			mpw* | macos*)
-				vendor=apple
-				;;
-			*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
-				vendor=atari
-				;;
-			vos*)
-				vendor=stratus
-				;;
-		esac
-		basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+	# Sometimes we do "kernel-abi", so those need to count as OSes.
+	musl* | newlib* | uclibc*)
+		;;
+	# Likewise for "kernel-libc"
+	eabi | eabihf | gnueabi | gnueabihf)
+		;;
+	# Now accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST end in a * to match a version number.
+	gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
+	     | hiux* | abug | nacl* | netware* | windows* \
+	     | os9* | macos* | osx* | ios* \
+	     | mpw* | magic* | mmixware* | mon960* | lnews* \
+	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
+	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+	     | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
+	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
+	     | chorusrdb* | cegcc* | glidix* \
+	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+	     | midipix* | mingw32* | mingw64* | mint* \
+	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+	     | interix* | uwin* | mks* | rhapsody* | darwin* \
+	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
+	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
+	     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+	     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
+		;;
+	# This one is extra strict with allowed versions
+	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		;;
+	none)
+		;;
+	*)
+		echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+		exit 1
 		;;
 esac
 
-echo "$basic_machine-$os"
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
+		;;
+	uclinux-uclibc* )
+		;;
+	-dietlibc* | -newlib* | -musl* | -uclibc* )
+		# These are just libc implementations, not actual OSes, and thus
+		# require a kernel.
+		echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+		exit 1
+		;;
+	kfreebsd*-gnu* | kopensolaris*-gnu*)
+		;;
+	nto-qnx*)
+		;;
+	os2-emx)
+		;;
+	*-eabi* | *-gnueabi*)
+		;;
+	-*)
+		# Blank kernel with real OS is always fine.
+		;;
+	*-*)
+		echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+		exit 1
+		;;
+esac
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+case $vendor in
+	unknown)
+		case $cpu-$os in
+			*-riscix*)
+				vendor=acorn
+				;;
+			*-sunos*)
+				vendor=sun
+				;;
+			*-cnk* | *-aix*)
+				vendor=ibm
+				;;
+			*-beos*)
+				vendor=be
+				;;
+			*-hpux*)
+				vendor=hp
+				;;
+			*-mpeix*)
+				vendor=hp
+				;;
+			*-hiux*)
+				vendor=hitachi
+				;;
+			*-unos*)
+				vendor=crds
+				;;
+			*-dgux*)
+				vendor=dg
+				;;
+			*-luna*)
+				vendor=omron
+				;;
+			*-genix*)
+				vendor=ns
+				;;
+			*-clix*)
+				vendor=intergraph
+				;;
+			*-mvs* | *-opened*)
+				vendor=ibm
+				;;
+			*-os400*)
+				vendor=ibm
+				;;
+			s390-* | s390x-*)
+				vendor=ibm
+				;;
+			*-ptx*)
+				vendor=sequent
+				;;
+			*-tpf*)
+				vendor=ibm
+				;;
+			*-vxsim* | *-vxworks* | *-windiss*)
+				vendor=wrs
+				;;
+			*-aux*)
+				vendor=apple
+				;;
+			*-hms*)
+				vendor=hitachi
+				;;
+			*-mpw* | *-macos*)
+				vendor=apple
+				;;
+			*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
+				vendor=atari
+				;;
+			*-vos*)
+				vendor=stratus
+				;;
+		esac
+		;;
+esac
+
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
 exit
 
 # Local variables:
diff --git a/configure b/configure
index 9a8c158..fd57219 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pcap 1.9.0-PRE-GIT.
+# Generated by GNU Autoconf 2.69 for pcap 1.10.0.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@
 # Identity of this package.
 PACKAGE_NAME='pcap'
 PACKAGE_TARNAME='pcap'
-PACKAGE_VERSION='1.9.0-PRE-GIT'
-PACKAGE_STRING='pcap 1.9.0-PRE-GIT'
+PACKAGE_VERSION='1.10.0'
+PACKAGE_STRING='pcap 1.10.0'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -623,20 +623,13 @@
 INSTALL_DATA
 INSTALL_SCRIPT
 INSTALL_PROGRAM
-RDMA_SRC
 PCAP_SUPPORT_RDMASNIFF
-DBUS_SRC
 PCAP_SUPPORT_DBUS
-PKGCONFIG
-BT_MONITOR_SRC
-BT_SRC
 PCAP_SUPPORT_BT
-NETMAP_SRC
+PCAP_SUPPORT_DPDK
 PCAP_SUPPORT_NETMAP
-NETFILTER_SRC
 PCAP_SUPPORT_NETFILTER
-USB_SRC
-PCAP_SUPPORT_USB
+PCAP_SUPPORT_LINUX_USBMON
 EXTRA_NETWORK_LIBS
 RPCAPD_LIBS
 INSTALL_RPCAPD
@@ -645,8 +638,12 @@
 MAN_ADMIN_COMMANDS
 MAN_MISC_INFO
 MAN_FILE_FORMATS
+MAN_DEVICES
 DYEXT
-SSRC
+REMOTE_C_SRC
+MODULE_C_SRC
+PLATFORM_CXX_SRC
+PLATFORM_C_SRC
 ADDLARCHIVEOBJS
 ADDLOBJS
 V_YACC
@@ -655,28 +652,34 @@
 V_SHLIB_OPT
 V_SHLIB_CMD
 V_SHLIB_CCOPT
-V_PCAP
 V_LEX
 V_INCLS
-V_FINDALLDEVS
 V_DEFS
+V_PROG_LDFLAGS_FAT
+V_PROG_CCOPT_FAT
+V_LIB_LDFLAGS_FAT
+V_LIB_CCOPT_FAT
 V_CCOPT
 MKDEP
 DEPENDENCY_CFLAG
 LN_S
 AR
 RANLIB
+REENTRANT_PARSER
 YFLAGS
 YACC
 LEXLIB
 LEX_OUTPUT_ROOT
 LEX
-PCAP_SUPPORT_PACKET_RING
+PKGCONFIG
 VALGRINDTEST_SRC
 LIBOBJS
 EGREP
 GREP
 CPP
+ac_ct_CXX
+CXXFLAGS
+CXX
 OBJEXT
 EXEEXT
 ac_ct_CC
@@ -716,6 +719,7 @@
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -741,10 +745,8 @@
 with_gcc
 enable_largefile
 enable_protochain
-with_sita
 with_pcap
 with_libnl
-enable_packet_ring
 enable_ipv6
 with_dag
 with_dag_includes
@@ -761,6 +763,7 @@
 enable_shared
 enable_usb
 enable_netmap
+with_dpdk
 enable_bluetooth
 enable_dbus
 enable_rdma
@@ -773,6 +776,9 @@
 LDFLAGS
 LIBS
 CPPFLAGS
+CXX
+CXXFLAGS
+CCC
 CPP
 YACC
 YFLAGS'
@@ -814,6 +820,7 @@
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1066,6 +1073,15 @@
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1203,7 +1219,7 @@
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1316,7 +1332,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures pcap 1.9.0-PRE-GIT to adapt to many kinds of systems.
+\`configure' configures pcap 1.10.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1356,6 +1372,7 @@
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1382,7 +1399,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pcap 1.9.0-PRE-GIT:";;
+     short | recursive ) echo "Configuration of pcap 1.10.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1392,7 +1409,6 @@
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-largefile     omit support for large files
   --disable-protochain    disable \"protochain\" insn
-  --enable-packet-ring    enable packet ring support on Linux [default=yes]
   --enable-ipv6           build IPv6-capable version [default=yes]
   --enable-remote         enable remote packet capture [default=no]
   --disable-remote        disable remote packet capture
@@ -1401,8 +1417,8 @@
   --disable-universal     don't build universal on macOS
   --enable-shared         build shared libraries [default=yes, if support
                           available]
-  --enable-usb            enable USB capture support [default=yes, if support
-                          available]
+  --enable-usb            enable Linux usbmon USB capture support
+                          [default=yes, if support available]
   --enable-netmap         enable netmap support [default=yes, if support
                           available]
   --enable-bluetooth      enable Bluetooth support [default=yes, if support
@@ -1416,7 +1432,6 @@
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --without-gcc           don't use gcc
-  --with-sita             include SITA support
   --with-pcap=TYPE        use packet capture TYPE
   --without-libnl         disable libnl support [default=yes, on Linux, if
                           present]
@@ -1437,6 +1452,8 @@
   --with-turbocap[=DIR]   include Riverbed TurboCap support (located in
                           directory DIR, if supplied). [default=yes, if
                           present]
+  --with-dpdk[=DIR]       include DPDK support (located in directory DIR, if
+                          supplied). [default=yes, if present]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1446,6 +1463,8 @@
   LIBS        libraries to pass to the linker, e.g. -l<library>
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
   CPP         C preprocessor
   YACC        The `Yet Another Compiler Compiler' implementation to use.
               Defaults to the first program found out of: `bison -y', `byacc',
@@ -1520,7 +1539,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pcap configure 1.9.0-PRE-GIT
+pcap configure 1.10.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1572,6 +1591,44 @@
 
 } # ac_fn_c_try_compile
 
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
 # ac_fn_c_try_link LINENO
 # -----------------------
 # Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -2042,7 +2099,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by pcap $as_me 1.9.0-PRE-GIT, which was
+It was created by pcap $as_me 1.10.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2607,8 +2664,9 @@
     fi
 
 #
-# Try to enable as many C99 features as we can.
-# At minimum, we want C++/C99-style // comments.
+# We require C99 or later.
+# Try to get it, which may involve adding compiler flags;
+# if that fails, give up.
 #
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -3576,6 +3634,274 @@
 fi
 
 
+if test "$ac_cv_prog_cc_c99" = "no"; then
+	as_fn_error $? "The C compiler does not support C99" "$LINENO" 5
+fi
+case "$host_os" in
+haiku*)
+	#
+	# Haiku's platform file is in C++.
+	#
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$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_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # 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_CXX="$ac_tool_prefix$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
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+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_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$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
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	;;
+esac
+
 
 
 
@@ -3997,8 +4323,8 @@
 	    aix*)
 		    ;;
 
-	    freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
-	    	    #
+	    freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|haiku*|midipix*)
+		    #
 		    # Platforms where the linker is the GNU linker
 		    # or accepts command-line arguments like
 		    # those the GNU linker accepts.
@@ -4014,7 +4340,7 @@
 		    sparc64*)
 			case "$host_os" in
 
-			freebsd*|openbsd*)
+			freebsd*|openbsd*|linux*)
 			    PIC_OPT=-fPIC
 			    ;;
 			esac
@@ -4027,7 +4353,7 @@
 
 	    hpux*)
 		    V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
-	    	    #
+		    #
 		    # XXX - this assumes GCC is using the HP linker,
 		    # rather than the GNU linker, and that the "+h"
 		    # option is used on all HP-UX platforms, both .sl
@@ -4035,7 +4361,7 @@
 		    #
 		    V_SONAME_OPT="-Wl,+h,"
 		    #
-		    # By default, directories specifed with -L
+		    # By default, directories specified with -L
 		    # are added to the run-time search path, so
 		    # we don't add them in pcap-config.
 		    #
@@ -4096,14 +4422,14 @@
 		    V_SHLIB_OPT="-b"
 		    V_SONAME_OPT="+h "
 		    #
-		    # By default, directories specifed with -L
+		    # By default, directories specified with -L
 		    # are added to the run-time search path, so
 		    # we don't add them in pcap-config.
 		    #
 		    ;;
 
 	    osf*)
-	    	    #
+		    #
 		    # Presumed to be DEC OSF/1, Digital UNIX, or
 		    # Tru64 UNIX.
 		    #
@@ -4214,7 +4540,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4260,7 +4586,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4284,7 +4610,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4329,7 +4655,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4353,7 +4679,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4855,7 +5181,7 @@
 done
 
 
-for ac_header in sys/ioccom.h sys/sockio.h limits.h
+for ac_header in sys/ioccom.h sys/sockio.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"
@@ -4931,24 +5257,11 @@
 fi
 
 case "$host_os" in
-linux*|uclinux*)
-	for ac_header in linux/sockios.h linux/if_bonding.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
-#include <sys/socket.h>
-#include <linux/if.h>
-
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
+haiku*)
+	#
+	# Haiku needs _BSD_SOURCE for the _IO* macros because it doesn't use them.
+	#
+	CFLAGS="$CFLAGS -D_BSD_SOURCE"
 	;;
 esac
 
@@ -4998,21 +5311,118 @@
 	    fi
     fi
 
-for ac_func in strerror strerror_r strerror_s strlcpy strlcat
+for ac_func in strerror
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes; then :
+
+	#
+	# We have strerror_r; if we define _GNU_SOURCE, is it a
+	# POSIX-compliant strerror_r() or a GNU strerror_r()?
+	#
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r is GNU-style" >&5
+$as_echo_n "checking whether strerror_r is GNU-style... " >&6; }
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+		#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+	return 0;
+}
+
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	        # GNU-style
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_GNU_STRERROR_R /**/" >>confdefs.h
+
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define HAVE_POSIX_STRERROR_R /**/" >>confdefs.h
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+else
+
+	#
+	# We don't have strerror_r; do we have _wcserror_s?
+	#
+	for ac_func in _wcserror_s
+do :
+  ac_fn_c_check_func "$LINENO" "_wcserror_s" "ac_cv_func__wcserror_s"
+if test "x$ac_cv_func__wcserror_s" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE__WCSERROR_S 1
 _ACEOF
 
 fi
 done
 
 
-needsnprintf=no
-for ac_func in vsnprintf snprintf
+fi
+
+
+#
+# Thanks, IBM, for not providing vsyslog() in AIX!
+#
+for ac_func in vsyslog
+do :
+  ac_fn_c_check_func "$LINENO" "vsyslog" "ac_cv_func_vsyslog"
+if test "x$ac_cv_func_vsyslog" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VSYSLOG 1
+_ACEOF
+
+fi
+done
+
+
+#
+# Make sure we have vsnprintf() and snprintf(); we require them.
+#
+ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
+if test "x$ac_cv_func_vsnprintf" = xyes; then :
+
+else
+  as_fn_error $? "vsnprintf() is required but wasn't found" "$LINENO" 5
+fi
+
+ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf"
+if test "x$ac_cv_func_snprintf" = xyes; then :
+
+else
+  as_fn_error $? "snprintf() is required but wasn't found" "$LINENO" 5
+fi
+
+
+needasprintf=no
+for ac_func in vasprintf asprintf
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -5022,14 +5432,60 @@
 _ACEOF
 
 else
-  needsnprintf=yes
+  needasprintf=yes
 fi
 done
 
-if test $needsnprintf = yes; then
+if test $needasprintf = yes; then
 	case " $LIBOBJS " in
-  *" snprintf.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+  *" asprintf.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS asprintf.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrlcat=no
+for ac_func in strlcat
+do :
+  ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
+if test "x$ac_cv_func_strlcat" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCAT 1
+_ACEOF
+
+else
+  needstrlcat=yes
+fi
+done
+
+if test $needstrlcat = yes; then
+	case " $LIBOBJS " in
+  *" strlcat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strlcat.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrlcpy=no
+for ac_func in strlcpy
+do :
+  ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCPY 1
+_ACEOF
+
+else
+  needstrlcpy=yes
+fi
+done
+
+if test $needstrlcpy = yes; then
+	case " $LIBOBJS " in
+  *" strlcpy.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext"
  ;;
 esac
 
@@ -5156,10 +5612,58 @@
 
 else
 
-	    #
-	    # We didn't find it.
-	    #
-	    as_fn_error $? "getaddrinfo is required, but wasn't found" "$LINENO" 5
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in -lnetwork" >&5
+$as_echo_n "checking for getaddrinfo in -lnetwork... " >&6; }
+if ${ac_cv_lib_network_getaddrinfo+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetwork  $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 getaddrinfo ();
+int
+main ()
+{
+return getaddrinfo ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_network_getaddrinfo=yes
+else
+  ac_cv_lib_network_getaddrinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_getaddrinfo" >&5
+$as_echo "$ac_cv_lib_network_getaddrinfo" >&6; }
+if test "x$ac_cv_lib_network_getaddrinfo" = xyes; then :
+
+		    #
+		    # OK, we found it in libnetwork on Haiku.
+		    #
+		    LIBS="-lnetwork $LIBS"
+
+else
+
+		    #
+		    # We didn't find it.
+		    #
+		    as_fn_error $? "getaddrinfo is required, but wasn't found" "$LINENO" 5
+
+fi
+
 
 fi
 
@@ -5902,25 +6406,6 @@
 #
 VALGRINDTEST_SRC=
 
-#
-# SITA support is mutually exclusive with native capture support;
-# "--with-sita" selects SITA support.
-#
-
-# Check whether --with-sita was given.
-if test "${with_sita+set}" = set; then :
-  withval=$with_sita;
-	if test ! "x$withval" = "xno" ; then
-
-$as_echo "#define SITA 1" >>confdefs.h
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5
-$as_echo "$as_me: Enabling SITA ACN support" >&6;}
-		V_PCAP=sita
-	fi
-
-else
-
 
 # Check whether --with-pcap was given.
 if test "${with_pcap+set}" = set; then :
@@ -5962,6 +6447,10 @@
 		#  requires that various BSD-style integer types
 		#  be defined;
 		#
+		#  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+		#  doesn't include it but does use struct timeval
+		#  in ioctl definitions;
+		#
 		#  sys/ioctl.h and, if we have it, sys/ioccom.h,
 		#  because net/bpf.h defines ioctls;
 		#
@@ -5984,6 +6473,7 @@
 /* end confdefs.h.  */
 
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #ifdef HAVE_SYS_IOCCOM_H
@@ -6050,6 +6540,18 @@
 
 done
 
+	for ac_header in config/HaikuConfig.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "config/HaikuConfig.h" "ac_cv_header_config_HaikuConfig_h" "$ac_includes_default"
+if test "x$ac_cv_header_config_HaikuConfig_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CONFIG_HAIKUCONFIG_H 1
+_ACEOF
+
+fi
+
+done
+
 
 	if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
 		#
@@ -6075,11 +6577,6 @@
 		# No prizes for guessing this one.
 		#
 		V_PCAP=linux
-
-		#
-		# XXX - this won't work with older kernels that have
-		# SOCK_PACKET sockets but not PF_PACKET sockets.
-		#
 		VALGRINDTEST_SRC=valgrindtest.c
 	elif test "$ac_cv_header_net_pfilt_h" = yes; then
 	        #
@@ -6111,6 +6608,11 @@
 		# DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
 		#
 		V_PCAP=dlpi
+	elif test "$ac_cv_header_config_HaikuConfig_h" = yes; then
+		#
+		# Haiku.
+		#
+		V_PCAP=haiku
 	else
 		#
 		# Nothing we support.
@@ -6129,16 +6631,53 @@
 
 
 #
-# Do capture-mechanism-dependent tests.
+# Do we have pkg-config?
+#
+# Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PKGCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$PKGCONFIG"; then
+  ac_cv_prog_PKGCONFIG="$PKGCONFIG" # 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_PKGCONFIG="pkg-config"
+    $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
+
+  test -z "$ac_cv_prog_PKGCONFIG" && ac_cv_prog_PKGCONFIG="no"
+fi
+fi
+PKGCONFIG=$ac_cv_prog_PKGCONFIG
+if test -n "$PKGCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
+$as_echo "$PKGCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+#
+# Handle each capture type.
 #
 case "$V_PCAP" in
 dlpi)
 	#
-	# Needed for common functions used by pcap-[dlpi,libdlpi].c
-	#
- 	SSRC="dlpisubs.c"
-
-	#
 	# Checks for some header files.
 	#
 	for ac_header in sys/bufmod.h sys/dlpi_ext.h
@@ -6166,7 +6705,7 @@
 	# Also, due to the bug above applications that link to libpcap with
 	# libdlpi will have to add "-L/lib" option to "configure".
 	#
-	saved_ldflags=$LDFLAGS
+	save_LDFLAGS="$LDFLAGS"
 	LDFLAGS="$LIBS -L/lib"
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
 $as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
@@ -6209,14 +6748,28 @@
 			LIBS="-ldlpi $LIBS"
 			V_PCAP=libdlpi
 
+			#
+			# Capture module plus common code needed for
+			# common functions used by pcap-[dlpi,libdlpi].c
+			#
+			PLATFORM_C_SRC="pcap-libdlpi.c dlpisubs.c"
+
 $as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h
 
 
 else
-  V_PCAP=dlpi
+
+			V_PCAP=dlpi
+
+			#
+			# Capture module plus common code needed for
+			# common functions used by pcap-[dlpi,libdlpi].c
+			#
+			PLATFORM_C_SRC="pcap-dlpi.c dlpisubs.c"
+
 fi
 
-	LDFLAGS=$saved_ldflags
+	LDFLAGS="$save_LDFLAGS"
 
 	#
 	# Checks whether <sys/dlpi.h> is usable, to catch weird SCO
@@ -6278,8 +6831,44 @@
 
 	;;
 
+enet)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-enet.c"
+	;;
+
+haiku)
+	#
+	# Capture module
+	#
+ 	PLATFORM_CXX_SRC="pcap-haiku.cpp"
+
+	#
+	# Just for the sake of it.
+	#
+	for ac_header in net/if.h net/if_dl.h net/if_types.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+	;;
+
 linux)
 	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-linux.c"
+
+	#
 	# Do we have the wireless extensions?
 	#
 	for ac_header in linux/wireless.h
@@ -6302,6 +6891,12 @@
 
 	#
 	# Do we have libnl?
+	# We only want version 3.  Version 2 was, apparently,
+	# short-lived, and version 1 is source and binary
+	# incompatible with version 3, and it appears that,
+	# these days, everybody's using version 3.  We're
+	# not supporting older versions of the Linux kernel;
+	# let's drop support for older versions of libnl, too.
 	#
 
 # Check whether --with-libnl was given.
@@ -6313,27 +6908,51 @@
 
 
 	if test x$with_libnl != xno ; then
-		have_any_nl="no"
+		if test "x$PKGCONFIG" != "xno"; then
+			#
+			# We have pkg-config; see if we have libnl-genl-3.0
+			# as a package.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnl-genl-3.0 with pkg-config" >&5
+$as_echo_n "checking for libnl-genl-3.0 with pkg-config... " >&6; }
+			if "$PKGCONFIG" libnl-genl-3.0; then
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+				pkg_config_found_libnl=yes
+				libnl_genl_cflags=`"$PKGCONFIG" --cflags libnl-genl-3.0`
+				V_INCLS="$V_INCLS ${libnl_genl_cflags}"
+				libnl_genl_libs=`"$PKGCONFIG" --libs libnl-genl-3.0`
+				LIBS="${libnl_genl_libs} $LIBS"
 
-                incdir=-I/usr/include/libnl3
-                libnldir=
-                case "$with_libnl" in
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
 
-                yes|if_available)
-                  ;;
+			else
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+			fi
+		fi
 
-                *)
-                  if test -d $withval; then
-                    libnldir=-L${withval}/lib/.libs
-                    incdir=-I${withval}/include
-                  fi
-                  ;;
-                esac
+		if test x$pkg_config_found_libnl != xyes; then
+			#
+			# OK, either we don't have pkg-config or there
+			# wasn't a .pc file for it; Check for it directly.
+			#
+			case "$with_libnl" in
 
-		#
-		# Try libnl 3.x first.
-		#
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl-3" >&5
+			yes|if_available)
+				incdir=-I/usr/include/libnl3
+				libnldir=
+				;;
+
+			*)
+				if test -d $withval; then
+					libnldir=-L${withval}/lib
+					incdir=-I${withval}/include
+				fi
+				;;
+			esac
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl-3" >&5
 $as_echo_n "checking for nl_socket_alloc in -lnl-3... " >&6; }
 if ${ac_cv_lib_nl_3_nl_socket_alloc+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -6371,195 +6990,31 @@
 $as_echo "$ac_cv_lib_nl_3_nl_socket_alloc" >&6; }
 if test "x$ac_cv_lib_nl_3_nl_socket_alloc" = xyes; then :
 
-			#
-			# Yes, we have libnl 3.x.
-			#
-			LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
+				#
+				# Yes, we have libnl 3.x.
+				#
+				LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
 
 $as_echo "#define HAVE_LIBNL 1" >>confdefs.h
 
+				V_INCLS="$V_INCLS ${incdir}"
 
-$as_echo "#define HAVE_LIBNL_3_x 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
-
-			V_INCLS="$V_INCLS ${incdir}"
-			have_any_nl="yes"
-
-fi
-
-
-		if test x$have_any_nl = xno ; then
-			#
-			# Try libnl 2.x
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5
-$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; }
-if ${ac_cv_lib_nl_nl_socket_alloc+:} false; then :
-  $as_echo_n "(cached) " >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char nl_socket_alloc ();
-int
-main ()
-{
-return nl_socket_alloc ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_nl_nl_socket_alloc=yes
-else
-  ac_cv_lib_nl_nl_socket_alloc=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_socket_alloc" >&5
-$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; }
-if test "x$ac_cv_lib_nl_nl_socket_alloc" = xyes; then :
 
 				#
-				# Yes, we have libnl 2.x.
+				# No, we don't have libnl at all.
+				# Fail if the user explicitly requested
+				# it.
 				#
-				LIBS="${libnldir} -lnl-genl -lnl $LIBS"
-
-$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
-
-				have_any_nl="yes"
+				if test x$with_libnl = xyes ; then
+					as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
+				fi
 
 fi
 
 		fi
-
-		if test x$have_any_nl = xno ; then
-			#
-			# No, we don't; do we have libnl 1.x?
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
-$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
-if ${ac_cv_lib_nl_nl_handle_alloc+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char nl_handle_alloc ();
-int
-main ()
-{
-return nl_handle_alloc ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_nl_nl_handle_alloc=yes
-else
-  ac_cv_lib_nl_nl_handle_alloc=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
-$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
-if test "x$ac_cv_lib_nl_nl_handle_alloc" = xyes; then :
-
-				#
-				# Yes.
-				#
-				LIBS="${libnldir} -lnl $LIBS"
-
-$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
-
-				have_any_nl="yes"
-
-fi
-
-		fi
-
-		if test x$have_any_nl = xno ; then
-			#
-			# No, we don't have libnl at all.
-			#
-			if test x$with_libnl = xyes ; then
-				as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
-			fi
-		fi
 	fi
 
-	for ac_header in linux/ethtool.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
-$ac_includes_default
-#include <linux/types.h>
-
-"
-if test "x$ac_cv_header_linux_ethtool_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_ETHTOOL_H 1
-_ACEOF
-
-fi
-
-done
-
-
-	#
-	# Check to see if struct tpacket_stats is defined in
-	# <linux/if_packet.h>.  If so, then pcap-linux.c can use this
-	# to report proper statistics.
-	#
-	# -Scott Barron
-	#
-	ac_fn_c_check_type "$LINENO" "struct tpacket_stats" "ac_cv_type_struct_tpacket_stats" "
-		#include <linux/if_packet.h>
-
-"
-if test "x$ac_cv_type_struct_tpacket_stats" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_TPACKET_STATS 1
-_ACEOF
-
-
-fi
-
-
 	#
 	# Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
 	#
@@ -6586,6 +7041,11 @@
 
 bpf)
 	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-bpf.c"
+
+	#
 	# Check whether we have the *BSD-style ioctls.
 	#
 	for ac_header in net/if_media.h
@@ -6624,12 +7084,44 @@
 
 	;;
 
+pf)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-pf.c"
+	;;
+
+snit)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-snit.c"
+	;;
+
+snoop)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-snoop.c"
+	;;
+
 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"
+	PLATFORM_C_SRC="pcap-dag.c"
+	xxx_only=yes
+	;;
+
+dpdk)
+	#
+	# --with-pcap=dpdk is the only way to get here, and it means
+	# "DPDK support but nothing else"
+	#
+	V_DEFS="$V_DEFS -DDPDK_ONLY"
+	PLATFORM_C_SRC="pcap-dpdk.c"
 	xxx_only=yes
 	;;
 
@@ -6639,6 +7131,7 @@
 	# "Septel support but nothing else"
 	#
 	V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+	PLATFORM_C_SRC="pcap-septel.c"
 	xxx_only=yes
 	;;
 
@@ -6648,10 +7141,15 @@
 	# "SNF support but nothing else"
 	#
 	V_DEFS="$V_DEFS -DSNF_ONLY"
+	PLATFORM_C_SRC="pcap-snf.c"
 	xxx_only=yes
 	;;
 
 null)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-null.c"
 	;;
 
 *)
@@ -6675,7 +7173,7 @@
 		    # We have the header, so we use "getifaddrs()" to
 		    # get the list of interfaces.
 		    #
-		    V_FINDALLDEVS=fad-getad.c
+		    PLATFORM_C_SRC="$PLATFORM_C_SRC fad-getad.c"
 
 else
 
@@ -6744,18 +7242,15 @@
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
 $as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
 		if test $ac_cv_lbl_have_siocglifconf = yes ; then
-			V_FINDALLDEVS=fad-glifc.c
+			PLATFORM_C_SRC="$PLATFORM_C_SRC fad-glifc.c"
 		else
-			V_FINDALLDEVS=fad-gifc.c
+			PLATFORM_C_SRC="$PLATFORM_C_SRC fad-gifc.c"
 		fi
 
 fi
 
 fi
 
-fi
-
-
 case "$host_os" in
 linux*)
 	for ac_header in linux/net_tstamp.h
@@ -6777,21 +7272,6 @@
 	;;
 esac
 
-# Check whether --enable-packet-ring was given.
-if test "${enable_packet_ring+set}" = set; then :
-  enableval=$enable_packet_ring;
-else
-  enable_packet_ring=yes
-fi
-
-
-if test "x$enable_packet_ring" != "xno" ; then
-
-$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
-
-
-fi
-
 #
 # Check for socklen_t.
 #
@@ -6901,10 +7381,17 @@
 
 	if test -z "$dag_lib_dir"; then
 		dag_lib_dir="$dag_root/lib"
+		#
+		# Handle multiarch systems.
+		#
+		if test -d "$dag_lib_dir/$host"
+		then
+			dag_lib_dir="$dag_lib_dir/$host"
+		fi
 	fi
 
-	V_INCLS="$V_INCLS -I$dag_include_dir"
-
+	save_CFLAGS="$CFLAGS"
+	CFLAGS="$CFLAGS -I$dag_include_dir"
 	for ac_header in dagapi.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "dagapi.h" "ac_cv_header_dagapi_h" "$ac_includes_default"
@@ -6920,14 +7407,16 @@
 
 	if test "$ac_cv_header_dagapi_h" = yes; then
 
+		V_INCLS="$V_INCLS -I$dag_include_dir"
+
 		if test $V_PCAP != dag ; then
-			 SSRC="$SSRC pcap-dag.c"
+			 MODULE_C_SRC="$MODULE_C_SRC pcap-dag.c"
 		fi
 
 		# Check for various DAG API functions.
 		# Don't need to save and restore LIBS to prevent -ldag being
 		# included if there's a found-action (arg 3).
-		saved_ldflags=$LDFLAGS
+		save_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; }
@@ -7105,7 +7594,7 @@
 fi
 
 
-		LDFLAGS=$saved_ldflags
+		LDFLAGS="$save_LDFLAGS"
 
 		#
 		# We assume that if we have libdag we have libdagconf,
@@ -7184,10 +7673,11 @@
 		fi
 
 		if test "$want_dag" = yes; then
-	        	# User wanted DAG support but we couldn't find it.
+			# 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
+	CFLAGS="$save_CFLAGS"
 fi
 
 
@@ -7253,7 +7743,7 @@
 		ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 
 		if test "$V_PCAP" != septel ; then
-			 SSRC="$SSRC pcap-septel.c"
+			 MODULE_C_SRC="$MODULE_C_SRC pcap-septel.c"
 		fi
 
 
@@ -7270,7 +7760,7 @@
 		fi
 
 		if test "$want_septel" = yes; then
-	        	# User wanted Septel support but we couldn't find it.
+			# 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
@@ -7354,11 +7844,18 @@
 
 	if test -z "$snf_lib_dir"; then
 		snf_lib_dir="$snf_root/lib"
+		#
+		# Handle multiarch systems.
+		#
+		if test -d "$snf_lib_dir/$host"
+		then
+			snf_lib_dir="$snf_lib_dir/$host"
+		fi
 	fi
 
 	if test -f "$snf_include_dir/snf.h"; then
 		# We found a header; make sure we can link with the library
-		saved_ldflags=$LDFLAGS
+		save_LDFLAGS="$LDFLAGS"
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
 $as_echo_n "checking for snf_init in -lsnf... " >&6; }
@@ -7400,7 +7897,7 @@
   ac_cv_lbl_snf_api="yes"
 fi
 
-		LDFLAGS="$saved_ldflags"
+		LDFLAGS="$save_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
@@ -7415,7 +7912,7 @@
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 
 		if test "$V_PCAP" != snf ; then
-			SSRC="$SSRC pcap-snf.c"
+			MODULE_C_SRC="$MODULE_C_SRC pcap-snf.c"
 		fi
 
 
@@ -7513,7 +8010,7 @@
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
-		SSRC="$SSRC pcap-tc.c"
+		MODULE_C_SRC="$MODULE_C_SRC pcap-tc.c"
 		V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
 		LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
 
@@ -7525,7 +8022,7 @@
 $as_echo "no" >&6; }
 
 		if test "$want_turbocap" = yes; then
-	        	# User wanted Turbo support but we couldn't find it.
+			# 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
@@ -7665,10 +8162,142 @@
 fi
 
 
+	#
+	# Optionally, we may want to support SSL.
+	# Check for OpenSSL/libressl.
+	#
+	# First, try looking for it as a regular system library.
+	# Make sure we can find SSL_library_init() using the
+	# standard headers, just in case we're running a version
+	# of macOS that ships with the OpenSSL library but not
+	# the OpenSSL headers, and have also installed another
+	# version of OpenSSL with headers.
+	#
+	save_LIBS="$LIBS"
+	LIBS="-lssl -lcrypto"
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have a system OpenSSL/libressl that we can use" >&5
+$as_echo_n "checking whether we have a system OpenSSL/libressl that we can use... " >&6; }
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <openssl/ssl.h>
+
+int
+main ()
+{
+
+SSL_library_init();
+return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		HAVE_OPENSSL=yes
+		OPENSSL_LIBS="-lssl -lcrypto"
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LIBS="$save_LIBS"
+
+	#
+	# If we didn't find it, check for it with pkg-config.
+	#
+	if test "x$HAVE_OPENSSL" != "xyes"; then
+		if test "x$PKGCONFIG" != "xno"; then
+			#
+			# We have pkg-config; see if we have OpenSSL/
+			# libressl installed as a package.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL/libressl with pkg-config" >&5
+$as_echo_n "checking for OpenSSL/libressl with pkg-config... " >&6; }
+			if "$PKGCONFIG" openssl; then
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+				HAVE_OPENSSL=yes
+				OPENSSL_CFLAGS=`"$PKGCONFIG" --cflags openssl`
+				OPENSSL_LIBS=`"$PKGCONFIG" --libs openssl`
+			else
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+			fi
+		fi
+	fi
+
+	#
+	# If we didn't find it, check for it under /usr/local/opt/openssl;
+	# that's where Homebrew puts it on macOS.  Feel free to add other
+	# -L directories as necessary; the "system library" check should
+	# also handle "add-on library under /usr/local", so that shouldn't
+	# be necessary here.
+	#
+	if test "x$HAVE_OPENSSL" != "xyes"; then
+		save_CFLAGS="$CFLAGS"
+		save_LIBS="$LIBS"
+		CFLAGS="$CFLAGS -L/usr/local/opt/openssl/include"
+		LIBS="$LIBS -L/usr/local/opt/openssl/lib -lssl -lcrypto"
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have OpenSSL/libressl in /usr/local/opt that we can use" >&5
+$as_echo_n "checking whether we have OpenSSL/libressl in /usr/local/opt that we can use... " >&6; }
+		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <openssl/ssl.h>
+
+int
+main ()
+{
+
+SSL_library_init();
+return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			HAVE_OPENSSL=yes
+			OPENSSL_CFLAGS="-I/usr/local/opt/openssl/include"
+			OPENSSL_LIBS="-L/usr/local/opt/openssl/lib -lssl -lcrypto"
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+		CFLAGS="$save_CFLAGS"
+		LIBS="$save_LIBS"
+	fi
+
+	#
+	# OK, did we find it?
+	#
+	if test "x$HAVE_OPENSSL" = "xyes"; then
+
+$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+		CFLAGS="$CFLAGS $OPENSSL_CFLAGS"
+		LIBS="$LIBS $OPENSSL_LIBS"
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: OpenSSL not found" >&5
+$as_echo "$as_me: OpenSSL not found" >&6;}
+	fi
+
 
 $as_echo "#define ENABLE_REMOTE /**/" >>confdefs.h
 
-	SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+	REMOTE_C_SRC="$REMOTE_C_SRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c sslutils.c"
 	BUILD_RPCAPD=build-rpcapd
 	INSTALL_RPCAPD=install-rpcapd
 	;;
@@ -7942,38 +8571,70 @@
 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; }
+case "$YACC" in
+
+*yacc)
+	#
+	# Make sure this is Berkeley YACC, not AT&T YACC; the latter
+	# doesn't support reentrant parsers.  Run it with "-V";
+	# that succeeds and reports the version number with
+	# Berkeley YACC, but will (probably) fail with various
+	# vendor flavors of AT&T YACC.
+	#
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable yacc" >&5
+$as_echo_n "checking for capable yacc... " >&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
+  if $YACC -V >/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.
+	if test $tcpdump_cv_capable_yacc = insufficient ; then
+	    as_fn_error $? "$YACC is insufficient to compile libpcap.
  libpcap requires Bison, a newer version of Berkeley YACC with support
  for reentrant parsers, or another YACC compatible with them." "$LINENO" 5
-fi
+	fi
+
+	#
+	# Berkeley YACC doesn't support "%define api.pure", so use
+	# "%pure-parser".
+	#
+	REENTRANT_PARSER="%pure-parser"
+	;;
+
+*)
+	#
+	# Bison prior to 2.4(.1) doesn't support "%define api.pure", so use
+	# "%pure-parser".
+	#
+	bison_major_version=`$YACC -V | sed -n 's/.* \([1-9][0-9]*\)\.[1-9][0-9.]*/\1/p'`
+	bison_minor_version=`$YACC -V | sed -n 's/.* [1-9][0-9]*\.\([1-9][0-9]*\).*/\1/p'`
+	if test "$bison_major_version" -lt 2 -o \
+	    \( "$bison_major_version" -eq 2 -a "$bison_major_version" -lt 4 \)
+	then
+		REENTRANT_PARSER="%pure-parser"
+	else
+		REENTRANT_PARSER="%define api.pure"
+	fi
+	;;
+esac
+
 
 #
 # Do various checks for various OSes and versions of those OSes.
 #
 # Assume, by default, no support for shared libraries and V7/BSD
-# convention for man pages (file formats in section 5, miscellaneous
-# info in section 7, administrative commands and daemons in section 8).
-# Individual cases can override this.
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
 #
 DYEXT="none"
+MAN_DEVICES=4
 MAN_FILE_FORMATS=5
 MAN_MISC_INFO=7
 MAN_ADMIN_COMMANDS=8
@@ -8035,79 +8696,181 @@
 	if test "$enable_universal" != "no"; then
 		case "$host_os" in
 
-		darwin0-7.*)
+		darwin[0-7].*)
 			#
 			# Pre-Tiger.  Build only for 32-bit PowerPC; no
 			# need for any special compiler or linker flags.
 			#
 			;;
 
-		darwin8.0123*)
+		darwin8.[0123]|darwin8.[0123].*)
 			#
-			# Tiger, prior to Intel support.  Build for 32-bit
-			# PowerPC and 64-bit PowerPC, with 32-bit PowerPC
-			# first.  (I'm guessing that's what Apple does.)
-			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64"
-			;;
-
-		darwin8.456*)
-			#
-			# Tiger, subsequent to Intel support but prior to
-			# x86-64 support.  Build for 32-bit PowerPC, 64-bit
-			# PowerPC, and x86, with 32-bit PowerPC first.
+			# Tiger, prior to Intel support.  Build
+			# libraries and executables for 32-bit PowerPC
+			# and 64-bit PowerPC, with 32-bit PowerPC first.
 			# (I'm guessing that's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386"
+			# (The double brackets are needed because
+			# autotools/m4 use brackets as a quoting
+			# character; the double brackets turn into
+			# single brackets in the generated configure
+			# file.)
+			#
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+			;;
+
+		darwin8.[456]|darwin.[456].*)
+			#
+			# Tiger, subsequent to Intel support but prior
+			# to x86-64 support.  Build libraries and
+			# executables for 32-bit PowerPC, 64-bit
+			# PowerPC, and 32-bit x86, with 32-bit PowerPC
+			# first.  (I'm guessing that's what Apple does.)
+			#
+			# (The double brackets are needed because
+			# autotools/m4 use brackets as a quoting
+			# character; the double brackets turn into
+			# single brackets in the generated configure
+			# file.)
+			#
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
 			;;
 
 		darwin8.*)
 			#
 			# All other Tiger, so subsequent to x86-64
-			# support. Build for 32-bit PowerPC, 64-bit
-			# PowerPC, x86, and x86-64, and with 32-bit PowerPC
-			# first.  (I'm guessing that's what Apple does.)
+			# support.  Build libraries and executables for
+			# 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+			# and x86-64, with 32-bit PowerPC first.  (I'm
+			# guessing that's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
 			;;
 
 		darwin9.*)
 			#
-			# Leopard.  Build for 32-bit PowerPC, 64-bit
-			# PowerPC, x86, and x86-64, with 32-bit PowerPC
-			# first.  (That's what Apple does.)
+			# Leopard.  Build libraries for 32-bit PowerPC,
+			# 64-bit PowerPC, 32-bit x86, and x86-64, with
+			# 32-bit PowerPC first, and build executables
+			# for 32-bit x86 and 32-bit PowerPC, with 32-bit
+			# x86 first.  (That's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+			V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
 			;;
 
 		darwin10.*)
 			#
-			# Snow Leopard.  Build for x86-64, x86, and
-			# 32-bit PowerPC, with x86-64 first.  (That's
-			# what Apple does, even though Snow Leopard
-			# doesn't run on PPC, so PPC libpcap runs under
-			# Rosetta, and Rosetta doesn't support BPF
-			# ioctls, so PPC programs can't do live
-			# captures.)
+			# Snow Leopard.  Build libraries for x86-64,
+			# 32-bit x86, and 32-bit PowerPC, with x86-64
+			# first, and build executables for x86-64 and
+			# 32-bit x86, with x86-64 first.  (That's what
+			# Apple does, even though Snow Leopard doesn't
+			# run on PPC, so PPC libpcap runs under Rosetta,
+			# and Rosetta doesn't support BPF ioctls, so PPC
+			# programs can't do live captures.)
 			#
-			V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
-			LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
+			V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+			V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+			V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+			V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
 			;;
 
 		darwin*)
 			#
-			# Post-Snow Leopard.  Build for x86-64 and
-			# x86, with x86-64 first.  (That's probably what
-			# Apple does, given that Rosetta is gone.)
+			# Post-Snow Leopard.  Build libraries for x86-64
+			# and 32-bit x86, with x86-64 first, and build
+			# executables only for x86-64.  (That's what
+			# Apple does.)  This requires no special flags
+			# for programs.
 			# XXX - update if and when Apple drops support
-			# for 32-bit x86 code.
+			# for 32-bit x86 code and if and when Apple adds
+			# ARM-based Macs.  (You're on your own for iOS
+			# etc.)
 			#
-			V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
-			LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
+			# XXX - check whether we *can* build for
+			# i386 and, if not, suggest that the user
+			# install the /usr/include headers if they
+			# want to build fat.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether building for 32-bit x86 is supported" >&5
+$as_echo_n "checking whether building for 32-bit x86 is supported... " >&6; }
+			save_CFLAGS="$CFLAGS"
+			CFLAGS="$CFLAGS -arch i386"
+			cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+				V_LIB_CCOPT_FAT="-arch x86_64"
+				V_LIB_LDFLAGS_FAT="-arch x86_64"
+
+				#
+				# OpenSSL installation on macOS seems
+				# to install only the libs for 64-bit
+				# x86 - at least that's what Brew does:
+				# only configure 32-bit builds if we
+				# don't have OpenSSL.
+				#
+				if test "$HAVE_OPENSSL" != yes; then
+					V_LIB_CCOPT_FAT="$V_LIB_CCOPT_FAT -arch i386"
+					V_LIB_LDFLAGS_FAT="$V_LIB_LDFLAGS_FAT -arch i386"
+				fi
+
+else
+
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+				V_LIB_CCOPT_FAT="-arch x86_64"
+				V_LIB_LDFLAGS_FAT="-arch x86_64"
+				case "$host_os" in
+
+				darwin18.*)
+					#
+					# Mojave; you need to install the
+					# /usr/include headers to get
+					# 32-bit x86 builds to work.
+					#
+					{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&2;}
+					;;
+
+				*)
+					#
+					# Pre-Mojave; the command-line
+					# tools should be sufficient to
+					# enable 32-bit x86 builds.
+					#
+					{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&2;}
+					;;
+				esac
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+			CFLAGS="$save_CFLAGS"
 			;;
 		esac
 	fi
@@ -8179,7 +8942,7 @@
 	MAN_MISC_INFO=5
 	;;
 
-linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|haiku*|midipix*)
 	DYEXT="so"
 
 	#
@@ -8202,6 +8965,7 @@
 	#
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
+	MAN_DEVICES=7
 	;;
 
 sinix*)
@@ -8267,6 +9031,7 @@
 		MAN_ADMIN_COMMANDS=1m
 		MAN_FILE_FORMATS=4
 		MAN_MISC_INFO=5
+		MAN_DEVICES=7D
 	esac
 	;;
 esac
@@ -8522,6 +9287,88 @@
 	CFLAGS="$save_CFLAGS"
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -W option" >&5
+$as_echo_n "checking whether the compiler supports the -W option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-W" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -W"
+	elif expr "x-W" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -W"
+	elif expr "x-W" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -W"
+	else
+	    CFLAGS="$CFLAGS -W"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -W " >&5
+$as_echo_n "checking whether -W ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -W"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
 $as_echo_n "checking whether the compiler supports the -Wall option... " >&6; }
 	save_CFLAGS="$CFLAGS"
@@ -8604,580 +9451,6 @@
 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; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wsign-compare " >&5
-$as_echo_n "checking whether -Wsign-compare ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wsign-compare"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-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"
-	if expr "x-Wmissing-prototypes" : "x-W.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
-	elif expr "x-Wmissing-prototypes" : "x-f.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
-	elif expr "x-Wmissing-prototypes" : "x-m.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
-	else
-	    CFLAGS="$CFLAGS -Wmissing-prototypes"
-	fi
-	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-return 0
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-prototypes " >&5
-$as_echo_n "checking whether -Wmissing-prototypes ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wmissing-prototypes"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "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 -Wstrict-prototypes option" >&5
-$as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
-	save_CFLAGS="$CFLAGS"
-	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.  */
-
-int
-main ()
-{
-return 0
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wstrict-prototypes " >&5
-$as_echo_n "checking whether -Wstrict-prototypes ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wstrict-prototypes"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
-$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
-	save_CFLAGS="$CFLAGS"
-	if expr "x-Wshadow" : "x-W.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshadow"
-	elif expr "x-Wshadow" : "x-f.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wshadow"
-	elif expr "x-Wshadow" : "x-m.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wshadow"
-	else
-	    CFLAGS="$CFLAGS -Wshadow"
-	fi
-	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-return 0
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wshadow " >&5
-$as_echo_n "checking whether -Wshadow ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wshadow"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -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; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdeclaration-after-statement " >&5
-$as_echo_n "checking whether -Wdeclaration-after-statement ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -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; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wused-but-marked-unused " >&5
-$as_echo_n "checking whether -Wused-but-marked-unused ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdocumentation option" >&5
-$as_echo_n "checking whether the compiler supports the -Wdocumentation option... " >&6; }
-	save_CFLAGS="$CFLAGS"
-	if expr "x-Wdocumentation" : "x-W.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdocumentation"
-	elif expr "x-Wdocumentation" : "x-f.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wdocumentation"
-	elif expr "x-Wdocumentation" : "x-m.*" >/dev/null
-	then
-	    CFLAGS="$CFLAGS -Werror -Wdocumentation"
-	else
-	    CFLAGS="$CFLAGS -Wdocumentation"
-	fi
-	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-return 0
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-		can_add_to_cflags=yes
-		#
-		# The compile supports this; do we have some C code for
-		# which the warning should *not* appear?
-		# We test the fourth argument because the third argument
-		# could contain quotes, breaking the test.
-		#
-		if test "x" != "x"
-		then
-		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdocumentation " >&5
-$as_echo_n "checking whether -Wdocumentation ... " >&6; }
-		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-			#
-			# Not a problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-
-			#
-			# A problem.
-			#
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-			can_add_to_cflags=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-		fi
-		CFLAGS="$save_CFLAGS"
-		if test x"$can_add_to_cflags" = "xyes"
-		then
-		    V_CCOPT="$V_CCOPT -Wdocumentation"
-		fi
-
-else
-
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		CFLAGS="$save_CFLAGS"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wcomma option" >&5
 $as_echo_n "checking whether the compiler supports the -Wcomma option... " >&6; }
 	save_CFLAGS="$CFLAGS"
@@ -9260,6 +9533,170 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdocumentation option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdocumentation option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wdocumentation" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdocumentation"
+	elif expr "x-Wdocumentation" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wdocumentation"
+	elif expr "x-Wdocumentation" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wdocumentation"
+	else
+	    CFLAGS="$CFLAGS -Wdocumentation"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdocumentation " >&5
+$as_echo_n "checking whether -Wdocumentation ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wdocumentation"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wformat-nonliteral option" >&5
+$as_echo_n "checking whether the compiler supports the -Wformat-nonliteral option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wformat-nonliteral" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wformat-nonliteral"
+	elif expr "x-Wformat-nonliteral" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+	elif expr "x-Wformat-nonliteral" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+	else
+	    CFLAGS="$CFLAGS -Wformat-nonliteral"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wformat-nonliteral " >&5
+$as_echo_n "checking whether -Wformat-nonliteral ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wformat-nonliteral"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-noreturn option" >&5
 $as_echo_n "checking whether the compiler supports the -Wmissing-noreturn option... " >&6; }
 	save_CFLAGS="$CFLAGS"
@@ -9341,9 +9778,88 @@
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-		    # Warns about safeguards added in case the enums are
-		    # extended
-		    # AC_LBL_CHECK_COMPILER_OPT(V_CCOPT, -Wcovered-switch-default)
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wmissing-prototypes" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+	elif expr "x-Wmissing-prototypes" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+	elif expr "x-Wmissing-prototypes" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+	else
+	    CFLAGS="$CFLAGS -Wmissing-prototypes"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-prototypes " >&5
+$as_echo_n "checking whether -Wmissing-prototypes ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wmissing-prototypes"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "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-variable-declarations option" >&5
 $as_echo_n "checking whether the compiler supports the -Wmissing-variable-declarations option... " >&6; }
@@ -9427,6 +9943,416 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-arith option" >&5
+$as_echo_n "checking whether the compiler supports the -Wpointer-arith option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wpointer-arith" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wpointer-arith"
+	elif expr "x-Wpointer-arith" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wpointer-arith"
+	elif expr "x-Wpointer-arith" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wpointer-arith"
+	else
+	    CFLAGS="$CFLAGS -Wpointer-arith"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wpointer-arith " >&5
+$as_echo_n "checking whether -Wpointer-arith ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wpointer-arith"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-sign option" >&5
+$as_echo_n "checking whether the compiler supports the -Wpointer-sign option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wpointer-sign" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wpointer-sign"
+	elif expr "x-Wpointer-sign" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wpointer-sign"
+	elif expr "x-Wpointer-sign" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wpointer-sign"
+	else
+	    CFLAGS="$CFLAGS -Wpointer-sign"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wpointer-sign " >&5
+$as_echo_n "checking whether -Wpointer-sign ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wpointer-sign"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
+$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wshadow" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshadow"
+	elif expr "x-Wshadow" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshadow"
+	elif expr "x-Wshadow" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshadow"
+	else
+	    CFLAGS="$CFLAGS -Wshadow"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wshadow " >&5
+$as_echo_n "checking whether -Wshadow ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wshadow"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
+$as_echo_n "checking whether the compiler supports the -Wsign-compare option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wsign-compare" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wsign-compare"
+	elif expr "x-Wsign-compare" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wsign-compare"
+	elif expr "x-Wsign-compare" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wsign-compare"
+	else
+	    CFLAGS="$CFLAGS -Wsign-compare"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wsign-compare " >&5
+$as_echo_n "checking whether -Wsign-compare ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wsign-compare"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+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 -Wstrict-prototypes option" >&5
+$as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	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.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wstrict-prototypes " >&5
+$as_echo_n "checking whether -Wstrict-prototypes ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wstrict-prototypes"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunused-parameter option" >&5
 $as_echo_n "checking whether the compiler supports the -Wunused-parameter option... " >&6; }
 	save_CFLAGS="$CFLAGS"
@@ -9509,20 +10435,20 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wformat-nonliteral option" >&5
-$as_echo_n "checking whether the compiler supports the -Wformat-nonliteral option... " >&6; }
+	{ $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-Wformat-nonliteral" : "x-W.*" >/dev/null
+	if expr "x-Wused-but-marked-unused" : "x-W.*" >/dev/null
 	then
-	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wformat-nonliteral"
-	elif expr "x-Wformat-nonliteral" : "x-f.*" >/dev/null
+	    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 -Wformat-nonliteral"
-	elif expr "x-Wformat-nonliteral" : "x-m.*" >/dev/null
+	    CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+	elif expr "x-Wused-but-marked-unused" : "x-m.*" >/dev/null
 	then
-	    CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+	    CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
 	else
-	    CFLAGS="$CFLAGS -Wformat-nonliteral"
+	    CFLAGS="$CFLAGS -Wused-but-marked-unused"
 	fi
 	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -9549,8 +10475,8 @@
 		if test "x" != "x"
 		then
 		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wformat-nonliteral " >&5
-$as_echo_n "checking whether -Wformat-nonliteral ... " >&6; }
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wused-but-marked-unused " >&5
+$as_echo_n "checking whether -Wused-but-marked-unused ... " >&6; }
 		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -9578,7 +10504,7 @@
 		CFLAGS="$save_CFLAGS"
 		if test x"$can_add_to_cflags" = "xyes"
 		then
-		    V_CCOPT="$V_CCOPT -Wformat-nonliteral"
+		    V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
 		fi
 
 else
@@ -9590,6 +10516,9 @@
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+		    # Warns about safeguards added in case the enums are
+		    # extended
+		    # AC_LBL_CHECK_COMPILER_OPT(V_CCOPT, -Wcovered-switch-default)
 		    #
 		    # This can cause problems with ntohs(), ntohl(),
 		    # htons(), and htonl() on some platforms, such
@@ -9703,6 +10632,88 @@
 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 -Wshorten-64-to-32 option" >&5
+$as_echo_n "checking whether the compiler supports the -Wshorten-64-to-32 option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wshorten-64-to-32" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshorten-64-to-32"
+	elif expr "x-Wshorten-64-to-32" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshorten-64-to-32"
+	elif expr "x-Wshorten-64-to-32" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshorten-64-to-32"
+	else
+	    CFLAGS="$CFLAGS -Wshorten-64-to-32"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		can_add_to_cflags=yes
+		#
+		# The compile supports this; do we have some C code for
+		# which the warning should *not* appear?
+		# We test the fourth argument because the third argument
+		# could contain quotes, breaking the test.
+		#
+		if test "x" != "x"
+		then
+		    CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wshorten-64-to-32 " >&5
+$as_echo_n "checking whether -Wshorten-64-to-32 ... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			#
+			# Not a problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+			#
+			# A problem.
+			#
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+		fi
+		CFLAGS="$save_CFLAGS"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wshorten-64-to-32"
+		fi
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 	    fi
 
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
@@ -9783,7 +10794,7 @@
 			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, with $ac_lbl_dependency_flag" >&5
 $as_echo "yes, with $ac_lbl_dependency_flag" >&6; }
 			DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
-			MKDEP='${srcdir}/mkdep'
+			MKDEP='${top_srcdir}/mkdep'
 		else
 			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -9791,7 +10802,7 @@
 			# We can't run mkdep, so have "make depend" do
 			# nothing.
 			#
-			MKDEP='${srcdir}/nomkdep'
+			MKDEP='${top_srcdir}/nomkdep'
 		fi
 		rm -rf conftest*
 	else
@@ -9801,7 +10812,7 @@
 		# We can't run mkdep, so have "make depend" do
 		# nothing.
 		#
-		MKDEP='${srcdir}/nomkdep'
+		MKDEP='${top_srcdir}/nomkdep'
 	fi
 
 
@@ -9890,100 +10901,6 @@
 fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5
-$as_echo_n "checking if unaligned accesses fail... " >&6; }
-    if ${ac_cv_lbl_unaligned_fail+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case "$host_cpu" in
-
-	#
-	# These are CPU types where:
-	#
-	#	the CPU faults on an unaligned access, but at least some
-	#	OSes that support that CPU catch the fault and simulate
-	#	the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
-	#	the simulation is slow, so we don't want to use it;
-	#
-	#	the CPU, I infer (from the old
-	#
-	# XXX: should also check that they don't do weird things (like on arm)
-	#
-	#	comment) doesn't fault on unaligned accesses, but doesn't
-	#	do a normal unaligned fetch, either (e.g., presumably, ARM);
-	#
-	#	for whatever reason, the test program doesn't work
-	#	(this has been claimed to be the case for several of those
-	#	CPUs - I don't know what the problem is; the problem
-	#	was reported as "the test program dumps core" for SuperH,
-	#	but that's what the test program is *supposed* to do -
-	#	it dumps core before it writes anything, so the test
-	#	for an empty output file should find an empty output
-	#	file and conclude that unaligned accesses don't work).
-	#
-	# This run-time test won't work if you're cross-compiling, so
-	# in order to support cross-compiling for a particular CPU,
-	# we have to wire in the list of CPU types anyway, as far as
-	# I know, so perhaps we should just have a set of CPUs on
-	# which we know it doesn't work, a set of CPUs on which we
-	# know it does work, and have the script just fail on other
-	# cpu types and update it when such a failure occurs.
-	#
-	alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
-		ac_cv_lbl_unaligned_fail=yes
-		;;
-
-	*)
-		cat >conftest.c <<EOF
-#		include <sys/types.h>
-#		include <sys/wait.h>
-#		include <stdio.h>
-		unsigned char a[5] = { 1, 2, 3, 4, 5 };
-		main() {
-		unsigned int i;
-		pid_t pid;
-		int status;
-		/* avoid "core dumped" message */
-		pid = fork();
-		if (pid <  0)
-			exit(2);
-		if (pid > 0) {
-			/* parent */
-			pid = waitpid(pid, &status, 0);
-			if (pid < 0)
-				exit(3);
-			exit(!WIFEXITED(status));
-		}
-		/* child */
-		i = *(unsigned int *)&a[1];
-		printf("%d\n", i);
-		exit(0);
-		}
-EOF
-		${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
-		    conftest.c $LIBS >/dev/null 2>&1
-		if test ! -x conftest ; then
-						ac_cv_lbl_unaligned_fail=yes
-		else
-			./conftest >conftest.out
-			if test ! -s conftest.out ; then
-				ac_cv_lbl_unaligned_fail=yes
-			else
-				ac_cv_lbl_unaligned_fail=no
-			fi
-		fi
-		rm -f -r conftest* core core.conftest
-		;;
-	esac
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5
-$as_echo "$ac_cv_lbl_unaligned_fail" >&6; }
-    if test $ac_cv_lbl_unaligned_fail = yes ; then
-
-$as_echo "#define LBL_ALIGN 1" >>confdefs.h
-
-    fi
 
 
 
@@ -10010,6 +10927,14 @@
 
 
 
+
+
+
+
+
+#
+# Various Linux-specific mechanisms.
+#
 # Check whether --enable-usb was given.
 if test "${enable_usb+set}" = set; then :
   enableval=$enable_usb;
@@ -10018,39 +10943,38 @@
 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 somebody requested an XXX-only pcap, that doesn't include
+# additional mechanisms.
+#
+if test "xxx_only" != yes; then
+  case "$host_os" in
+  linux*)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux usbmon USB sniffing support" >&5
+$as_echo_n "checking for Linux usbmon USB sniffing support... " >&6; }
+    if test "x$enable_usb" != "xno" ; then
 
-if test "x$enable_usb" != "xno" ; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
-$as_echo_n "checking for USB sniffing support... " >&6; }
-   case "$host_os" in
-   linux*)
+$as_echo "#define PCAP_SUPPORT_LINUX_USBMON 1" >>confdefs.h
 
-$as_echo "#define PCAP_SUPPORT_USB 1" >>confdefs.h
-
-	USB_SRC=pcap-usb-linux.c
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+      MODULE_C_SRC="$MODULE_C_SRC pcap-usb-linux.c"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
-	if test $? -ne 0 ; then
-	  ac_usb_dev_name="usbmon"
-	fi
+      ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+      if test $? -ne 0 ; then
+        ac_usb_dev_name="usbmon"
+      fi
 
 cat >>confdefs.h <<_ACEOF
 #define LINUX_USB_MON_DEV "/dev/$ac_usb_dev_name"
 _ACEOF
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5
 $as_echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;}
-	#
-	# Do we have a version of <linux/compiler.h> available?
-	# If so, we might need it for <linux/usbdevice_fs.h>.
-	#
-	for ac_header in linux/compiler.h
+      #
+      # Do we have a version of <linux/compiler.h> available?
+      # If so, we might need it for <linux/usbdevice_fs.h>.
+      #
+      for ac_header in linux/compiler.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "linux/compiler.h" "ac_cv_header_linux_compiler_h" "$ac_includes_default"
 if test "x$ac_cv_header_linux_compiler_h" = xyes; then :
@@ -10062,11 +10986,11 @@
 
 done
 
-	if test "$ac_cv_header_linux_compiler_h" = yes; then
-	  #
-	  # Yes - include it when testing for <linux/usbdevice_fs.h>.
-	  #
-	  for ac_header in linux/usbdevice_fs.h
+      if test "$ac_cv_header_linux_compiler_h" = yes; then
+        #
+        # Yes - include it when testing for <linux/usbdevice_fs.h>.
+        #
+        for ac_header in linux/usbdevice_fs.h
 do :
   ac_fn_c_check_header_compile "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "#include <linux/compiler.h>
 "
@@ -10079,8 +11003,8 @@
 
 done
 
-	else
-	  for ac_header in linux/usbdevice_fs.h
+      else
+        for ac_header in linux/usbdevice_fs.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "$ac_includes_default"
 if test "x$ac_cv_header_linux_usbdevice_fs_h" = xyes; then :
@@ -10092,20 +11016,20 @@
 
 done
 
-	fi
-	if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
-	  #
-	  # OK, does it define bRequestType?  Older versions of the kernel
-	  # define fields with names like "requesttype, "request", and
-	  # "value", rather than "bRequestType", "bRequest", and
-	  # "wValue".
-	  #
-	  ac_fn_c_check_member "$LINENO" "struct usbdevfs_ctrltransfer" "bRequestType" "ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" "
-		  $ac_includes_default
-		  #ifdef HAVE_LINUX_COMPILER_H
-		  #include <linux/compiler.h>
-		  #endif
-		  #include <linux/usbdevice_fs.h>
+      fi
+      if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+        #
+        # OK, does it define bRequestType?  Older versions of the kernel
+        # define fields with names like "requesttype, "request", and
+        # "value", rather than "bRequestType", "bRequest", and
+        # "wValue".
+        #
+        ac_fn_c_check_member "$LINENO" "struct usbdevfs_ctrltransfer" "bRequestType" "ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" "
+            $ac_includes_default
+            #ifdef HAVE_LINUX_COMPILER_H
+            #include <linux/compiler.h>
+            #endif
+            #include <linux/usbdevice_fs.h>
 
 "
 if test "x$ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" = xyes; then :
@@ -10117,44 +11041,23 @@
 
 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
+      fi
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	;;
-esac
-fi
+    fi
 
-
-
-if test "xxx_only" != yes; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
-$as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; }
-	case "$host_os" in
-	linux*)
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-		#
-		# Life's too short to deal with trying to get this to compile
-		# if you don't get the right types defined with
-		# __KERNEL_STRICT_NAMES getting defined by some other include.
-		#
-		# Check whether the includes Just Work.  If not, don't turn on
-		# netfilter support.
-		#
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
+    #
+    # 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
@@ -10186,20 +11089,16 @@
 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
-$as_echo "no" >&6; }
-		;;
-	esac
+      MODULE_C_SRC="$MODULE_C_SRC pcap-netfilter-linux.c"
+    fi
+    ;;
+  esac
 fi
 
 
@@ -10252,10 +11151,294 @@
 
 $as_echo "#define PCAP_SUPPORT_NETMAP 1" >>confdefs.h
 
-	    NETMAP_SRC=pcap-netmap.c
+	    MODULE_C_SRC="$MODULE_C_SRC pcap-netmap.c"
 	fi
 
+fi
 
+# Check for DPDK support.
+
+# Check whether --with-dpdk was given.
+if test "${with_dpdk+set}" = set; then :
+  withval=$with_dpdk;
+	if test "$withval" = no
+	then
+		# User doesn't want DPDK support.
+		want_dpdk=no
+	elif test "$withval" = yes
+	then
+		# User wants DPDK support but hasn't specified a directory.
+		want_dpdk=yes
+	else
+		# User wants DPDK support and has specified a directory,
+		# so use the provided value.
+		want_dpdk=yes
+		dpdk_dir=$withval
+	fi
+
+else
+
+	if test "$V_PCAP" = dpdk; then
+		# User requested DPDK-only libpcap, so we'd better have
+		# the DPDK API.
+		want_dpdk=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want DPDK support.
+		want_dpdk=no
+	else
+		#
+		# Use DPDK API if present, otherwise don't
+		#
+		want_dpdk=ifpresent
+	fi
+
+fi
+
+
+if test "$want_dpdk" != no; then
+	if test "x$PKGCONFIG" != "xno"
+	then
+		#
+		# We have pkg-config; see if we have DPDK installed
+		# as a package.
+		#
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DPDK with pkg-config" >&5
+$as_echo_n "checking for DPDK with pkg-config... " >&6; }
+		if "$PKGCONFIG" libdpdk
+		then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+			found_dpdk_with_pkg_config=yes
+			DPDK_CFLAGS=`"$PKGCONFIG" --cflags libdpdk`
+			DPDK_LDFLAGS=`"$PKGCONFIG" --libs libdpdk`
+		else
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+		fi
+	fi
+
+	#
+	# If we didn't find it with pkg-config, try checking for
+	# it manually.
+	#
+	if test "x$found_dpdk_with_pkg_config" != "xyes"
+	then
+		if test -z "$dpdk_dir"; then
+			#
+			# The user didn't specify a directory containing
+			# the DPDK headers and libraries.  If we find
+			# a /usr/local/include/dpdk directory, assume
+			# it's /usr/local, otherwise assume it's /usr.
+			#
+			if test -d "/usr/local/include/dpdk"; then
+				dpdk_dir="/usr/local"
+			else
+				dpdk_dir="/usr"
+			fi
+		fi
+		#
+		# The convention appears to be that 1) there's a "dpdk"
+		# subdirectory of the include directory, containing DPDK
+		# headers (at least in the installation on Ubuntu with
+		# the system DPDK packages) and 2) includes of DPDK
+		# headers don't use "dpdk/{header}" (at least from the
+		# way the DPDK documentation is written).
+		#
+		# So we add "/dpdk" to the include directory, and always
+		# add that to the list of include directories to search.
+		#
+		dpdk_inc_dir="$dpdk_dir/include/dpdk"
+		dpdk_inc_flags="-I$dpdk_inc_dir"
+		dpdk_lib_dir="$dpdk_dir/lib"
+		#
+		# Handle multiarch systems.
+		#
+		# Step 1: run the C compiler with the -dumpmachine option;
+		# if it succeeds, the output would be the multiarch directory
+		# name if your system has multiarch directories.
+		#
+		multiarch_dir=`$CC -dumpmachine 2>/dev/null`
+		if test ! -z "$multiarch_dir"
+		then
+			#
+			# OK, we have a multiarch directory.
+			#
+			# Now deal with includes.  On Ubuntu 20.04, for
+			# example, we have /usr/include/dpdk *and*
+			# /usr/include/$multiarch_dir/dpdk, and must
+			# search both.
+			#
+			if test -d "$dpdk_dir/include/$multiarch_dir/dpdk"
+			then
+				dpdk_inc_flags="-I$dpdk_dir/include/$multiarch_dir/dpdk $dpdk_inc_flags"
+			fi
+
+			#
+			# Now deal with libraries.
+			#
+			if test -d "$dpdk_lib_dir/$multiarch_dir"
+			then
+				dpdk_lib_dir="$dpdk_lib_dir/$multiarch_dir"
+			fi
+		fi
+		DPDK_MACHINE_CFLAGS="-march=native"
+		DPDK_CFLAGS="$DPDK_MACHINE_CFLAGS $dpdk_inc_flags"
+		DPDK_LDFLAGS="-L$dpdk_lib_dir -ldpdk -lrt -lm -lnuma -ldl -pthread"
+	fi
+
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	save_LDFLAGS="$LDFLAGS"
+	CFLAGS="$CFLAGS $DPDK_CFLAGS"
+	LIBS="$LIBS $DPDK_LDFLAGS"
+	LDFLAGS="$LDFLAGS $DPDK_LDFLAGS"
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the DPDK support" >&5
+$as_echo_n "checking whether we can compile the DPDK support... " >&6; }
+	if ${ac_cv_dpdk_can_compile+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+$ac_includes_default
+#include <rte_common.h>
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_dpdk_can_compile=yes
+else
+  ac_cv_dpdk_can_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_dpdk_can_compile" >&5
+$as_echo "$ac_cv_dpdk_can_compile" >&6; }
+
+	#
+	# We include rte_bus.h, and older versions of DPDK
+	# didn't have it, so check for it.
+	#
+	if test "$ac_cv_dpdk_can_compile" = yes; then
+		#
+		# This runs the preprocessor, so make sure it
+		# looks in the DPDK directories.  Instead of
+		# including dpdk/XXX.h, we include just XXX.h
+		# and assume DPDK_CFLAGS is the directory
+		# containing the DPDK headers (that's how
+		# pkg-config sets it, at least on Ubuntu),
+		# so just looking under /usr/include won't
+		# find it.
+		#
+		save_CPPFLAGS="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS $DPDK_CFLAGS"
+		ac_fn_c_check_header_mongrel "$LINENO" "rte_bus.h" "ac_cv_header_rte_bus_h" "$ac_includes_default"
+if test "x$ac_cv_header_rte_bus_h" = xyes; then :
+
+fi
+
+
+		CPPFLAGS="$save_CPPFLAGS"
+	fi
+
+	#
+	# We call rte_eth_dev_count_avail(), and older versions
+	# of DPDK didn't have it, so check for it.
+	#
+	if test "$ac_cv_header_rte_bus_h" = yes; then
+		ac_fn_c_check_func "$LINENO" "rte_eth_dev_count_avail" "ac_cv_func_rte_eth_dev_count_avail"
+if test "x$ac_cv_func_rte_eth_dev_count_avail" = xyes; then :
+
+fi
+
+	fi
+
+	CFLAGS="$save_CFLAGS"
+	LIBS="$save_LIBS"
+	LDFLAGS="$save_LDFLAGS"
+
+	if test "$ac_cv_func_rte_eth_dev_count_avail" = yes; then
+		CFLAGS="$CFLAGS $DPDK_CFLAGS"
+		LIBS="$LIBS $DPDK_LDFLAGS"
+		LDFLAGS="$LDFLAGS $DPDK_LDFLAGS"
+		V_INCLS="$V_INCLS $DPDK_CFLAGS"
+
+$as_echo "#define PCAP_SUPPORT_DPDK 1" >>confdefs.h
+
+		if test $V_PCAP != dpdk ; then
+			MODULE_C_SRC="$MODULE_C_SRC pcap-dpdk.c"
+		fi
+
+		#
+		# Check whether the rte_ether.h file defines
+		# struct ether_addr or struct rte_ether_addr.
+		#
+		# ("API compatibility?  That's for losers!")
+		#
+		ac_fn_c_check_type "$LINENO" "struct rte_ether_addr" "ac_cv_type_struct_rte_ether_addr" "
+			#include <rte_ether.h>
+
+"
+if test "x$ac_cv_type_struct_rte_ether_addr" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_RTE_ETHER_ADDR 1
+_ACEOF
+
+
+fi
+
+	else
+		if test "$V_PCAP" = dpdk; then
+			# User requested DPDK-only capture support, but
+			# we couldn't the DPDK API support at all, or we
+			# found it but it wasn't a sufficiently recent
+			# version.
+			if test "$ac_cv_dpdk_can_compile" != yes; then
+				#
+				# Couldn't even find the headers.
+				#
+				as_fn_error $? "DPDK support requested with --with-pcap=dpdk, but the DPDK headers weren't found at $dpdk_inc_dir: make sure the DPDK support is installed, specify a different path or paths if necessary, or don't request DPDK support" "$LINENO" 5
+			else
+				#
+				# Found the headers, but we couldn't find
+				# rte_bus.h or rte_eth_dev_count_avail(),
+				# we don't have a sufficiently recent
+				# version of DPDK.
+				#
+				as_fn_error $? "DPDK support requested with --with-pcap=dpdk, but we require DPDK 18.x or later; install a newer version of DPDK, or don't request DPDK support" "$LINENO" 5
+			fi
+		fi
+
+		if test "$want_dpdk" = yes; then
+			# User requested DPDK-only capture support, but
+			# we couldn't the DPDK API support at all, or we
+			# found it but it wasn't a sufficiently recent
+			# version.
+			if test "$ac_cv_dpdk_can_compile" != yes; then
+				#
+				# Couldn't even find the headers.
+				#
+				as_fn_error $? "DPDK support requested with --with-pcap=dpdk, but the DPDK headers weren't found at $dpdk_inc_dir: make sure the DPDK support is installed, specify a different path or paths if necessary, or don't request DPDK support" "$LINENO" 5
+			else
+				#
+				# Found the headers, but we couldn't find
+				# rte_bus.h or rte_eth_dev_count_avail(),
+				# we don't have a sufficiently recent
+				# version of DPDK.
+				#
+				as_fn_error $? "DPDK support requested with --with-pcap=dpdk, but we require DPDK 18.x or later: install a newer version of DPDK, or don't request DPDK support" "$LINENO" 5
+			fi
+		fi
+	fi
 fi
 
 
@@ -10286,7 +11469,7 @@
 
 $as_echo "#define PCAP_SUPPORT_BT 1" >>confdefs.h
 
-			BT_SRC=pcap-bt-linux.c
+			MODULE_C_SRC="$MODULE_C_SRC pcap-bt-linux.c"
 			{ $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5
 $as_echo "$as_me: Bluetooth sniffing is supported" >&6;}
 			ac_lbl_bluetooth_available=yes
@@ -10338,7 +11521,7 @@
 
 $as_echo "#define PCAP_SUPPORT_BT_MONITOR /**/" >>confdefs.h
 
-					    BT_MONITOR_SRC=pcap-bt-monitor-linux.c
+					    MODULE_C_SRC="$MODULE_C_SRC pcap-bt-monitor-linux.c"
 
 else
 
@@ -10380,8 +11563,6 @@
 		;;
 	esac
 
-
-
 fi
 
 # Check whether --enable-dbus was given.
@@ -10431,44 +11612,6 @@
 fi
 
 if test "x$enable_dbus" != "xno"; then
-	# Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_PKGCONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$PKGCONFIG"; then
-  ac_cv_prog_PKGCONFIG="$PKGCONFIG" # 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_PKGCONFIG="pkg-config"
-    $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
-
-  test -z "$ac_cv_prog_PKGCONFIG" && ac_cv_prog_PKGCONFIG="no"
-fi
-fi
-PKGCONFIG=$ac_cv_prog_PKGCONFIG
-if test -n "$PKGCONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
-$as_echo "$PKGCONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
 	if test "x$PKGCONFIG" != "xno"; then
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for D-Bus" >&5
 $as_echo_n "checking for D-Bus... " >&6; }
@@ -10506,7 +11649,7 @@
 
 $as_echo "#define PCAP_SUPPORT_DBUS 1" >>confdefs.h
 
-				DBUS_SRC=pcap-dbus.c
+				MODULE_C_SRC="$MODULE_C_SRC pcap-dbus.c"
 				V_INCLS="$V_INCLS $DBUS_CFLAGS"
 
 else
@@ -10531,24 +11674,23 @@
 		fi
 	fi
 
-
 fi
 
 # Check whether --enable-rdma was given.
 if test "${enable_rdma+set}" = set; then :
   enableval=$enable_rdma;
 else
-  enable_rdmasniff=ifavailable
+  enable_rdma=ifavailable
 fi
 
 
 if test "xxx_only" = yes; then
 	# User requested something-else-only pcap, so they don't
 	# want RDMA support.
-	enable_rdmasniff=no
+	enable_rdma=no
 fi
 
-if test "x$enable_rdmasniff" != "xno"; then
+if test "x$enable_rdma" != "xno"; then
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ibv_get_device_list in -libverbs" >&5
 $as_echo_n "checking for ibv_get_device_list in -libverbs... " >&6; }
 if ${ac_cv_lib_ibverbs_ibv_get_device_list+:} false; then :
@@ -10626,7 +11768,7 @@
 
 $as_echo "#define PCAP_SUPPORT_RDMASNIFF /**/" >>confdefs.h
 
-					RDMA_SRC=pcap-rdmasniff.c
+					MODULE_C_SRC="$MODULE_C_SRC pcap-rdmasniff.c"
 					LIBS="-libverbs $LIBS"
 
 else
@@ -10646,7 +11788,6 @@
 fi
 
 
-
 fi
 
 # Find a good install program.  We prefer a C program (faster),
@@ -10748,7 +11889,7 @@
 
 ac_config_commands="$ac_config_commands default-1"
 
-ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin testprogs/Makefile"
+ac_config_files="$ac_config_files Makefile grammar.y pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile testprogs/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -11256,7 +12397,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by pcap $as_me 1.9.0-PRE-GIT, which was
+This file was extended by pcap $as_me 1.10.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -11322,7 +12463,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-pcap config.status 1.9.0-PRE-GIT
+pcap config.status 1.10.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -11452,6 +12593,7 @@
     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
     "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "grammar.y") CONFIG_FILES="$CONFIG_FILES grammar.y" ;;
     "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;;
     "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;;
     "pcap-tstamp.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-tstamp.manmisc" ;;
@@ -11465,10 +12607,12 @@
     "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;;
     "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
     "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
+    "pcap_set_immediate_mode.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_immediate_mode.3pcap" ;;
     "pcap_set_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_precision.3pcap" ;;
     "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;;
     "rpcapd/Makefile") CONFIG_FILES="$CONFIG_FILES rpcapd/Makefile" ;;
     "rpcapd/rpcapd.manadmin") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd.manadmin" ;;
+    "rpcapd/rpcapd-config.manfile") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd-config.manfile" ;;
     "testprogs/Makefile") CONFIG_FILES="$CONFIG_FILES testprogs/Makefile" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
diff --git a/configure.ac b/configure.ac
index eff6eb8..2ad28bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,7 +8,7 @@
 #
 # See
 #
-#	http://ftp.gnu.org/gnu/config/README
+#	https://ftp.gnu.org/gnu/config/README
 #
 # for the URLs to use to fetch new versions of config.guess and
 # config.sub.
@@ -24,10 +24,23 @@
 
 AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS)
 #
-# Try to enable as many C99 features as we can.
-# At minimum, we want C++/C99-style // comments.
+# We require C99 or later.
+# Try to get it, which may involve adding compiler flags;
+# if that fails, give up.
 #
 AC_PROG_CC_C99
+if test "$ac_cv_prog_cc_c99" = "no"; then
+	AC_MSG_ERROR([The C compiler does not support C99])
+fi
+case "$host_os" in
+haiku*)
+	#
+	# Haiku's platform file is in C++.
+	#
+	AC_PROG_CXX
+	;;
+esac
+
 AC_LBL_C_INIT(V_CCOPT, V_INCLS)
 AC_LBL_SHLIBS_INIT
 AC_LBL_C_INLINE
@@ -47,7 +60,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)
+AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h)
 AC_CHECK_HEADERS(netpacket/packet.h)
 AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
 #include <sys/socket.h>
@@ -72,24 +85,91 @@
 fi
 
 case "$host_os" in
-linux*|uclinux*)
-	AC_CHECK_HEADERS(linux/sockios.h linux/if_bonding.h,,,
-	[
-#include <sys/socket.h>
-#include <linux/if.h>
-	])
+haiku*)
+	#
+	# Haiku needs _BSD_SOURCE for the _IO* macros because it doesn't use them.
+	#
+	CFLAGS="$CFLAGS -D_BSD_SOURCE"
 	;;
 esac
 
 AC_LBL_FIXINCLUDES
 
-AC_CHECK_FUNCS(strerror strerror_r strerror_s strlcpy strlcat)
+AC_CHECK_FUNCS(strerror)
+AC_CHECK_FUNC(strerror_r,
+    [
+	#
+	# We have strerror_r; if we define _GNU_SOURCE, is it a
+	# POSIX-compliant strerror_r() or a GNU strerror_r()?
+	#
+	AC_MSG_CHECKING(whether strerror_r is GNU-style)
+	AC_COMPILE_IFELSE(
+	    [
+		AC_LANG_SOURCE(
+#define _GNU_SOURCE
+#include <string.h>
 
-needsnprintf=no
-AC_CHECK_FUNCS(vsnprintf snprintf,,
-	[needsnprintf=yes])
-if test $needsnprintf = yes; then
-	AC_LIBOBJ([snprintf])
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+	return 0;
+}
+)
+	    ],
+	    [
+	        # GNU-style
+		AC_MSG_RESULT(yes)
+		AC_DEFINE(HAVE_GNU_STRERROR_R,,
+		    [Define to 1 if you have a GNU-style `strerror_r' function.])
+	    ],
+	    [
+		AC_MSG_RESULT(no)
+		AC_DEFINE(HAVE_POSIX_STRERROR_R,,
+		    [Define to 1 if you have a POSIX-style `strerror_r' function.])
+	    ])
+    ],
+    [
+	#
+	# We don't have strerror_r; do we have _wcserror_s?
+	#
+	AC_CHECK_FUNCS(_wcserror_s)
+    ])
+
+#
+# Thanks, IBM, for not providing vsyslog() in AIX!
+#
+AC_CHECK_FUNCS(vsyslog)
+
+#
+# Make sure we have vsnprintf() and snprintf(); we require them.
+#
+AC_CHECK_FUNC(vsnprintf,,
+    AC_MSG_ERROR([vsnprintf() is required but wasn't found]))
+AC_CHECK_FUNC(snprintf,,
+    AC_MSG_ERROR([snprintf() is required but wasn't found]))
+
+needasprintf=no
+AC_CHECK_FUNCS(vasprintf asprintf,,
+	[needasprintf=yes])
+if test $needasprintf = yes; then
+	AC_LIBOBJ([asprintf])
+fi
+
+needstrlcat=no
+AC_CHECK_FUNCS(strlcat,,
+	[needstrlcat=yes])
+if test $needstrlcat = yes; then
+	AC_LIBOBJ([strlcat])
+fi
+
+needstrlcpy=no
+AC_CHECK_FUNCS(strlcpy,,
+	[needstrlcpy=yes])
+if test $needstrlcpy = yes; then
+	AC_LIBOBJ([strlcpy])
 fi
 
 needstrtok_r=no
@@ -510,20 +590,6 @@
 #
 VALGRINDTEST_SRC=
 
-#
-# SITA support is mutually exclusive with native capture support;
-# "--with-sita" selects SITA support.
-#
-AC_ARG_WITH(sita,
-AC_HELP_STRING([--with-sita],[include SITA support]),
-[
-	if test ! "x$withval" = "xno" ; then
-		AC_DEFINE(SITA,1,[include ACN support])
-		AC_MSG_NOTICE(Enabling SITA ACN support)
-		V_PCAP=sita
-	fi
-],
-[
 AC_ARG_WITH(pcap,
 AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
 if test ! -z "$with_pcap" ; then
@@ -550,6 +616,10 @@
 		#  requires that various BSD-style integer types
 		#  be defined;
 		#
+		#  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+		#  doesn't include it but does use struct timeval
+		#  in ioctl definitions;
+		#
 		#  sys/ioctl.h and, if we have it, sys/ioccom.h,
 		#  because net/bpf.h defines ioctls;
 		#
@@ -568,6 +638,7 @@
 			AC_TRY_COMPILE(
 [
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #ifdef HAVE_SYS_IOCCOM_H
@@ -584,6 +655,7 @@
 	AC_CHECK_HEADERS(net/pfilt.h net/enet.h)
 	AC_CHECK_HEADERS(net/nit.h sys/net/nit.h)
 	AC_CHECK_HEADERS(linux/socket.h net/raw.h sys/dlpi.h)
+	AC_CHECK_HEADERS(config/HaikuConfig.h)
 
 	if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
 		#
@@ -609,11 +681,6 @@
 		# No prizes for guessing this one.
 		#
 		V_PCAP=linux
-
-		#
-		# XXX - this won't work with older kernels that have
-		# SOCK_PACKET sockets but not PF_PACKET sockets.
-		#
 		VALGRINDTEST_SRC=valgrindtest.c
 	elif test "$ac_cv_header_net_pfilt_h" = yes; then
 	        #
@@ -645,6 +712,11 @@
 		# DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
 		#
 		V_PCAP=dlpi
+	elif test "$ac_cv_header_config_HaikuConfig_h" = yes; then
+		#
+		# Haiku.
+		#
+		V_PCAP=haiku
 	else
 		#
 		# Nothing we support.
@@ -659,16 +731,16 @@
 AC_SUBST(VALGRINDTEST_SRC)
 
 #
-# Do capture-mechanism-dependent tests.
+# Do we have pkg-config?
+#
+AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
+
+#
+# Handle each capture type.
 #
 case "$V_PCAP" in
 dlpi)
 	#
-	# Needed for common functions used by pcap-[dlpi,libdlpi].c
-	#
- 	SSRC="dlpisubs.c"
-
-	#
 	# Checks for some header files.
 	#
 	AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
@@ -684,16 +756,30 @@
 	# Also, due to the bug above applications that link to libpcap with
 	# libdlpi will have to add "-L/lib" option to "configure".
 	#
-	saved_ldflags=$LDFLAGS
+	save_LDFLAGS="$LDFLAGS"
 	LDFLAGS="$LIBS -L/lib"
 	AC_CHECK_LIB(dlpi, dlpi_walk,
 		[
 			LIBS="-ldlpi $LIBS"
 			V_PCAP=libdlpi
+
+			#
+			# Capture module plus common code needed for
+			# common functions used by pcap-[dlpi,libdlpi].c
+			#
+			PLATFORM_C_SRC="pcap-libdlpi.c dlpisubs.c"
 			AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists])
 		],
-		V_PCAP=dlpi)
-	LDFLAGS=$saved_ldflags
+		[
+			V_PCAP=dlpi
+
+			#
+			# Capture module plus common code needed for
+			# common functions used by pcap-[dlpi,libdlpi].c
+			#
+			PLATFORM_C_SRC="pcap-dlpi.c dlpisubs.c"
+		])
+	LDFLAGS="$save_LDFLAGS"
 
 	#
 	# Checks whether <sys/dlpi.h> is usable, to catch weird SCO
@@ -728,8 +814,32 @@
 	    ])
 	;;
 
+enet)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-enet.c"
+	;;
+
+haiku)
+	#
+	# Capture module
+	#
+ 	PLATFORM_CXX_SRC="pcap-haiku.cpp"
+
+	#
+	# Just for the sake of it.
+	#
+	AC_CHECK_HEADERS(net/if.h net/if_dl.h net/if_types.h)
+	;;
+
 linux)
 	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-linux.c"
+
+	#
 	# Do we have the wireless extensions?
 	#
 	AC_CHECK_HEADERS(linux/wireless.h, [], [],
@@ -741,107 +851,78 @@
 
 	#
 	# Do we have libnl?
+	# We only want version 3.  Version 2 was, apparently,
+	# short-lived, and version 1 is source and binary
+	# incompatible with version 3, and it appears that,
+	# these days, everybody's using version 3.  We're
+	# not supporting older versions of the Linux kernel;
+	# let's drop support for older versions of libnl, too.
 	#
 	AC_ARG_WITH(libnl,
 	AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
 		with_libnl=$withval,with_libnl=if_available)
 
 	if test x$with_libnl != xno ; then
-		have_any_nl="no"
-
-                incdir=-I/usr/include/libnl3
-                libnldir=
-                case "$with_libnl" in
-
-                yes|if_available)
-                  ;;
-
-                *)
-                  if test -d $withval; then
-                    libnldir=-L${withval}/lib/.libs
-                    incdir=-I${withval}/include
-                  fi
-                  ;;
-                esac
-
-		#
-		# Try libnl 3.x first.
-		#
-		AC_CHECK_LIB(nl-3, nl_socket_alloc,
-		[
+		if test "x$PKGCONFIG" != "xno"; then
 			#
-			# Yes, we have libnl 3.x.
+			# We have pkg-config; see if we have libnl-genl-3.0
+			# as a package.
 			#
-			LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
-			AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
-			AC_DEFINE(HAVE_LIBNL_3_x,1,[if libnl exists and is version 3.x])
-			AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
-			AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
-			V_INCLS="$V_INCLS ${incdir}"
-			have_any_nl="yes"
-		],[], ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 )
-
-		if test x$have_any_nl = xno ; then
-			#
-			# Try libnl 2.x
-			#
-			AC_CHECK_LIB(nl, nl_socket_alloc,
-			[
-				#
-				# Yes, we have libnl 2.x.
-				#
-				LIBS="${libnldir} -lnl-genl -lnl $LIBS"
+			AC_MSG_CHECKING([for libnl-genl-3.0 with pkg-config])
+			if "$PKGCONFIG" libnl-genl-3.0; then
+				AC_MSG_RESULT([found])
+				pkg_config_found_libnl=yes
+				libnl_genl_cflags=`"$PKGCONFIG" --cflags libnl-genl-3.0`
+				V_INCLS="$V_INCLS ${libnl_genl_cflags}"
+				libnl_genl_libs=`"$PKGCONFIG" --libs libnl-genl-3.0`
+				LIBS="${libnl_genl_libs} $LIBS"
 				AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
-				AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
-				AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
-				AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
-				have_any_nl="yes"
-			])
-		fi
-
-		if test x$have_any_nl = xno ; then
-			#
-			# No, we don't; do we have libnl 1.x?
-			#
-			AC_CHECK_LIB(nl, nl_handle_alloc,
-			[
-				#
-				# Yes.
-				#
-				LIBS="${libnldir} -lnl $LIBS"
-				AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
-				have_any_nl="yes"
-			])
-		fi
-
-		if test x$have_any_nl = xno ; then
-			#
-			# No, we don't have libnl at all.
-			#
-			if test x$with_libnl = xyes ; then
-				AC_MSG_ERROR([libnl support requested but libnl not found])
+			else
+				AC_MSG_RESULT([not found])
 			fi
 		fi
+
+		if test x$pkg_config_found_libnl != xyes; then
+			#
+			# OK, either we don't have pkg-config or there
+			# wasn't a .pc file for it; Check for it directly.
+			#
+			case "$with_libnl" in
+
+			yes|if_available)
+				incdir=-I/usr/include/libnl3
+				libnldir=
+				;;
+
+			*)
+				if test -d $withval; then
+					libnldir=-L${withval}/lib
+					incdir=-I${withval}/include
+				fi
+				;;
+			esac
+
+			AC_CHECK_LIB(nl-3, nl_socket_alloc,
+			[
+				#
+				# Yes, we have libnl 3.x.
+				#
+				LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
+				AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+				V_INCLS="$V_INCLS ${incdir}"
+			],[
+				#
+				# No, we don't have libnl at all.
+				# Fail if the user explicitly requested
+				# it.
+				#
+				if test x$with_libnl = xyes ; then
+					AC_MSG_ERROR([libnl support requested but libnl not found])
+				fi
+			], ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 )
+		fi
 	fi
 
-	AC_CHECK_HEADERS(linux/ethtool.h,,,
-	    [
-AC_INCLUDES_DEFAULT
-#include <linux/types.h>
-	    ])
-
-	#
-	# Check to see if struct tpacket_stats is defined in
-	# <linux/if_packet.h>.  If so, then pcap-linux.c can use this
-	# to report proper statistics.
-	#
-	# -Scott Barron
-	#
-	AC_CHECK_TYPES(struct tpacket_stats,,,
-	    [
-		#include <linux/if_packet.h>
-	    ])
-
 	#
 	# Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
 	#
@@ -859,6 +940,11 @@
 
 bpf)
 	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-bpf.c"
+
+	#
 	# Check whether we have the *BSD-style ioctls.
 	#
 	AC_CHECK_HEADERS(net/if_media.h)
@@ -877,12 +963,44 @@
 	    ])
 	;;
 
+pf)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-pf.c"
+	;;
+
+snit)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-snit.c"
+	;;
+
+snoop)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-snoop.c"
+	;;
+
 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"
+	PLATFORM_C_SRC="pcap-dag.c"
+	xxx_only=yes
+	;;
+
+dpdk)
+	#
+	# --with-pcap=dpdk is the only way to get here, and it means
+	# "DPDK support but nothing else"
+	#
+	V_DEFS="$V_DEFS -DDPDK_ONLY"
+	PLATFORM_C_SRC="pcap-dpdk.c"
 	xxx_only=yes
 	;;
 
@@ -892,6 +1010,7 @@
 	# "Septel support but nothing else"
 	#
 	V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+	PLATFORM_C_SRC="pcap-septel.c"
 	xxx_only=yes
 	;;
 
@@ -901,10 +1020,15 @@
 	# "SNF support but nothing else"
 	#
 	V_DEFS="$V_DEFS -DSNF_ONLY"
+	PLATFORM_C_SRC="pcap-snf.c"
 	xxx_only=yes
 	;;
 
 null)
+	#
+	# Capture module
+	#
+ 	PLATFORM_C_SRC="pcap-null.c"
 	;;
 
 *)
@@ -929,7 +1053,7 @@
 		    # We have the header, so we use "getifaddrs()" to
 		    # get the list of interfaces.
 		    #
-		    V_FINDALLDEVS=fad-getad.c
+		    PLATFORM_C_SRC="$PLATFORM_C_SRC fad-getad.c"
 		],[
 		    #
 		    # We don't have the header - give up.
@@ -973,13 +1097,12 @@
 			ac_cv_lbl_have_siocglifconf=no))
 		AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
 		if test $ac_cv_lbl_have_siocglifconf = yes ; then
-			V_FINDALLDEVS=fad-glifc.c
+			PLATFORM_C_SRC="$PLATFORM_C_SRC fad-glifc.c"
 		else
-			V_FINDALLDEVS=fad-gifc.c
+			PLATFORM_C_SRC="$PLATFORM_C_SRC fad-gifc.c"
 		fi
 	])
 fi
-])
 
 dnl check for hardware timestamp support
 case "$host_os" in
@@ -991,15 +1114,6 @@
 	;;
 esac
 
-AC_ARG_ENABLE([packet-ring],
-[AC_HELP_STRING([--enable-packet-ring],[enable packet ring support on Linux @<:@default=yes@:>@])],
-,enable_packet_ring=yes)
-
-if test "x$enable_packet_ring" != "xno" ; then
-	AC_DEFINE(PCAP_SUPPORT_PACKET_RING, 1, [use packet ring capture support on Linux if available])
-	AC_SUBST(PCAP_SUPPORT_PACKET_RING)
-fi
-
 #
 # Check for socklen_t.
 #
@@ -1084,22 +1198,31 @@
 
 	if test -z "$dag_lib_dir"; then
 		dag_lib_dir="$dag_root/lib"
+		#
+		# Handle multiarch systems.
+		#
+		if test -d "$dag_lib_dir/$host"
+		then
+			dag_lib_dir="$dag_lib_dir/$host"
+		fi
 	fi
 
-	V_INCLS="$V_INCLS -I$dag_include_dir"
-
+	save_CFLAGS="$CFLAGS"
+	CFLAGS="$CFLAGS -I$dag_include_dir"
 	AC_CHECK_HEADERS([dagapi.h])
 
 	if test "$ac_cv_header_dagapi_h" = yes; then
 
+		V_INCLS="$V_INCLS -I$dag_include_dir"
+
 		if test $V_PCAP != dag ; then
-			 SSRC="$SSRC pcap-dag.c"
+			 MODULE_C_SRC="$MODULE_C_SRC pcap-dag.c"
 		fi
 
 		# Check for various DAG API functions.
 		# Don't need to save and restore LIBS to prevent -ldag being
 		# included if there's a found-action (arg 3).
-		saved_ldflags=$LDFLAGS
+		save_LDFLAGS="$LDFLAGS"
 		LDFLAGS="-L$dag_lib_dir"
 		AC_CHECK_LIB([dag], [dag_attach_stream],
 		    [],
@@ -1110,7 +1233,7 @@
 		AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
 			AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
 
-		LDFLAGS=$saved_ldflags
+		LDFLAGS="$save_LDFLAGS"
 
 		#
 		# We assume that if we have libdag we have libdagconf,
@@ -1142,10 +1265,11 @@
 		fi
 
 		if test "$want_dag" = yes; then
-	        	# User wanted DAG support but we couldn't find it.
+			# 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
+	CFLAGS="$save_CFLAGS"
 fi
 
 AC_ARG_WITH(septel,
@@ -1204,7 +1328,7 @@
 		ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 
 		if test "$V_PCAP" != septel ; then
-			 SSRC="$SSRC pcap-septel.c"
+			 MODULE_C_SRC="$MODULE_C_SRC pcap-septel.c"
 		fi
 
 		AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have the Septel API])
@@ -1218,7 +1342,7 @@
 		fi
 
 		if test "$want_septel" = yes; then
-	        	# User wanted Septel support but we couldn't find it.
+			# 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
@@ -1290,14 +1414,21 @@
 
 	if test -z "$snf_lib_dir"; then
 		snf_lib_dir="$snf_root/lib"
+		#
+		# Handle multiarch systems.
+		#
+		if test -d "$snf_lib_dir/$host"
+		then
+			snf_lib_dir="$snf_lib_dir/$host"
+		fi
 	fi
 
 	if test -f "$snf_include_dir/snf.h"; then
 		# We found a header; make sure we can link with the library
-		saved_ldflags=$LDFLAGS
+		save_LDFLAGS="$LDFLAGS"
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 		AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"])
-		LDFLAGS="$saved_ldflags"
+		LDFLAGS="$save_LDFLAGS"
 		if test "$ac_cv_lbl_snf_api" = no; then
 			AC_MSG_ERROR(SNF API cannot correctly be linked; check config.log)
 		fi
@@ -1311,7 +1442,7 @@
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 
 		if test "$V_PCAP" != snf ; then
-			SSRC="$SSRC pcap-snf.c"
+			MODULE_C_SRC="$MODULE_C_SRC pcap-snf.c"
 		fi
 
 		AC_DEFINE(HAVE_SNF_API, 1, [define if you have the Myricom SNF API])
@@ -1388,7 +1519,7 @@
 	if test $ac_cv_lbl_turbocap_api = yes; then
 		AC_MSG_RESULT(yes)
 
-		SSRC="$SSRC pcap-tc.c"
+		MODULE_C_SRC="$MODULE_C_SRC pcap-tc.c"
 		V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
 		LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
 
@@ -1397,7 +1528,7 @@
 		AC_MSG_RESULT(no)
 
 		if test "$want_turbocap" = yes; then
-	        	# User wanted Turbo support but we couldn't find it.
+			# 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
@@ -1463,9 +1594,103 @@
 		#include <sys/socket.h>
 	    ])
 
+	#
+	# Optionally, we may want to support SSL.
+	# Check for OpenSSL/libressl.
+	#
+	# First, try looking for it as a regular system library.
+	# Make sure we can find SSL_library_init() using the
+	# standard headers, just in case we're running a version
+	# of macOS that ships with the OpenSSL library but not
+	# the OpenSSL headers, and have also installed another
+	# version of OpenSSL with headers.
+	#
+	save_LIBS="$LIBS"
+	LIBS="-lssl -lcrypto"
+	AC_MSG_CHECKING(whether we have a system OpenSSL/libressl that we can use)
+	AC_TRY_LINK(
+	    [
+#include <openssl/ssl.h>
+	    ],
+	    [
+SSL_library_init();
+return 0;
+	    ],
+	    [
+		AC_MSG_RESULT(yes)
+		HAVE_OPENSSL=yes
+		OPENSSL_LIBS="-lssl -lcrypto"
+	    ],
+	    AC_MSG_RESULT(no))
+	LIBS="$save_LIBS"
+
+	#
+	# If we didn't find it, check for it with pkg-config.
+	#
+	if test "x$HAVE_OPENSSL" != "xyes"; then
+		if test "x$PKGCONFIG" != "xno"; then
+			#
+			# We have pkg-config; see if we have OpenSSL/
+			# libressl installed as a package.
+			#
+			AC_MSG_CHECKING([for OpenSSL/libressl with pkg-config])
+			if "$PKGCONFIG" openssl; then
+				AC_MSG_RESULT([found])
+				HAVE_OPENSSL=yes
+				OPENSSL_CFLAGS=`"$PKGCONFIG" --cflags openssl`
+				OPENSSL_LIBS=`"$PKGCONFIG" --libs openssl`
+			else
+				AC_MSG_RESULT([not found])
+			fi
+		fi
+	fi
+
+	#
+	# If we didn't find it, check for it under /usr/local/opt/openssl;
+	# that's where Homebrew puts it on macOS.  Feel free to add other
+	# -L directories as necessary; the "system library" check should
+	# also handle "add-on library under /usr/local", so that shouldn't
+	# be necessary here.
+	#
+	if test "x$HAVE_OPENSSL" != "xyes"; then
+		save_CFLAGS="$CFLAGS"
+		save_LIBS="$LIBS"
+		CFLAGS="$CFLAGS -L/usr/local/opt/openssl/include"
+		LIBS="$LIBS -L/usr/local/opt/openssl/lib -lssl -lcrypto"
+		AC_MSG_CHECKING(whether we have OpenSSL/libressl in /usr/local/opt that we can use)
+		AC_TRY_LINK(
+		    [
+#include <openssl/ssl.h>
+		    ],
+		    [
+SSL_library_init();
+return 0;
+		    ],
+		    [
+			AC_MSG_RESULT(yes)
+			HAVE_OPENSSL=yes
+			OPENSSL_CFLAGS="-I/usr/local/opt/openssl/include"
+			OPENSSL_LIBS="-L/usr/local/opt/openssl/lib -lssl -lcrypto"
+		    ],
+		    AC_MSG_RESULT(no))
+		CFLAGS="$save_CFLAGS"
+		LIBS="$save_LIBS"
+	fi
+
+	#
+	# OK, did we find it?
+	#
+	if test "x$HAVE_OPENSSL" = "xyes"; then
+		AC_DEFINE([HAVE_OPENSSL], [1], [Use OpenSSL])
+		CFLAGS="$CFLAGS $OPENSSL_CFLAGS"
+		LIBS="$LIBS $OPENSSL_LIBS"
+	else
+		AC_MSG_NOTICE(OpenSSL not found)
+	fi
+
 	AC_DEFINE(ENABLE_REMOTE,,
 	    [Define to 1 if remote packet capture is to be supported])
-	SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+	REMOTE_C_SRC="$REMOTE_C_SRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c sslutils.c"
 	BUILD_RPCAPD=build-rpcapd
 	INSTALL_RPCAPD=install-rpcapd
 	;;
@@ -1517,31 +1742,63 @@
 #
 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.
+case "$YACC" in
+
+*yacc)
+	#
+	# Make sure this is Berkeley YACC, not AT&T YACC; the latter
+	# doesn't support reentrant parsers.  Run it with "-V";
+	# that succeeds and reports the version number with
+	# Berkeley YACC, but will (probably) fail with various
+	# vendor flavors of AT&T YACC.
+	#
+	AC_CACHE_CHECK([for capable yacc], tcpdump_cv_capable_yacc,
+	    if $YACC -V >/dev/null 2>&1; then
+		tcpdump_cv_capable_yacc=yes
+	    else
+		tcpdump_cv_capable_yacc=insufficient
+	    fi)
+	if test $tcpdump_cv_capable_yacc = insufficient ; then
+	    AC_MSG_ERROR([$YACC is insufficient to compile libpcap.
  libpcap requires Bison, a newer version of Berkeley YACC with support
  for reentrant parsers, or another YACC compatible with them.])
-fi
+	fi
+
+	#
+	# Berkeley YACC doesn't support "%define api.pure", so use
+	# "%pure-parser".
+	#
+	REENTRANT_PARSER="%pure-parser"
+	;;
+
+*)
+	#
+	# Bison prior to 2.4(.1) doesn't support "%define api.pure", so use
+	# "%pure-parser".
+	#
+	bison_major_version=`$YACC -V | sed -n 's/.* \(@<:@1-9@:>@@<:@0-9@:>@*\)\.@<:@1-9@:>@@<:@0-9.@:>@*/\1/p'`
+	bison_minor_version=`$YACC -V | sed -n 's/.* @<:@1-9@:>@@<:@0-9@:>@*\.\(@<:@1-9@:>@@<:@0-9@:>@*\).*/\1/p'`
+	if test "$bison_major_version" -lt 2 -o \
+	    \( "$bison_major_version" -eq 2 -a "$bison_major_version" -lt 4 \)
+	then
+		REENTRANT_PARSER="%pure-parser"
+	else
+		REENTRANT_PARSER="%define api.pure"
+	fi
+	;;
+esac
+AC_SUBST(REENTRANT_PARSER)
 
 #
 # Do various checks for various OSes and versions of those OSes.
 #
 # Assume, by default, no support for shared libraries and V7/BSD
-# convention for man pages (file formats in section 5, miscellaneous
-# info in section 7, administrative commands and daemons in section 8).
-# Individual cases can override this.
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
 #
 DYEXT="none"
+MAN_DEVICES=4
 MAN_FILE_FORMATS=5
 MAN_MISC_INFO=7
 MAN_ADMIN_COMMANDS=8
@@ -1597,79 +1854,163 @@
 	if test "$enable_universal" != "no"; then
 		case "$host_os" in
 
-		darwin[0-7].*)
+		darwin[[0-7]].*)
 			#
 			# Pre-Tiger.  Build only for 32-bit PowerPC; no
 			# need for any special compiler or linker flags.
 			#
 			;;
 
-		darwin8.[0123]*)
+		darwin8.[[0123]]|darwin8.[[0123]].*)
 			#
-			# Tiger, prior to Intel support.  Build for 32-bit
-			# PowerPC and 64-bit PowerPC, with 32-bit PowerPC
-			# first.  (I'm guessing that's what Apple does.)
-			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64"
-			;;
-
-		darwin8.[456]*)
-			#
-			# Tiger, subsequent to Intel support but prior to
-			# x86-64 support.  Build for 32-bit PowerPC, 64-bit
-			# PowerPC, and x86, with 32-bit PowerPC first.
+			# Tiger, prior to Intel support.  Build
+			# libraries and executables for 32-bit PowerPC
+			# and 64-bit PowerPC, with 32-bit PowerPC first.
 			# (I'm guessing that's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386"
+			# (The double brackets are needed because
+			# autotools/m4 use brackets as a quoting
+			# character; the double brackets turn into
+			# single brackets in the generated configure
+			# file.)
+			#
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+			;;
+
+		darwin8.[[456]]|darwin.[[456]].*)
+			#
+			# Tiger, subsequent to Intel support but prior
+			# to x86-64 support.  Build libraries and
+			# executables for 32-bit PowerPC, 64-bit
+			# PowerPC, and 32-bit x86, with 32-bit PowerPC
+			# first.  (I'm guessing that's what Apple does.)
+			#
+			# (The double brackets are needed because
+			# autotools/m4 use brackets as a quoting
+			# character; the double brackets turn into
+			# single brackets in the generated configure
+			# file.)
+			#
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
 			;;
 
 		darwin8.*)
 			#
 			# All other Tiger, so subsequent to x86-64
-			# support. Build for 32-bit PowerPC, 64-bit
-			# PowerPC, x86, and x86-64, and with 32-bit PowerPC
-			# first.  (I'm guessing that's what Apple does.)
+			# support.  Build libraries and executables for
+			# 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+			# and x86-64, with 32-bit PowerPC first.  (I'm
+			# guessing that's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
 			;;
 
 		darwin9.*)
 			#
-			# Leopard.  Build for 32-bit PowerPC, 64-bit
-			# PowerPC, x86, and x86-64, with 32-bit PowerPC
-			# first.  (That's what Apple does.)
+			# Leopard.  Build libraries for 32-bit PowerPC,
+			# 64-bit PowerPC, 32-bit x86, and x86-64, with
+			# 32-bit PowerPC first, and build executables
+			# for 32-bit x86 and 32-bit PowerPC, with 32-bit
+			# x86 first.  (That's what Apple does.)
 			#
-			V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-			LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+			V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+			V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
 			;;
 
 		darwin10.*)
 			#
-			# Snow Leopard.  Build for x86-64, x86, and
-			# 32-bit PowerPC, with x86-64 first.  (That's
-			# what Apple does, even though Snow Leopard
-			# doesn't run on PPC, so PPC libpcap runs under
-			# Rosetta, and Rosetta doesn't support BPF
-			# ioctls, so PPC programs can't do live
-			# captures.)
+			# Snow Leopard.  Build libraries for x86-64,
+			# 32-bit x86, and 32-bit PowerPC, with x86-64
+			# first, and build executables for x86-64 and
+			# 32-bit x86, with x86-64 first.  (That's what
+			# Apple does, even though Snow Leopard doesn't
+			# run on PPC, so PPC libpcap runs under Rosetta,
+			# and Rosetta doesn't support BPF ioctls, so PPC
+			# programs can't do live captures.)
 			#
-			V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
-			LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
+			V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+			V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+			V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+			V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
 			;;
 
 		darwin*)
 			#
-			# Post-Snow Leopard.  Build for x86-64 and
-			# x86, with x86-64 first.  (That's probably what
-			# Apple does, given that Rosetta is gone.)
+			# Post-Snow Leopard.  Build libraries for x86-64
+			# and 32-bit x86, with x86-64 first, and build
+			# executables only for x86-64.  (That's what
+			# Apple does.)  This requires no special flags
+			# for programs.
 			# XXX - update if and when Apple drops support
-			# for 32-bit x86 code.
+			# for 32-bit x86 code and if and when Apple adds
+			# ARM-based Macs.  (You're on your own for iOS
+			# etc.)
 			#
-			V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
-			LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
+			# XXX - check whether we *can* build for
+			# i386 and, if not, suggest that the user
+			# install the /usr/include headers if they
+			# want to build fat.
+			#
+			AC_MSG_CHECKING(whether building for 32-bit x86 is supported)
+			save_CFLAGS="$CFLAGS"
+			CFLAGS="$CFLAGS -arch i386"
+			AC_TRY_LINK(
+			    [],
+			    [return 0;],
+			    [
+				AC_MSG_RESULT(yes)
+				V_LIB_CCOPT_FAT="-arch x86_64"
+				V_LIB_LDFLAGS_FAT="-arch x86_64"
+
+				#
+				# OpenSSL installation on macOS seems
+				# to install only the libs for 64-bit
+				# x86 - at least that's what Brew does:
+				# only configure 32-bit builds if we
+				# don't have OpenSSL.
+				#
+				if test "$HAVE_OPENSSL" != yes; then
+					V_LIB_CCOPT_FAT="$V_LIB_CCOPT_FAT -arch i386"
+					V_LIB_LDFLAGS_FAT="$V_LIB_LDFLAGS_FAT -arch i386"
+				fi
+			    ],
+			    [
+				AC_MSG_RESULT(no)
+				V_LIB_CCOPT_FAT="-arch x86_64"
+				V_LIB_LDFLAGS_FAT="-arch x86_64"
+				case "$host_os" in
+
+				darwin18.*)
+					#
+					# Mojave; you need to install the
+					# /usr/include headers to get
+					# 32-bit x86 builds to work.
+					#
+					AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package])
+					;;
+
+				*)
+					#
+					# Pre-Mojave; the command-line
+					# tools should be sufficient to
+					# enable 32-bit x86 builds.
+					#
+					AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools])
+					;;
+				esac
+			    ])
+			CFLAGS="$save_CFLAGS"
 			;;
 		esac
 	fi
@@ -1743,7 +2084,7 @@
 	MAN_MISC_INFO=5
 	;;
 
-linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|haiku*|midipix*)
 	DYEXT="so"
 
 	#
@@ -1766,6 +2107,7 @@
 	#
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
+	MAN_DEVICES=7
 	;;
 
 sinix*)
@@ -1809,6 +2151,7 @@
 		MAN_ADMIN_COMMANDS=1m
 		MAN_FILE_FORMATS=4
 		MAN_MISC_INFO=5
+		MAN_DEVICES=7D
 	esac
 	;;
 esac
@@ -1861,14 +2204,14 @@
 	#include <sys/dlpi_ext.h>
     ])
 
-AC_LBL_UNALIGNED_ACCESS
-
 AC_SUBST(V_CCOPT)
+AC_SUBST(V_LIB_CCOPT_FAT)
+AC_SUBST(V_LIB_LDFLAGS_FAT)
+AC_SUBST(V_PROG_CCOPT_FAT)
+AC_SUBST(V_PROG_LDFLAGS_FAT)
 AC_SUBST(V_DEFS)
-AC_SUBST(V_FINDALLDEVS)
 AC_SUBST(V_INCLS)
 AC_SUBST(V_LEX)
-AC_SUBST(V_PCAP)
 AC_SUBST(V_SHLIB_CCOPT)
 AC_SUBST(V_SHLIB_CMD)
 AC_SUBST(V_SHLIB_OPT)
@@ -1877,8 +2220,12 @@
 AC_SUBST(V_YACC)
 AC_SUBST(ADDLOBJS)
 AC_SUBST(ADDLARCHIVEOBJS)
-AC_SUBST(SSRC)
+AC_SUBST(PLATFORM_C_SRC)
+AC_SUBST(PLATFORM_CXX_SRC)
+AC_SUBST(MODULE_C_SRC)
+AC_SUBST(REMOTE_C_SRC)
 AC_SUBST(DYEXT)
+AC_SUBST(MAN_DEVICES)
 AC_SUBST(MAN_FILE_FORMATS)
 AC_SUBST(MAN_MISC_INFO)
 AC_SUBST(MAN_ADMIN_COMMANDS)
@@ -1888,94 +2235,77 @@
 AC_SUBST(RPCAPD_LIBS)
 AC_SUBST(EXTRA_NETWORK_LIBS)
 
+#
+# Various Linux-specific mechanisms.
+#
 AC_ARG_ENABLE([usb],
-[AC_HELP_STRING([--enable-usb],[enable USB capture support @<:@default=yes, if support available@:>@])],
+[AC_HELP_STRING([--enable-usb],[enable Linux usbmon USB capture support @<:@default=yes, if support available@:>@])],
     [],
     [enable_usb=yes])
 
-if test "xxx_only" = yes; then
-	# User requested something-else-only pcap, so they don't
-	# want USB support.
-	enable_usb=no
-fi
-
-if test "x$enable_usb" != "xno" ; then
-   dnl check for USB sniffing support
-   AC_MSG_CHECKING(for USB sniffing support)
-   case "$host_os" in
-   linux*)
-	AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
-	USB_SRC=pcap-usb-linux.c
-	AC_MSG_RESULT(yes)
-	ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
-	if test $? -ne 0 ; then
-	  ac_usb_dev_name="usbmon"
-	fi
-	AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
-	AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
-	#
-	# Do we have a version of <linux/compiler.h> available?
-	# If so, we might need it for <linux/usbdevice_fs.h>.
-	#
-	AC_CHECK_HEADERS(linux/compiler.h)
-	if test "$ac_cv_header_linux_compiler_h" = yes; then
-	  #
-	  # Yes - include it when testing for <linux/usbdevice_fs.h>.
-	  #
-	  AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
-	else
-	  AC_CHECK_HEADERS(linux/usbdevice_fs.h)
-	fi
-	if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
-	  #
-	  # OK, does it define bRequestType?  Older versions of the kernel
-	  # define fields with names like "requesttype, "request", and
-	  # "value", rather than "bRequestType", "bRequest", and
-	  # "wValue".
-	  #
-	  AC_CHECK_MEMBERS([struct usbdevfs_ctrltransfer.bRequestType],,,
-	      [
-		  AC_INCLUDES_DEFAULT
-		  #ifdef HAVE_LINUX_COMPILER_H
-		  #include <linux/compiler.h>
-		  #endif
-		  #include <linux/usbdevice_fs.h>
-	      ])
-	fi
-	;;
-    freebsd*)
-	#
-	# This just uses BPF in FreeBSD 8.4 and later; we don't need
-	# to check for anything special for capturing.
-	#
-	AC_MSG_RESULT([yes, in FreeBSD 8.4 and later])
-	;;
-
-    *)
-	AC_MSG_RESULT(no)
-	;;
-esac
-fi
-AC_SUBST(PCAP_SUPPORT_USB)
-AC_SUBST(USB_SRC)
-
-dnl check for netfilter sniffing support
+#
+# If somebody requested an XXX-only pcap, that doesn't include
+# additional mechanisms.
+#
 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([
+  case "$host_os" in
+  linux*)
+    dnl check for USB sniffing support
+    AC_MSG_CHECKING(for Linux usbmon USB sniffing support)
+    if test "x$enable_usb" != "xno" ; then
+      AC_DEFINE(PCAP_SUPPORT_LINUX_USBMON, 1, [target host supports Linux usbmon for USB sniffing])
+      MODULE_C_SRC="$MODULE_C_SRC pcap-usb-linux.c"
+      AC_MSG_RESULT(yes)
+      ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+      if test $? -ne 0 ; then
+        ac_usb_dev_name="usbmon"
+      fi
+      AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
+      AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
+      #
+      # Do we have a version of <linux/compiler.h> available?
+      # If so, we might need it for <linux/usbdevice_fs.h>.
+      #
+      AC_CHECK_HEADERS(linux/compiler.h)
+      if test "$ac_cv_header_linux_compiler_h" = yes; then
+        #
+        # Yes - include it when testing for <linux/usbdevice_fs.h>.
+        #
+        AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
+      else
+        AC_CHECK_HEADERS(linux/usbdevice_fs.h)
+      fi
+      if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+        #
+        # OK, does it define bRequestType?  Older versions of the kernel
+        # define fields with names like "requesttype, "request", and
+        # "value", rather than "bRequestType", "bRequest", and
+        # "wValue".
+        #
+        AC_CHECK_MEMBERS([struct usbdevfs_ctrltransfer.bRequestType],,,
+          [
+            AC_INCLUDES_DEFAULT
+            #ifdef HAVE_LINUX_COMPILER_H
+            #include <linux/compiler.h>
+            #endif
+            #include <linux/usbdevice_fs.h>
+          ])
+      fi
+    else
+      AC_MSG_RESULT(no)
+    fi
+
+    #
+    # 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>
@@ -1986,23 +2316,20 @@
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_log.h>
 #include <linux/netfilter/nfnetlink_queue.h>],
-		    [],
-		    ac_cv_netfilter_can_compile=yes,
-		    ac_cv_netfilter_can_compile=no))
-		AC_MSG_RESULT($ac_cv_netfilter_can_compile)
-		if test $ac_cv_netfilter_can_compile = yes ; then
-		  AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
-		    [target host supports netfilter sniffing])
-		  NETFILTER_SRC=pcap-netfilter-linux.c
-		fi
-		;;
-	*)
-		AC_MSG_RESULT(no)
-		;;
-	esac
+        [],
+        ac_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])
+      MODULE_C_SRC="$MODULE_C_SRC pcap-netfilter-linux.c"
+    fi
+    ;;
+  esac
 fi
+AC_SUBST(PCAP_SUPPORT_LINUX_USBMON)
 AC_SUBST(PCAP_SUPPORT_NETFILTER)
-AC_SUBST(NETFILTER_SRC)
 
 AC_ARG_ENABLE([netmap],
 [AC_HELP_STRING([--enable-netmap],[enable netmap support @<:@default=yes, if support available@:>@])],
@@ -2029,12 +2356,249 @@
 	if test $ac_cv_net_netmap_user_can_compile = yes ; then
 	  AC_DEFINE(PCAP_SUPPORT_NETMAP, 1,
 	    [target host supports netmap])
-	    NETMAP_SRC=pcap-netmap.c
+	    MODULE_C_SRC="$MODULE_C_SRC pcap-netmap.c"
 	fi
 	AC_SUBST(PCAP_SUPPORT_NETMAP)
-	AC_SUBST(NETMAP_SRC)
 fi
 
+# Check for DPDK support.
+AC_ARG_WITH([dpdk],
+AC_HELP_STRING([--with-dpdk@<:@=DIR@:>@],[include DPDK support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
+[
+	if test "$withval" = no
+	then
+		# User doesn't want DPDK support.
+		want_dpdk=no
+	elif test "$withval" = yes
+	then
+		# User wants DPDK support but hasn't specified a directory.
+		want_dpdk=yes
+	else
+		# User wants DPDK support and has specified a directory,
+		# so use the provided value.
+		want_dpdk=yes
+		dpdk_dir=$withval
+	fi
+],[
+	if test "$V_PCAP" = dpdk; then
+		# User requested DPDK-only libpcap, so we'd better have
+		# the DPDK API.
+		want_dpdk=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want DPDK support.
+		want_dpdk=no
+	else
+		#
+		# Use DPDK API if present, otherwise don't
+		#
+		want_dpdk=ifpresent
+	fi
+])
+
+if test "$want_dpdk" != no; then
+	if test "x$PKGCONFIG" != "xno"
+	then
+		#
+		# We have pkg-config; see if we have DPDK installed
+		# as a package.
+		#
+		AC_MSG_CHECKING([for DPDK with pkg-config])
+		if "$PKGCONFIG" libdpdk
+		then
+			AC_MSG_RESULT([found])
+			found_dpdk_with_pkg_config=yes
+			DPDK_CFLAGS=`"$PKGCONFIG" --cflags libdpdk`
+			DPDK_LDFLAGS=`"$PKGCONFIG" --libs libdpdk`
+		else
+			AC_MSG_RESULT([not found])
+		fi
+	fi
+
+	#
+	# If we didn't find it with pkg-config, try checking for
+	# it manually.
+	#
+	if test "x$found_dpdk_with_pkg_config" != "xyes"
+	then
+		if test -z "$dpdk_dir"; then
+			#
+			# The user didn't specify a directory containing
+			# the DPDK headers and libraries.  If we find
+			# a /usr/local/include/dpdk directory, assume
+			# it's /usr/local, otherwise assume it's /usr.
+			#
+			if test -d "/usr/local/include/dpdk"; then
+				dpdk_dir="/usr/local"
+			else
+				dpdk_dir="/usr"
+			fi
+		fi
+		#
+		# The convention appears to be that 1) there's a "dpdk"
+		# subdirectory of the include directory, containing DPDK
+		# headers (at least in the installation on Ubuntu with
+		# the system DPDK packages) and 2) includes of DPDK
+		# headers don't use "dpdk/{header}" (at least from the
+		# way the DPDK documentation is written).
+		#
+		# So we add "/dpdk" to the include directory, and always
+		# add that to the list of include directories to search.
+		#
+		dpdk_inc_dir="$dpdk_dir/include/dpdk"
+		dpdk_inc_flags="-I$dpdk_inc_dir"
+		dpdk_lib_dir="$dpdk_dir/lib"
+		#
+		# Handle multiarch systems.
+		#
+		# Step 1: run the C compiler with the -dumpmachine option;
+		# if it succeeds, the output would be the multiarch directory
+		# name if your system has multiarch directories.
+		#
+		multiarch_dir=`$CC -dumpmachine 2>/dev/null`
+		if test ! -z "$multiarch_dir"
+		then
+			#
+			# OK, we have a multiarch directory.
+			#
+			# Now deal with includes.  On Ubuntu 20.04, for
+			# example, we have /usr/include/dpdk *and*
+			# /usr/include/$multiarch_dir/dpdk, and must
+			# search both.
+			#
+			if test -d "$dpdk_dir/include/$multiarch_dir/dpdk"
+			then
+				dpdk_inc_flags="-I$dpdk_dir/include/$multiarch_dir/dpdk $dpdk_inc_flags"
+			fi
+
+			#
+			# Now deal with libraries.
+			#
+			if test -d "$dpdk_lib_dir/$multiarch_dir"
+			then
+				dpdk_lib_dir="$dpdk_lib_dir/$multiarch_dir"
+			fi
+		fi
+		DPDK_MACHINE_CFLAGS="-march=native"
+		DPDK_CFLAGS="$DPDK_MACHINE_CFLAGS $dpdk_inc_flags"
+		DPDK_LDFLAGS="-L$dpdk_lib_dir -ldpdk -lrt -lm -lnuma -ldl -pthread"
+	fi
+
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	save_LDFLAGS="$LDFLAGS"
+	CFLAGS="$CFLAGS $DPDK_CFLAGS"
+	LIBS="$LIBS $DPDK_LDFLAGS"
+	LDFLAGS="$LDFLAGS $DPDK_LDFLAGS"
+
+	AC_MSG_CHECKING(whether we can compile the DPDK support)
+	AC_CACHE_VAL(ac_cv_dpdk_can_compile,
+	AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#include <rte_common.h>],
+	    [],
+	    ac_cv_dpdk_can_compile=yes,
+	    ac_cv_dpdk_can_compile=no))
+	AC_MSG_RESULT($ac_cv_dpdk_can_compile)
+
+	#
+	# We include rte_bus.h, and older versions of DPDK
+	# didn't have it, so check for it.
+	#
+	if test "$ac_cv_dpdk_can_compile" = yes; then
+		#
+		# This runs the preprocessor, so make sure it
+		# looks in the DPDK directories.  Instead of
+		# including dpdk/XXX.h, we include just XXX.h
+		# and assume DPDK_CFLAGS is the directory
+		# containing the DPDK headers (that's how
+		# pkg-config sets it, at least on Ubuntu),
+		# so just looking under /usr/include won't
+		# find it.
+		#
+		save_CPPFLAGS="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS $DPDK_CFLAGS"
+		AC_CHECK_HEADER(rte_bus.h)
+		CPPFLAGS="$save_CPPFLAGS"
+	fi
+
+	#
+	# We call rte_eth_dev_count_avail(), and older versions
+	# of DPDK didn't have it, so check for it.
+	#
+	if test "$ac_cv_header_rte_bus_h" = yes; then
+		AC_CHECK_FUNC(rte_eth_dev_count_avail)
+	fi
+
+	CFLAGS="$save_CFLAGS"
+	LIBS="$save_LIBS"
+	LDFLAGS="$save_LDFLAGS"
+
+	if test "$ac_cv_func_rte_eth_dev_count_avail" = yes; then
+		CFLAGS="$CFLAGS $DPDK_CFLAGS"
+		LIBS="$LIBS $DPDK_LDFLAGS"
+		LDFLAGS="$LDFLAGS $DPDK_LDFLAGS"
+		V_INCLS="$V_INCLS $DPDK_CFLAGS"
+		AC_DEFINE(PCAP_SUPPORT_DPDK, 1, [target host supports DPDK])
+		if test $V_PCAP != dpdk ; then
+			MODULE_C_SRC="$MODULE_C_SRC pcap-dpdk.c"
+		fi
+
+		#
+		# Check whether the rte_ether.h file defines
+		# struct ether_addr or struct rte_ether_addr.
+		#
+		# ("API compatibility?  That's for losers!")
+		#
+		AC_CHECK_TYPES(struct rte_ether_addr,,,
+		    [
+			#include <rte_ether.h>
+		    ])
+	else
+		if test "$V_PCAP" = dpdk; then
+			# User requested DPDK-only capture support, but
+			# we couldn't the DPDK API support at all, or we
+			# found it but it wasn't a sufficiently recent
+			# version.
+			if test "$ac_cv_dpdk_can_compile" != yes; then
+				#
+				# Couldn't even find the headers.
+				#
+				AC_MSG_ERROR([DPDK support requested with --with-pcap=dpdk, but the DPDK headers weren't found at $dpdk_inc_dir: make sure the DPDK support is installed, specify a different path or paths if necessary, or don't request DPDK support])
+			else
+				#
+				# Found the headers, but we couldn't find
+				# rte_bus.h or rte_eth_dev_count_avail(),
+				# we don't have a sufficiently recent
+				# version of DPDK.
+				#
+				AC_MSG_ERROR([DPDK support requested with --with-pcap=dpdk, but we require DPDK 18.x or later; install a newer version of DPDK, or don't request DPDK support])
+			fi
+		fi
+
+		if test "$want_dpdk" = yes; then
+			# User requested DPDK-only capture support, but
+			# we couldn't the DPDK API support at all, or we
+			# found it but it wasn't a sufficiently recent
+			# version.
+			if test "$ac_cv_dpdk_can_compile" != yes; then
+				#
+				# Couldn't even find the headers.
+				#
+				AC_MSG_ERROR([DPDK support requested with --with-pcap=dpdk, but the DPDK headers weren't found at $dpdk_inc_dir: make sure the DPDK support is installed, specify a different path or paths if necessary, or don't request DPDK support])
+			else
+				#
+				# Found the headers, but we couldn't find
+				# rte_bus.h or rte_eth_dev_count_avail(),
+				# we don't have a sufficiently recent
+				# version of DPDK.
+				#
+				AC_MSG_ERROR([DPDK support requested with --with-pcap=dpdk, but we require DPDK 18.x or later: install a newer version of DPDK, or don't request DPDK support])
+			fi
+		fi
+	fi
+fi
+AC_SUBST(PCAP_SUPPORT_DPDK)
 
 AC_ARG_ENABLE([bluetooth],
 [AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
@@ -2058,7 +2622,7 @@
 			# sniffing.
 			#
 			AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
-			BT_SRC=pcap-bt-linux.c
+			MODULE_C_SRC="$MODULE_C_SRC pcap-bt-linux.c"
 			AC_MSG_NOTICE(Bluetooth sniffing is supported)
 			ac_lbl_bluetooth_available=yes
 
@@ -2085,7 +2649,7 @@
 					    AC_MSG_RESULT(yes)
 					    AC_DEFINE(PCAP_SUPPORT_BT_MONITOR,,
 					      [target host supports Bluetooth Monitor])
-					    BT_MONITOR_SRC=pcap-bt-monitor-linux.c
+					    MODULE_C_SRC="$MODULE_C_SRC pcap-bt-monitor-linux.c"
 					],
 					[
 					    AC_MSG_RESULT(no)
@@ -2117,8 +2681,6 @@
 		;;
 	esac
 	AC_SUBST(PCAP_SUPPORT_BT)
-	AC_SUBST(BT_SRC)
-	AC_SUBST(BT_MONITOR_SRC)
 fi
 
 AC_ARG_ENABLE([dbus],
@@ -2165,7 +2727,6 @@
 fi
 
 if test "x$enable_dbus" != "xno"; then
-	AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
 	if test "x$PKGCONFIG" != "xno"; then
 		AC_MSG_CHECKING([for D-Bus])
 		if "$PKGCONFIG" dbus-1; then
@@ -2188,7 +2749,7 @@
 			    [
 				AC_MSG_RESULT([yes])
 				AC_DEFINE(PCAP_SUPPORT_DBUS, 1, [support D-Bus sniffing])
-				DBUS_SRC=pcap-dbus.c
+				MODULE_C_SRC="$MODULE_C_SRC pcap-dbus.c"
 				V_INCLS="$V_INCLS $DBUS_CFLAGS"
 			    ],
 			    [
@@ -2207,21 +2768,20 @@
 		fi
 	fi
 	AC_SUBST(PCAP_SUPPORT_DBUS)
-	AC_SUBST(DBUS_SRC)
 fi
 
 AC_ARG_ENABLE([rdma],
 [AC_HELP_STRING([--enable-rdma],[enable RDMA capture support @<:@default=yes, if support available@:>@])],
     [],
-    [enable_rdmasniff=ifavailable])
+    [enable_rdma=ifavailable])
 
 if test "xxx_only" = yes; then
 	# User requested something-else-only pcap, so they don't
 	# want RDMA support.
-	enable_rdmasniff=no
+	enable_rdma=no
 fi
 
-if test "x$enable_rdmasniff" != "xno"; then
+if test "x$enable_rdma" != "xno"; then
 	AC_CHECK_LIB(ibverbs, ibv_get_device_list, [
 		AC_CHECK_HEADER(infiniband/verbs.h, [
 			#
@@ -2247,7 +2807,7 @@
 				[
 					AC_MSG_RESULT([yes])
 					AC_DEFINE(PCAP_SUPPORT_RDMASNIFF, , [target host supports RDMA sniffing])
-					RDMA_SRC=pcap-rdmasniff.c
+					MODULE_C_SRC="$MODULE_C_SRC pcap-rdmasniff.c"
 					LIBS="-libverbs $LIBS"
 				],
 				[
@@ -2257,7 +2817,6 @@
 		])
 	])
 	AC_SUBST(PCAP_SUPPORT_RDMASNIFF)
-	AC_SUBST(RDMA_SRC)
 fi
 
 AC_PROG_INSTALL
@@ -2269,12 +2828,13 @@
 	cat $srcdir/Makefile-devel-adds >> Makefile
 	make depend
 fi])
-AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
+AC_OUTPUT(Makefile grammar.y pcap-filter.manmisc pcap-linktype.manmisc
 	pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
 	pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
 	pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap
 	pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap
-	pcap_open_offline.3pcap pcap_set_tstamp_precision.3pcap
-	pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin
+	pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap
+	pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap
+	rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile
 	testprogs/Makefile)
 exit 0
diff --git a/diag-control.h b/diag-control.h
index cfc581b..47d31b9 100644
--- a/diag-control.h
+++ b/diag-control.h
@@ -48,7 +48,43 @@
 #endif
 
 /*
- * Suppress Flex warnings.
+ * Suppress "enum value not explicitly handled in switch" warnings.
+ * We may have to build on multiple different Windows SDKs, so we
+ * may not be able to include all enum values in a switch, as they
+ * won't necessarily be defined on all the SDKs, and, unlike
+ * #defines, there's no easy way to test whether a given enum has
+ * a given value.  It *could* be done by the configure script or
+ * CMake tests.
+ */
+#if defined(_MSC_VER)
+  #define DIAG_OFF_ENUM_SWITCH \
+    __pragma(warning(push)) \
+    __pragma(warning(disable:4061))
+  #define DIAG_ON_ENUM_SWITCH \
+    __pragma(warning(pop))
+#else
+  #define DIAG_OFF_ENUM_SWITCH
+  #define DIAG_ON_ENUM_SWITCH
+#endif
+
+/*
+ * Suppress "switch statement has only a default case" warnings.
+ * There's a switch in bpf_filter.c that only has additional
+ * cases on Linux.
+ */
+#if defined(_MSC_VER)
+  #define DIAG_OFF_DEFAULT_ONLY_SWITCH \
+    __pragma(warning(push)) \
+    __pragma(warning(disable:4065))
+  #define DIAG_ON_DEFAULT_ONLY_SWITCH \
+    __pragma(warning(pop))
+#else
+  #define DIAG_OFF_DEFAULT_ONLY_SWITCH
+  #define DIAG_ON_DEFAULT_ONLY_SWITCH
+#endif
+
+/*
+ * Suppress Flex, narrowing, and deprecation warnings.
  */
 #if defined(_MSC_VER)
   /*
@@ -64,7 +100,27 @@
     __pragma(warning(disable:4242)) \
     __pragma(warning(disable:4244)) \
     __pragma(warning(disable:4702))
-  #define DIAG_ON_FLEX  __pragma(warning(pop))
+  #define DIAG_ON_FLEX \
+    __pragma(warning(pop))
+
+  /*
+   * Suppress narrowing warnings.
+   */
+  #define DIAG_OFF_NARROWING \
+    __pragma(warning(push)) \
+    __pragma(warning(disable:4242)) \
+    __pragma(warning(disable:4311))
+  #define DIAG_ON_NARROWING \
+    __pragma(warning(pop))
+
+  /*
+   * Suppress deprecation warnings.
+   */
+  #define DIAG_OFF_DEPRECATION \
+    __pragma(warning(push)) \
+    __pragma(warning(disable:4996))
+  #define DIAG_ON_DEPRECATION \
+    __pragma(warning(pop))
 #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
   /*
    * This is Clang 2.8 or later; we can use "clang diagnostic
@@ -79,11 +135,31 @@
     PCAP_DO_PRAGMA(clang diagnostic push) \
     PCAP_DO_PRAGMA(clang diagnostic ignored "-Wsign-compare") \
     PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdocumentation") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshorten-64-to-32") \
     PCAP_DO_PRAGMA(clang diagnostic ignored "-Wmissing-noreturn") \
     PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunused-parameter") \
     PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
   #define DIAG_ON_FLEX \
     PCAP_DO_PRAGMA(clang diagnostic pop)
+
+  /*
+   * Suppress the only narrowing warnings you get from Clang.
+   */
+  #define DIAG_OFF_NARROWING \
+    PCAP_DO_PRAGMA(clang diagnostic push) \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshorten-64-to-32")
+
+  #define DIAG_ON_NARROWING \
+    PCAP_DO_PRAGMA(clang diagnostic pop)
+
+  /*
+   * Suppress deprecation warnings.
+   */
+  #define DIAG_OFF_DEPRECATION \
+    PCAP_DO_PRAGMA(clang diagnostic push) \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdeprecated-declarations")
+  #define DIAG_ON_DEPRECATION \
+    PCAP_DO_PRAGMA(clang diagnostic pop)
 #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
   /*
    * This is GCC 4.6 or later, or a compiler claiming to be that.
@@ -97,6 +173,21 @@
     PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
   #define DIAG_ON_FLEX \
     PCAP_DO_PRAGMA(GCC diagnostic pop)
+
+  /*
+   * GCC currently doesn't issue any narrowing warnings.
+   */
+  #define DIAG_OFF_NARROWING
+  #define DIAG_ON_NARROWING
+
+  /*
+   * Suppress deprecation warnings.
+   */
+  #define DIAG_OFF_DEPRECATION \
+    PCAP_DO_PRAGMA(GCC diagnostic push) \
+    PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")
+  #define DIAG_ON_DEPRECATION \
+    PCAP_DO_PRAGMA(GCC diagnostic pop)
 #else
   /*
    * Neither Visual Studio, nor Clang 2.8 or later, nor GCC 4.6 or later
@@ -105,6 +196,10 @@
    */
   #define DIAG_OFF_FLEX
   #define DIAG_ON_FLEX
+  #define DIAG_OFF_NARROWING
+  #define DIAG_ON_NARROWING
+  #define DIAG_OFF_DEPRECATION
+  #define DIAG_ON_DEPRECATION
 #endif
 
 #ifdef YYBYACC
@@ -127,92 +222,75 @@
   #if defined(_MSC_VER)
     /*
      * This is Microsoft Visual Studio; we can use
-     * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+     * __pragma(warning(disable:XXXX)).
      */
     #define DIAG_OFF_BISON_BYACC \
-      __pragma(warning(push)) \
       __pragma(warning(disable:4702))
-    #define DIAG_ON_BISON_BYACC  __pragma(warning(pop))
   #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
     /*
      * This is Clang 2.8 or later; we can use "clang diagnostic
-     * ignored -Wxxx" and "clang diagnostic push/pop".
+     * ignored -Wxxx".
      */
     #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic push) \
       PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshadow") \
       PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
-    #define DIAG_ON_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic pop)
   #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
     /*
      * This is GCC 4.6 or later, or a compiler claiming to be that.
-     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
-     * and "GCC diagnostic push/pop" (introduced in 4.6).
+     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2,
+     * but it may not actually work very well prior to 4.6).
      */
     #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(GCC diagnostic push) \
       PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wshadow") \
       PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
-    #define DIAG_ON_BISON_BYACC \
-      PCAP_DO_PRAGMA(GCC diagnostic pop)
   #else
     /*
      * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
      * claiming to be that; there's nothing we know of that we can do.
      */
     #define DIAG_OFF_BISON_BYACC
-    #define DIAG_ON_BISON_BYACC
   #endif
 #else
   /*
    * Bison.
    *
-   * The generated code may have functions with unreachable code, so
-   * suppress warnings about those.
+   * The generated code may have functions with unreachable code and
+   * switches with only a default case, so suppress warnings about those.
    */
   #if defined(_MSC_VER)
     /*
      * This is Microsoft Visual Studio; we can use
-     * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+     * __pragma(warning(disable:XXXX)).
      *
      * Suppress some /Wall warnings.
      */
     #define DIAG_OFF_BISON_BYACC \
-      __pragma(warning(push)) \
+      __pragma(warning(disable:4065)) \
       __pragma(warning(disable:4127)) \
       __pragma(warning(disable:4242)) \
       __pragma(warning(disable:4244)) \
       __pragma(warning(disable:4702))
-    #define DIAG_ON_BISON_BYACC  __pragma(warning(pop))
   #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
     /*
      * This is Clang 2.8 or later; we can use "clang diagnostic
-     * ignored -Wxxx" and "clang diagnostic push/pop".
+     * ignored -Wxxx".
      */
     #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic push) \
       PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
-    #define DIAG_ON_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic pop)
   #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
     /*
      * This is GCC 4.6 or later, or a compiler claiming to be that.
-     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
-     * and "GCC diagnostic push/pop" (introduced in 4.6).
+     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2,
+     * but it may not actually work very well prior to 4.6).
      */
     #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(GCC diagnostic push) \
       PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
-    #define DIAG_ON_BISON_BYACC \
-      PCAP_DO_PRAGMA(GCC diagnostic pop)
   #else
     /*
      * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
      * claiming to be that; there's nothing we know of that we can do.
      */
     #define DIAG_OFF_BISON_BYACC
-    #define DIAG_ON_BISON_BYACC
   #endif
 #endif
 
diff --git a/dlpisubs.c b/dlpisubs.c
index 5f6e41a..2ef0931 100644
--- a/dlpisubs.c
+++ b/dlpisubs.c
@@ -114,6 +114,20 @@
 }
 
 /*
+ * Does the processor for which we're compiling this support aligned loads?
+ */
+#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
+    (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
+    (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
+    (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
+    (defined(__s390__) || defined(__s390x__) || defined(__zarch__))
+    /* Yes, it does. */
+#else
+    /* No, it doesn't. */
+    #define REQUIRE_ALIGNMENT
+#endif
+
+/*
  * Loop through the packets and call the callback for each packet.
  * Return the number of packets read.
  */
@@ -127,7 +141,7 @@
 	struct pcap_pkthdr pkthdr;
 #ifdef HAVE_SYS_BUFMOD_H
 	struct sb_hdr *sbp;
-#ifdef LBL_ALIGN
+#ifdef REQUIRE_ALIGNMENT
 	struct sb_hdr sbhdr;
 #endif
 #endif
@@ -157,7 +171,7 @@
 				return (n);
 			}
 		}
-#ifdef LBL_ALIGN
+#ifdef REQUIRE_ALIGNMENT
 		if ((long)bufp & 3) {
 			sbp = &sbhdr;
 			memcpy(sbp, bufp, sizeof(*sbp));
@@ -176,7 +190,7 @@
 		bufp += caplen;
 #endif
 		++pd->stat.ps_recv;
-		if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
+		if (pcap_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
 #ifdef HAVE_SYS_BUFMOD_H
 			pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
 			pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
@@ -275,7 +289,7 @@
 		 * XXX - DL_IPNET devices default to "raw IP" rather than
 		 * "IPNET header"; see
 		 *
-		 *    http://seclists.org/tcpdump/2009/q1/202
+		 *    https://seclists.org/tcpdump/2009/q1/202
 		 *
 		 * We'd have to do DL_IOC_IPNET_INFO to enable getting
 		 * the IPNET header.
@@ -286,7 +300,7 @@
 #endif
 
 	default:
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
 		    mactype);
 		retv = -1;
 	}
diff --git a/doc/README.Win32 b/doc/README.Win32
deleted file mode 100644
index 0a42dab..0000000
--- a/doc/README.Win32
+++ /dev/null
@@ -1,46 +0,0 @@
-Under Win32, libpcap is integrated in the WinPcap packet capture system.
-WinPcap provides a framework that allows libpcap to capture the packets
-under Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000
-and Windows XP.
-WinPcap binaries and source code can be found at http://winpcap.polito.it:
-they include also a developer's pack with all the necessary to compile
-libpcap-based applications under Windows.
-
-How to compile libpcap with Visual Studio
------------------------------------------
-
-In order to compile libpcap you will need:
-
-- version 6 (or higher) of Microsoft Visual Studio
-- The November 2001 (or later) edition of Microsoft Platform
-Software Development Kit (SDK), that contains some necessary includes
-for IPv6 support. You can download it from http://www.microsoft.com/sdk
-- the latest WinPcap sources from http://winpcap.polito.it/install
-
-The WinPcap source code already contains a recent (usually the latest
-stable) version of libpcap. If you need to compile a different one,
-simply download it from www.tcpdump.org and copy the sources in the
-winpcap\wpcap\libpcap folder of the WinPcap distribution. If you want to
-compile a libpcap source retrieved from the tcpdump.org Git, you will
-have to create the scanner and the grammar by hand (with lex and yacc)
-or with the cygnus makefile, since The Visual Studio project is not able
-to build them.
-
-Open the project file winpcap\wpcap\prj\wpcap.dsw with Visual Studio and
-build wpcap.dll. wpcap.lib, the library file to link with the applications,
-will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in
-winpcap\wpcap\prj\release or winpcap\wpcap\prj\debug depending on the type
-of binary that is being created.
-
-How to compile libpcap with Cygnus
-----------------------------------
-
-To build wpcap.dll, cd to the directory WPCAP/PRJ of the WinPcap source code
-distribution and type "make". libwpcap.a, the library file to link with the
-applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be
-generated in winpcap\wpcap\prj.
-
-Remember, you CANNOT use the MSVC-generated .lib files with gcc, use
-libwpcap.a instead.
-
-"make install" installs wpcap.dll in the Windows system folder.
diff --git a/doc/README.Win32.md b/doc/README.Win32.md
new file mode 100644
index 0000000..626f89b
--- /dev/null
+++ b/doc/README.Win32.md
@@ -0,0 +1,198 @@
+Building libpcap on Windows with Visual Studio
+==============================================
+
+Unlike the UN*Xes on which libpcap can capture network traffic, Windows
+has no network traffic capture mechanism that libpcap can use.
+Therefore, libpcap requires a driver, and a library to access the
+driver, provided by the Npcap or WinPcap projects.
+
+Those projects include versions of libpcap built to use that driver and
+library; these instructions are for people who want to build libpcap
+source releases, or libpcap from the Git repository, as a replacement
+for the version provided with Npcap or WinPcap.
+
+Npcap and WinPcap SDK
+---------------------
+
+In order to build libpcap, you will need to download Npcap and its
+software development kit (SDK) or WinPcap and its software development
+kit.
+
+Npcap is currently being developed and maintained, and offers many
+additional capabilities that WinPcap does not.
+
+WinPcap is no longer being developed or maintained; it should be used
+only if there is some other requirement to use it rather than Npcap,
+such as a requirement to support versions of Windows earlier than
+Windows Vista, which is the earliest version supported by Npcap.
+
+Npcap and its SDK can be downloaded from its home page:
+
+  https://npcap.org
+
+The SDK is a ZIP archive; create a folder on your C: drive, e.g.
+C:\npcap-sdk, and put the contents of the ZIP archive into that folder.
+
+The WinPcap installer can be downloaded from
+
+  https://www.winpcap.org/install/default.htm
+
+and the WinPcap Developer's Kit can be downloaded from
+
+  https://www.winpcap.org/devel.htm
+
+Required build tools
+--------------------
+
+The Developer's Kit is a ZIP archive; it contains a folder named
+WpdPack, which you should place on your C: drive, e.g. C:\WpdPack.
+
+Building libpcap on Windows requires Visual Studio 2015 or later.  The
+Community Edition of Visual Studio can be downloaded at no cost from
+
+  https://visualstudio.microsoft.com
+
+Additional tools are also required.  Chocolatey is a package manager for
+Windows with which those tools, and other tools, can be installed; it
+can be downloaded from
+
+  https://chocolatey.org
+
+It is a command-line tool; a GUI tool, Chocolatey GUI, is provided as a
+Chocolatey package, which can be installed from the command line:
+
+	choco install chocolateygui
+
+For convenience, the "choco install" command can be run with the "-y"
+flag, forcing it to automatically answer all questions asked of the user
+with "yes":
+
+	choco install -y chocolateygui
+
+The required tools are:
+
+### CMake ###
+
+libpcap does not provide supported project files for Visual Studio
+(there are currently unsupported project files provided, but we do not
+guarantee that they will work or that we will continue to provide them).
+It does provide files for CMake, which is a cross-platform tool that
+runs on UN*Xes and on Windows and that can generate project files for
+UN*X Make, the Ninja build system, and Visual Studio, among other build
+systems.
+
+Visual Studio 2015 does not provide CMake; an installer can be
+downloaded from
+
+  https://cmake.org/download/
+
+When you run the installer, you should choose to add CMake to the system
+PATH for all users and to create the desktop icon.
+
+CMake can also be installed as the Chocolatey package "cmake":
+
+	choco install -y cmake
+
+Visual Studio 2017 and later provide CMake, so you will not need to
+install CMake if you have installed Visual Studio 2017 or later.  They
+include built-in support for CMake-based projects:
+
+  https://devblogs.microsoft.com/cppblog/cmake-support-in-visual-studio/
+
+For Visual Studio 2017, make sure "Visual C++ tools for CMake" is
+installed; for Visual Studio 2019, make sure "C++ CMake tools for
+Windows" is intalled.
+
+### winflexbison ###
+
+libpcap uses the Flex lexical-analyzer generator and the Bison or
+Berkeley YACC parser generators to generate the parser for filter
+expressions.  Windows versions of Flex and Bison can be downloaded from
+
+  https://sourceforge.net/projects/winflexbison/
+
+The downloaded file is a ZIP archive; create a folder on your C: drive,
+e.g. C:\Program Files\winflexbison, and put the contents of the ZIP
+archive into that folder.  Then add that folder to the system PATH
+environment variable.
+
+Git
+---
+
+An optional tool, required only if you will be building from a Git
+repository rather than from a release source tarball, is Git.  Git is
+provided as an optional installation component, "Git for Windows", with
+Visual Studio 2017 and later.
+
+Building from the Visual Studio GUI
+-----------------------------------
+
+### Visual Studio 2017 ###
+
+Open the folder containing the libpcap source with Open > Folder.
+Visual Studio will run CMake; however, you will need to indicate where
+the Npcap or WinPcap SDK is installed.
+
+To do this, go to Project > "Change CMake Settings" > pcap and:
+
+Choose which configuration type to build, if you don't want the default
+Debug build.
+
+In the CMakeSettings.json tab, change cmakeCommandArgs to include
+
+	-DPacket_ROOT={path-to-sdk}
+
+where {path-to-sdk} is the path of the directory containing the Npcap or
+WinPcap SDK.  Note that backslashes in the path must be specified as two
+backslashes.
+
+Save the configuration changes with File > "Save CMakeSettings.json" or
+with control-S.
+
+Visual Studio will then re-run CMake.  If that completes without errors,
+you can build with CMake > "Build All".
+
+### Visual Studio 2019 ###
+
+Open the folder containing the libpcap source with Open > Folder.
+Visual Studio will run CMake; however, you will need to indicate where
+the Npcap or WinPcap SDK is installed.
+
+To do this, go to Project > "CMake Settings for pcap" and:
+
+Choose which configuration type to build, if you don't want the default
+Debug build.
+
+Scroll down to "Cmake variables and cache", scroll through the list
+looking for the entry for Packet_ROOT, and either type in the path of
+the directory containing the Npcap or WinPcap SDK or use the "Browse..."
+button to browse for that directory.
+
+Save the configuration changes with File > "Save CMakeSettings.json" or
+with control-S.
+
+Visual Studio will then re-run CMake.  If that completes without errors,
+you can build with Build > "Build All".
+
+Building from the command line
+------------------------------
+
+Start the appropriate Native Tools command line prompt.
+
+Change to the directory into which you want to build libpcap, possibly
+after creating it first.  One choice is to create it as a subdirectory
+of the libpcap source directory.
+
+Run the command
+
+	cmake "-DPacket_ROOT={path-to-sdk}" {path-to-libpcap-source}
+
+where {path-to-sdk} is the path of the directory containing the Npcap or
+WinPcap SDK and {path-to-libpcap-source} is the pathname of the
+top-level source directory for libpcap.
+
+Run the command
+
+	msbuild/m pcap.sln
+
+to compile libpcap.
diff --git a/doc/README.aix b/doc/README.aix
index 92e513f..9e9a23d 100644
--- a/doc/README.aix
+++ b/doc/README.aix
@@ -27,7 +27,7 @@
     If you fix the problems yourself, please submit a patch by forking
     the branch at
 
-	https://github.com/the-tcpdump-group/libpcap/issues
+	https://github.com/the-tcpdump-group/libpcap/tree/master
 
     and issuing a pull request, so we can incorporate the fixes into the
     next release.
diff --git a/doc/README.capture-module b/doc/README.capture-module
new file mode 100644
index 0000000..e13eaf3
--- /dev/null
+++ b/doc/README.capture-module
@@ -0,0 +1,353 @@
+		    How to write a libpcap module
+
+WARNING: this document describes an unstable interface; future releases
+of libpcap may, and some probably will, change the interface in an
+incompatible fashion.  If you submit your module to the libpcap
+developers for inclusion in libpcap, not only does that make it more
+likely that it will be available in the libpcap provided by operating
+system vendors (such as Linux distributions), but it also means that we
+will attempt to update it to handle future changes to this interface.
+If we add new capabilities, we may have to ask you how to provide those
+additional capabilities if you're using an underlying mechanism for
+which we have neither the source code nor the documentation.
+
+NOTE: this document assumes familiarity with the entire libpcap API.
+
+TODO: more routines, more stuff that the activate routine has to do
+(such as setting the list of DLT_s), convert to Markdown?
+
+On Linux, *BSD, macOS, Solaris, AIX, HP-UX, IRIX, and Tru64 UNIX,
+Libpcap supports capturing on network interfaces as supported by the
+operating system networking stack, using the native packet capture
+mechanism provided by the OS.  On Windows, it supports it with the help
+of the driver and library supplied by WinPcap and Npcap.
+
+In addition, it also supports capturing on other types of devices, such
+as:
+
+	specialized capture cards, such as Endace DAG cards;
+
+	network adapters that provide special high-performance code
+	paths, such as CSPI Myricom adapters;
+
+	buses such as USB;
+
+	software communication channels such as D-Bus and Linux netlink;
+
+	etc..
+
+Support for those devices is provided by modules compiled into libpcap.
+
+If you want to add such a module, you would first have to check the list
+of link-layer header types supported by libpcap, to see if one of those
+would be sufficient for your device.  The current version of the list
+can be found at
+
+	https://www.tcpdump.org/linktypes.html
+
+If none of those would work for your device, please read
+doc/DLT_ALLOCATE_HOWTO.md and the introductory paragraphs on the Web
+page mentioned above, and then send a request for the new link-layer
+header type to tcpdump-workers@lists.tcpdump.org.
+
+Once you have a link-layer header type value or values that you can use,
+you can add new module.
+
+The module should be a C source file, with a name of the form
+pcap-{MOD}.c, where {MOD} is a name appropriate for your device; for
+example, the support for DAG cards is in pcap-dag.c, and the support for
+capturing USB traffic on Linux is pcap-usb-linux.c.
+
+Your module is assumed to support one or more named devices.  The names
+should be relatively short names, containing only lower-case
+alphanumeric characters, consisting of a prefix that ends with an
+alphabetic character and, if there can be more than one device instance,
+possibly followed by a numerical device ID, such as "mydevice" or
+"mydevice0"/"mydevice1"/....  If you have more than one type of device
+that you can support, you can have more than one prefix, each of which
+can be followed by a numerical device ID.
+
+The two exported functions that your module must provide are routines to
+provide a list of device instances and a program to initialize a
+created-but-not-activated pcap_t for an instance of one of your devices.
+
+The "list of device instances" routine takes, as arguments:
+
+	a pointer to a pcap_if_list_t;
+
+	a pointer to an error message buffer.
+
+The error message buffer may be assumed to be PCAP_ERRBUF_SIZE bytes
+large, but must not be assumed to be larger.  By convention, the routine
+typically has a name containing "findalldevs".
+
+The routine should attempt to determine what device instances are
+available and add them to the list pointed to by the first argument;
+this may be impossible for some modules, but, for those modules, it may
+be difficult to capture on the devices using Wirehshark (although it
+should be possible to capture on them using tcpdump, TShark, or other
+programs that take a device name on the command line), so we recommend
+that your routine provide the list of devices if possible.  If it
+cannot, it should just immediately return 0.
+
+The routine should add devices to the list by calling the add_dev()
+routine in libpcap, declared in the pcap-int.h header.  It takes, as
+arguments:
+
+	the pointer to the pcap_if_list_t passed as an argument to the
+	routine;
+
+	the device name, as described above;
+
+	a 32-bit word of flags, as provided by pcap_findalldevs();
+
+	a text description of the device, or NULL if there is no
+	description;
+
+	the error message buffer pointer provided to the routine.
+
+add_dev() will, if it succeeds, return a pointer to a pcap_if_t that was
+added to the list of devices.  If it fails, it will return NULL; in this
+case, the error message buffer has been filled in with an error string,
+and your routine must return -1 to indicate the error.
+
+If your routine succeeds, it must return 0.  If it fails, it must fill
+in the error message buffer with an error string and return -1.
+
+The "initialize the pcap_t" routine takes, as arguments:
+
+	a pointer to a device name;
+
+	a pointer to an error message buffer;
+
+	a pointer to an int.
+
+It returns a pointer to a pcap_t.
+
+Your module will probably need, for each pcap_t for an opened device, a
+private data structure to maintain its own information about the opened
+device.  These should be allocated per opened instance, not per device;
+if, for example, mydevice0 can be captured on by more than one program
+at the same time, there will be more than one pcap_t opened for
+mydevice0, and so there will be separate private data structures for
+each pcap_t.  If you need to maintain per-device, rather than per-opened
+instance information, you will have to maintain that yourself.
+
+The routine should first check the device to see whether it looks like a
+device that this module would handle; for example, it should begin with
+one of the device name prefixes for your module and, if your devices
+have instance numbers, be followed by a number.  If it is not one of
+those devices, you must set the integer pointed to by the third
+argument to 0, to indicate that this is *not* one of the devices for
+your module, and return NULL.
+
+If it *is* one of those devices, it should call pcap_create_common,
+passing to it the error message buffer as the first argument and the
+size of the per-opened instance data structure as the second argument.
+If it fails, it will return NULL; you must return NULL in this case.
+
+If it succeeds, the pcap_t pointed to by the return value has been
+partially initialized, but you will need to complete the process.  It
+has a "priv" member, which is a void * that points to the private data
+structure attached to it; that structure has been initialized to zeroes.
+
+What you need to set are some function pointers to your routines to
+handle certain operations:
+
+	activate_op
+		the routine called when pcap_activate() is done on the
+		pcap_t
+
+	can_set_rfmon_op
+		the routine called when pcap_can_set_rfmon() is done on
+		the pcap_t - if your device doesn't support 802.11
+		monitor mode, you can leave this as initialized by
+		pcap_create_common(), as that routine will return "no,
+		monitor mode isn't supported".
+
+Once you've set the activate_op and, if necessary, the can_set_rfmon_op,
+you must return the pcap_t * that was returned to you.
+
+Your activate routine takes, as an argument, a pointer to the pcap_t
+being activated, and returns an int.
+
+The perameters set for the device in the pcap_create() call, and after
+that call(), are mostly in the opt member of the pcap_t:
+
+	device
+		the name of the device
+
+	timeout
+		the buffering timeout, in milliseconds
+
+	buffer_size
+		the buffer size to use
+
+	promisc
+		1 if promiscuous mode is to be used, 0 otherwise
+
+	rfmon
+		1 if monitor mode is to be used, 0 otherwise
+
+	immediate
+		1 if the device should be in immediate mode, 0 otherwise
+
+	nonblock
+		1 if the device should be in non-blocking mode, 0
+		otherwise
+
+	tstamp_type
+		the type of time stamp to supply
+
+	tstamp_precision
+		the time stamp precision to supply
+
+The snapshot member of the pcap_t structure will contain the snapshot
+length to be used.
+
+Your routine should attempt to set up the device for capturing.  If it
+fails, it must return an error indication which is one of the PCAP_ERROR
+values.  For PCAP_ERROR, it must also set the errbuf member of the
+pcap_t to an error string.  For PCAP_ERROR_NO_SUCH_DEVICE and
+PCAP_ERROR_PERM_DENIED, it may set it to an error string providing
+additional information that may be useful for debugging, or may just
+leave it as a null string.
+
+If it succeeds, it must set certain function pointers in the pcap_t
+structure:
+
+	read_op
+		called whenever packets are to be read
+
+	inject_op
+		called whenever packets are to be injected
+
+	setfilter_op
+		called whenever pcap_setfilter() is called
+
+	setdirection_op
+		called whenever pcap_setdirection() is called
+
+	set_datalink_op
+		called whnever pcap_set_datalink() is called
+
+	getnonblock_op
+		called whenever pcap_getnonblock() is called
+
+	setnonblock_op
+		called whenever pcap_setnonblock() is called
+
+	stats_op
+		called whenever pcap_stats() is called
+
+	cleanup_op
+		called if the activate routine fails or pcap_close() is
+		called
+
+and must also set the linktype member to the DLT_ value for the device.
+
+On UN*Xes, if the device supports waiting for packets to arrive with
+select()/poll()/epoll()/kqueues etc., it should set the selectable_fd
+member of the structure to the descriptor you would use with those
+calls.  If it does not, then, if that's because the device polls for
+packets rather than receiving interrupts or other signals when packets
+arrive, it should have a struct timeval in the private data structure,
+set the value of that struct timeval to the poll timeout, and set the
+required_select_timeout member of the pcap_t to point to the struct
+timeval.
+
+The read_op routine is called when pcap_dispatch(), pcap_loop(),
+pcap_next(), or pcap_next_ex() is called.  It is passed the same
+arguments as pcap_dispatch() is called.
+
+The routine should first check if the break_loop member of the pcap_t is
+non-zero and, if so, set that member to zero and return
+PCAP_ERROR_BREAK.
+
+Then, if the pcap_t is in blocking mode (as opposed to non-blocking
+mode), and there are no packets immediately available to be passed to
+the callback, it should block waiting for packets to arrive, using the
+buffering timeout, first, and read packets from the device if necessary.
+
+Then it should loop through the available packets, calling the callback
+routine for each packet:
+
+	If the PACKET_COUNT_IS_UNLIMITED() macro evaluates to true when
+	passed the packet count argument, the loop should continue until
+	there are no more packets immediately available or the
+	break_loop member of the pcap_t is non-zero.  If the break_loop
+	member is fount to be non-zero, it should set that member to
+	zero and return PCAP_ERROR_BREAK.
+
+	If it doesn't evaluat to true, then the loop should also
+	terminate if the specified number of packets have been delivered
+	to the callback.
+
+Note that there is *NO* requirement that the packet header or data
+provided to the callback remain available, or valid, after the callback
+routine returns; if the callback needs to save the data for other code
+to use, it must make a copy of that data.  This means that the module is
+free to, for example, overwrite the buffer into which it read the
+packet, or release back to the kernel a packet in a memory-mapped
+buffer shared between the kernel and userland, after the callback
+returns.
+
+If an error occurs when reading packets from the device, it must set the
+errbuf member of the pcap_t to an error string and return PCAP_ERROR.
+
+If no error occurs, it must return the number of packets that were
+supplied to the callback routine.
+
+The inject routine is passed a pointer to the pcap_t, a buffer
+containing the contents of the packet to inject, and the number of bytes
+in the packet.  If the device doesn't support packet injection, the
+routine must set the errbuf member of the pcap_t to a message indicating
+that packet injection isn't supported and return PCAP_ERROR.  Otherwise,
+it should attempt to inject the packet; if the attempt fails, it must
+set the errbuf member of the pcap_t to an error message and return
+PCAP_ERROR.  Otherwise, it should return the number of bytes injected.
+
+The setfilter routine is passed a pointer to the pcap_t and a pointer
+to a struct bpf_program containing a BPF program to be used as a filter.
+If the mechanism used by your module can perform filtering with a BPF
+program, it would attempt to set that filter to the specified program.
+
+If that failed because the program was too large, or used BPF features
+not supported by that mechanism, the module should fall back on
+filtering in userland by saving a copy of the filter with a call to
+install_bpf_program(), setting a flag in the private data instructure
+indicating that filtering is being done by the module and, in the read
+routine's main loop, checking the flag and, if it's set, calling
+pcap_filter(), passing it the fcode.bf_insns member of the pcap_t, the
+raw packet data, the on-the-wire length of the packet, and the captured
+length of the packet, and only passing the packet to the callback
+routine, and counting it, if pcap_filter() returns a non-zero value.
+(If the flag is not set, all packets should be passed to the callback
+routine and counted, as the filtering is being done by the mechanism
+used by the module.)  If install_bpf_program() returns a negative value,
+the routine should return PCAP_ERROR.
+
+If the attempt to set the filter failed for any other reason, the
+routine must set the errbuf member of the pcap_t to an error message and
+return PCAP_ERROR.
+
+If the attempt to set the filter succeeded, or it failed because the
+mechanism used by the module rejected it and the call to
+install_bpf_program() succeeded, the routine should return 0.
+
+If the mechanism the module uses doesn't support filtering, the pointer
+to the setfilter routine can just be set to point to
+install_bpf_program; the module does not need a routine of its own to
+handle that.
+
+The setdirection routine is passed a pointer to the pcap_t and a
+pcap_direction_t indicating which packet directions should be accepted.
+If the module can't arrange to handle only incoming packets or only
+outgoing packets, it can set the pointer to the setdirection routine to
+NULL, and calls to pcap_setdirection() will fail with an error message
+indicating that setting the direction isn't supported.
+
+XXX describe set_datalink, including what the activate routine has to do
+XXX
+
+XXX describe the rest of the routines XXX
diff --git a/doc/README.dag b/doc/README.dag
index accae7c..13332c6 100644
--- a/doc/README.dag
+++ b/doc/README.dag
@@ -1,11 +1,11 @@
 
 The following instructions apply if you have a Linux or FreeBSD platform and
 want libpcap to support the DAG range of passive network monitoring cards from
-Endace (http://www.endace.com, see below for further contact details).
+Endace (https://www.endace.com, see below for further contact details).
 
 1) Install and build the DAG software distribution by following the
 instructions supplied with that package. Current Endace customers can download
-the DAG software distibution from https://www.endace.com
+the DAG software distribution from https://www.endace.com
 
 2) Configure libcap. To allow the 'configure' script to locate the DAG
 software distribution use the '--with-dag' option:
@@ -88,7 +88,7 @@
 as dag0. These are visible via pcap_findalldevs().
 
 libpcap now does NOT set the card's hardware snaplen (slen). This must now be
-set using the appropriate DAG coniguration program, e.g. dagthree, dagfour,
+set using the appropriate DAG configuration program, e.g. dagthree, dagfour,
 dagsix, dagconfig. This is because the snaplen is currently shared between
 all of the streams. In future this may change if per-stream slen is
 implemented.
@@ -117,6 +117,6 @@
 
 Please also visit our Web site at:
 
-        http://www.endace.com/
+        https://www.endace.com/
 
 For more information about Endace DAG cards contact <sales@endace.com>.
diff --git a/doc/README.hpux b/doc/README.hpux
index 65ecff9..b995eee 100644
--- a/doc/README.hpux
+++ b/doc/README.hpux
@@ -8,7 +8,7 @@
 able to see packets sent from the machine on which they're running.
 Some articles on groups.google.com discussing this are:
 
-	http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
+	https://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
 
 which says:
 
@@ -69,7 +69,7 @@
 
 and
 
-	http://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no
+	https://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no
 
 which says:
 
@@ -118,7 +118,7 @@
 
 Another posting:
 
-	http://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com
+	https://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com
 
 indicates that you need to install the optional STREAMS product to do
 captures on HP-UX 9.x:
@@ -159,7 +159,7 @@
 	   of an interface
 	A: You need to get PHNE_20892,PHNE_20725 and PHCO_10947 (or
 	   newer, this is as of 4.4.00) and its dependencies.  Then you can
-	   enable the feature as descibed below:
+	   enable the feature as described below:
 
 	Patch Name: PHNE_20892
 	Patch Description: s700 10.20 PCI 100Base-T cumulative patch
diff --git a/doc/README.linux.md b/doc/README.linux.md
index ffcb928..143dff6 100644
--- a/doc/README.linux.md
+++ b/doc/README.linux.md
@@ -1,73 +1,8 @@
-In order for libpcap to be able to capture packets on a Linux system,
-the "packet" protocol must be supported by your kernel.  If it is not,
-you may get error messages such as
+Currently, libpcap supports packet capturing on Linux 2.6.27 and later;
+earlier versions are not supported.
 
-	modprobe: can't locate module net-pf-17
-
-in "/var/adm/messages", or may get messages such as
-
-	socket: Address family not supported by protocol
-
-from applications using libpcap.
-
-You must configure the kernel with the CONFIG_PACKET option for this
-protocol; the following note is from the Linux "Configure.help" file for
-the 2.0[.x] kernel:
-
-	Packet socket
-	CONFIG_PACKET
-	  The Packet protocol is used by applications which communicate
-	  directly with network devices without an intermediate network
-	  protocol implemented in the kernel, e.g. tcpdump. If you want them
-	  to work, choose Y.
-
-	  This driver is also available as a module called af_packet.o ( =
-	  code which can be inserted in and removed from the running kernel
-	  whenever you want). If you want to compile it as a module, say M
-	  here and read Documentation/modules.txt; if you use modprobe or
-	  kmod, you may also want to add "alias net-pf-17 af_packet" to
-	  /etc/modules.conf.
-
-and the note for the 2.2[.x] kernel says:
-
-	Packet socket
-	CONFIG_PACKET
-	  The Packet protocol is used by applications which communicate
-	  directly with network devices without an intermediate network
-	  protocol implemented in the kernel, e.g. tcpdump. If you want them
-	  to work, choose Y. This driver is also available as a module called
-	  af_packet.o ( = code which can be inserted in and removed from the
-	  running kernel whenever you want). If you want to compile it as a
-	  module, say M here and read Documentation/modules.txt.  You will
-	  need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules
-	  file for the module version to function automatically.  If unsure,
-	  say Y.
-
-In addition, there is an option that, in 2.2 and later kernels, will
-allow packet capture filters specified to programs such as tcpdump to be
-executed in the kernel, so that packets that don't pass the filter won't
-be copied from the kernel to the program, rather than having all packets
-copied to the program and libpcap doing the filtering in user mode.
-
-Copying packets from the kernel to the program consumes a significant
-amount of CPU, so filtering in the kernel can reduce the overhead of
-capturing packets if a filter has been specified that discards a
-significant number of packets.  (If no filter is specified, it makes no
-difference whether the filtering isn't performed in the kernel or isn't
-performed in user mode. :-))
-
-The option for this is the CONFIG_FILTER option; the "Configure.help"
-file says:
-
-	Socket filtering
-	CONFIG_FILTER
-	  The Linux Socket Filter is derived from the Berkeley Packet Filter.
-	  If you say Y here, user-space programs can attach a filter to any
-	  socket and thereby tell the kernel that it should allow or disallow
-	  certain types of data to get through the socket. Linux Socket
-	  Filtering works on all socket types except TCP for now. See the text
-	  file linux/Documentation/networking/filter.txt for more information.
-	  If unsure, say N.
+You must configure 2.26.x kernels with the CONFIG_PACKET_MMAP option for
+this protocol.  3.x and later kernels do not require that.
 
 Note that, by default, libpcap will, if libnl is present, build with it;
 it uses libnl to support monitor mode on mac80211 devices.  There is a
@@ -94,13 +29,6 @@
 Statistics reported by pcap are platform specific.  The statistics
 reported by pcap_stats on Linux are as follows:
 
-2.2.x
-=====
-ps_recv   Number of packets that were accepted by the pcap filter
-ps_drop   Always 0, this statistic is not gatherd on this platform
-
-2.4.x
-=====
 ps_recv   Number of packets that were accepted by the pcap filter
 ps_drop   Number of packets that had passed filtering but were not
           passed on to pcap due to things like buffer shortage, etc.
diff --git a/doc/README.septel b/doc/README.septel
index fa2c0c9..203ec1a 100644
--- a/doc/README.septel
+++ b/doc/README.septel
@@ -1,6 +1,6 @@
 The following instructions apply if you have a Linux platform and want
 libpcap to support the Septel range of passive network monitoring cards
-from Intel (http://www.intel.com)
+from Intel (https://www.intel.com)
 
 1) Install and build the Septel software distribution by following the
 instructions supplied with that package.
diff --git a/doc/README.sita b/doc/README.sita
index 5a65822..37003f5 100644
--- a/doc/README.sita
+++ b/doc/README.sita
@@ -1,6 +1,13 @@
+NOTE: this is not currently supported; the configure script doesn't
+support --with-sita, and CMake doesn't support enabling SITA ACN
+support.  The code currently does not compile; it should really be
+implemented as an additional remote capture mechanism, using a URL,
+rather than as a separate version of libpcap that supports only the ACN
+product, but the infrastructure for that isn't yet available.
+
 The following instructions apply if you have a Linux platform and want
 libpcap to support the 'ACN' WAN/LAN router product from SITA
-(http://www.sita.aero)
+(https://www.sita.aero)
 
 This might also work on non-Linux Unix-compatible platforms, but that
 has not been tested.
@@ -12,7 +19,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.ac file; that can be created if neccessay by
+a correct configure.ac file; that can be created if necessary by
 using the normal autoconf procedure of:
 
 aclocal
diff --git a/etherent.c b/etherent.c
index 5f49961..69da9a5 100644
--- a/etherent.c
+++ b/etherent.c
@@ -25,7 +25,6 @@
 
 #include <pcap-types.h>
 
-#include <ctype.h>
 #include <memory.h>
 #include <stdio.h>
 #include <string.h>
@@ -45,14 +44,18 @@
 static inline u_char
 xdtoi(u_char c)
 {
-	if (isdigit(c))
+	if (c >= '0' && c <= '9')
 		return (u_char)(c - '0');
-	else if (islower(c))
+	else if (c >= 'a' && c <= 'f')
 		return (u_char)(c - 'a' + 10);
 	else
 		return (u_char)(c - 'A' + 10);
 }
 
+/*
+ * Skip linear white space (space and tab) and any CRs before LF.
+ * Stop when we hit a non-white-space character or an end-of-line LF.
+ */
 static inline int
 skip_space(FILE *f)
 {
@@ -60,7 +63,7 @@
 
 	do {
 		c = getc(f);
-	} while (isspace(c) && c != '\n');
+	} while (c == ' ' || c == '\t' || c == '\r');
 
 	return c;
 }
@@ -97,7 +100,7 @@
 
 		/* If this is a comment, or first thing on line
 		   cannot be Ethernet address, skip the line. */
-		if (!isxdigit(c)) {
+		if (!PCAP_ISXDIGIT(c)) {
 			c = skip_line(fp);
 			if (c == EOF)
 				return (NULL);
@@ -110,7 +113,7 @@
 			c = getc(fp);
 			if (c == EOF)
 				return (NULL);
-			if (isxdigit(c)) {
+			if (PCAP_ISXDIGIT(c)) {
 				d <<= 4;
 				d |= xdtoi((u_char)c);
 				c = getc(fp);
@@ -126,7 +129,7 @@
 		}
 
 		/* Must be whitespace */
-		if (!isspace(c)) {
+		if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
 			c = skip_line(fp);
 			if (c == EOF)
 				return (NULL);
@@ -156,7 +159,8 @@
 			c = getc(fp);
 			if (c == EOF)
 				return (NULL);
-		} while (!isspace(c) && --namesize != 0);
+		} while (c != ' ' && c != '\t' && c != '\r' && c != '\n'
+		    && --namesize != 0);
 		*bp = '\0';
 
 		/* Eat trailing junk */
diff --git a/ethertype.h b/ethertype.h
index 51f6308..e34e07b 100644
--- a/ethertype.h
+++ b/ethertype.h
@@ -32,58 +32,58 @@
  */
 
 #ifndef ETHERTYPE_PUP
-#define	ETHERTYPE_PUP		0x0200	/* PUP protocol */
+#define ETHERTYPE_PUP		0x0200	/* PUP protocol */
 #endif
 #ifndef ETHERTYPE_IP
-#define	ETHERTYPE_IP		0x0800	/* IP protocol */
+#define ETHERTYPE_IP		0x0800	/* IP protocol */
 #endif
 #ifndef ETHERTYPE_ARP
 #define ETHERTYPE_ARP		0x0806	/* Addr. resolution protocol */
 #endif
-#ifndef ETHERTYPE_REVARP
-#define ETHERTYPE_REVARP	0x8035	/* reverse Addr. resolution protocol */
-#endif
 #ifndef ETHERTYPE_NS
 #define ETHERTYPE_NS		0x0600
 #endif
 #ifndef	ETHERTYPE_SPRITE
-#define	ETHERTYPE_SPRITE	0x0500
+#define ETHERTYPE_SPRITE	0x0500
 #endif
 #ifndef ETHERTYPE_TRAIL
 #define ETHERTYPE_TRAIL		0x1000
 #endif
 #ifndef	ETHERTYPE_MOPDL
-#define	ETHERTYPE_MOPDL		0x6001
+#define ETHERTYPE_MOPDL		0x6001
 #endif
 #ifndef	ETHERTYPE_MOPRC
-#define	ETHERTYPE_MOPRC		0x6002
+#define ETHERTYPE_MOPRC		0x6002
 #endif
 #ifndef	ETHERTYPE_DN
-#define	ETHERTYPE_DN		0x6003
+#define ETHERTYPE_DN		0x6003
 #endif
 #ifndef	ETHERTYPE_LAT
-#define	ETHERTYPE_LAT		0x6004
+#define ETHERTYPE_LAT		0x6004
 #endif
 #ifndef ETHERTYPE_SCA
 #define ETHERTYPE_SCA		0x6007
 #endif
+#ifndef ETHERTYPE_TEB
+#define ETHERTYPE_TEB		0x6558
+#endif
 #ifndef ETHERTYPE_REVARP
-#define ETHERTYPE_REVARP	0x8035
+#define ETHERTYPE_REVARP	0x8035	/* reverse Addr. resolution protocol */
 #endif
 #ifndef	ETHERTYPE_LANBRIDGE
-#define	ETHERTYPE_LANBRIDGE	0x8038
+#define ETHERTYPE_LANBRIDGE	0x8038
 #endif
 #ifndef	ETHERTYPE_DECDNS
-#define	ETHERTYPE_DECDNS	0x803c
+#define ETHERTYPE_DECDNS	0x803c
 #endif
 #ifndef	ETHERTYPE_DECDTS
-#define	ETHERTYPE_DECDTS	0x803e
+#define ETHERTYPE_DECDTS	0x803e
 #endif
 #ifndef	ETHERTYPE_VEXP
-#define	ETHERTYPE_VEXP		0x805b
+#define ETHERTYPE_VEXP		0x805b
 #endif
 #ifndef	ETHERTYPE_VPROD
-#define	ETHERTYPE_VPROD		0x805c
+#define ETHERTYPE_VPROD		0x805c
 #endif
 #ifndef ETHERTYPE_ATALK
 #define ETHERTYPE_ATALK		0x809b
@@ -101,10 +101,10 @@
 #define ETHERTYPE_IPV6		0x86dd
 #endif
 #ifndef ETHERTYPE_MPLS
-#define ETHERTYPE_MPLS          0x8847
+#define ETHERTYPE_MPLS		0x8847
 #endif
 #ifndef ETHERTYPE_MPLS_MULTI
-#define ETHERTYPE_MPLS_MULTI    0x8848
+#define ETHERTYPE_MPLS_MULTI	0x8848
 #endif
 #ifndef ETHERTYPE_PPPOED
 #define ETHERTYPE_PPPOED	0x8863
@@ -116,7 +116,7 @@
 #define ETHERTYPE_8021AD	0x88a8
 #endif
 #ifndef	ETHERTYPE_LOOPBACK
-#define	ETHERTYPE_LOOPBACK	0x9000
+#define ETHERTYPE_LOOPBACK	0x9000
 #endif
 #ifndef ETHERTYPE_8021QINQ
 #define ETHERTYPE_8021QINQ	0x9100
diff --git a/extract.h b/extract.h
index aa3ff99..e776a9e 100644
--- a/extract.h
+++ b/extract.h
@@ -25,15 +25,94 @@
 
 #include <pcap/pcap-inttypes.h>
 #include <pcap/compiler-tests.h>
+#include "portability.h"
 
 /*
- * Macros to extract possibly-unaligned big-endian integral values.
+ * If we have versions of GCC or Clang that support an __attribute__
+ * to say "if we're building with unsigned behavior sanitization,
+ * don't complain about undefined behavior in this function", we
+ * label these functions with that attribute - we *know* it's undefined
+ * in the C standard, but we *also* know it does what we want with
+ * the ISA we're targeting and the compiler we're using.
+ *
+ * For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined));
+ * pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether
+ * GCC or Clang first had __attribute__((no_sanitize(XXX)).
+ *
+ * For Clang, we check for __attribute__((no_sanitize(XXX)) with
+ * __has_attribute, as there are versions of Clang that support
+ * __attribute__((no_sanitize("undefined")) but don't support
+ * __attribute__((no_sanitize_undefined)).
+ *
+ * We define this here, rather than in funcattrs.h, because we
+ * only want it used here, we don't want it to be broadly used.
+ * (Any printer will get this defined, but this should at least
+ * make it harder for people to find.)
  */
-#ifdef LBL_ALIGN
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
+#define UNALIGNED_OK	__attribute__((no_sanitize_undefined))
+#elif __has_attribute(no_sanitize)
+#define UNALIGNED_OK	__attribute__((no_sanitize("undefined")))
+#else
+#define UNALIGNED_OK
+#endif
+
+#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
+    (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
+    (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
+    (defined(__s390__) || defined(__s390x__) || defined(__zarch__))
 /*
- * The processor doesn't natively handle unaligned loads.
+ * The processor natively handles unaligned loads, so we can just
+ * cast the pointer and fetch through it.
+ *
+ * XXX - are those all the x86 tests we need?
+ * XXX - are those the only 68k tests we need not to generated
+ * unaligned accesses if the target is the 68000 or 68010?
+ * XXX - are there any tests we don't need, because some definitions are for
+ * compilers that also predefine the GCC symbols?
+ * XXX - do we need to test for both 32-bit and 64-bit versions of those
+ * architectures in all cases?
  */
-#if PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \
+UNALIGNED_OK static inline uint16_t
+EXTRACT_BE_U_2(const void *p)
+{
+	return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+UNALIGNED_OK static inline int16_t
+EXTRACT_BE_S_2(const void *p)
+{
+	return ((int16_t)ntohs(*(const int16_t *)(p)));
+}
+
+UNALIGNED_OK static inline uint32_t
+EXTRACT_BE_U_4(const void *p)
+{
+	return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+UNALIGNED_OK static inline int32_t
+EXTRACT_BE_S_4(const void *p)
+{
+	return ((int32_t)ntohl(*(const int32_t *)(p)));
+}
+
+UNALIGNED_OK static inline uint64_t
+EXTRACT_BE_U_8(const void *p)
+{
+	return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
+		((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
+UNALIGNED_OK static inline int64_t
+EXTRACT_BE_S_8(const void *p)
+{
+	return ((int64_t)(((int64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
+		((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+#elif PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \
     (defined(__alpha) || defined(__alpha__) || \
      defined(__mips) || defined(__mips__))
 /*
@@ -52,7 +131,7 @@
  *
  * 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
+ * "ntohl()", which might be better 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
@@ -93,45 +172,90 @@
 } __attribute__((packed)) unaligned_uint16_t;
 
 typedef struct {
+	int16_t		val;
+} __attribute__((packed)) unaligned_int16_t;
+
+typedef struct {
 	uint32_t	val;
 } __attribute__((packed)) unaligned_uint32_t;
 
-static inline uint16_t
-EXTRACT_16BITS(const void *p)
+typedef struct {
+	int32_t		val;
+} __attribute__((packed)) unaligned_int32_t;
+
+UNALIGNED_OK static inline uint16_t
+EXTRACT_BE_U_2(const void *p)
 {
 	return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
 }
 
-static inline uint32_t
-EXTRACT_32BITS(const void *p)
+UNALIGNED_OK static inline int16_t
+EXTRACT_BE_S_2(const void *p)
+{
+	return ((int16_t)ntohs(((const unaligned_int16_t *)(p))->val));
+}
+
+UNALIGNED_OK static inline uint32_t
+EXTRACT_BE_U_4(const void *p)
 {
 	return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
 }
 
-static inline uint64_t
-EXTRACT_64BITS(const void *p)
+UNALIGNED_OK static inline int32_t
+EXTRACT_BE_S_4(const void *p)
 {
-	return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+	return ((int32_t)ntohl(((const unaligned_int32_t *)(p))->val));
+}
+
+UNALIGNED_OK static inline uint64_t
+EXTRACT_BE_U_8(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 */
+UNALIGNED_OK static inline int64_t
+EXTRACT_BE_S_8(const void *p)
+{
+	return ((int64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
+		((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+#else
 /*
- * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * This architecture doesn't natively support unaligned loads, and either
+ * 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.
+ *
+ * XXX - ARM is a special case.  ARMv1 through ARMv5 didn't suppory
+ * unaligned loads; ARMv6 and later support it *but* have a bit in
+ * the system control register that the OS can set and that causes
+ * unaligned loads to fault rather than succeeding.
+ *
+ * At least some OSes may set that flag, so we do *not* treat ARM
+ * as supporting unaligned loads.  If your OS supports them on ARM,
+ * and you want to use them, please update the tests in the #if above
+ * to check for ARM *and* for your OS.
  */
-#define EXTRACT_16BITS(p) \
+#define EXTRACT_BE_U_2(p) \
 	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
 	            ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
-#define EXTRACT_32BITS(p) \
+#define EXTRACT_BE_S_2(p) \
+	((int16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+	           ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
+#define EXTRACT_BE_U_4(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) \
+#define EXTRACT_BE_S_4(p) \
+	((int32_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_BE_U_8(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) | \
@@ -140,47 +264,67 @@
 	            ((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 */
+#define EXTRACT_BE_S_8(p) \
+	((int64_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)))
+
 /*
- * The processor natively handles unaligned loads, so we can just
- * cast the pointer and fetch through it.
+ * Extract an IPv4 address, which is in network byte order, and not
+ * necessarily aligned, and provide the result in host byte order.
  */
-static inline uint16_t
-EXTRACT_16BITS(const void *p)
-{
-	return ((uint16_t)ntohs(*(const uint16_t *)(p)));
-}
+#define EXTRACT_IPV4_TO_HOST_ORDER(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)))
+#endif /* unaligned access checks */
 
-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) \
+/*
+ * Non-power-of-2 sizes.
+ */
+#define EXTRACT_BE_U_3(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) \
+#define EXTRACT_BE_S_3(p) \
+	(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
+	  ((int32_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))) : \
+	  ((int32_t)(0xFF000000U | \
+	             ((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_BE_U_5(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) \
+#define EXTRACT_BE_S_5(p) \
+	(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
+	  ((int64_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))) : \
+	  ((int64_t)(INT64_T_CONSTANT(0xFFFFFF0000000000U) | \
+	             ((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_BE_U_6(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) | \
@@ -188,7 +332,23 @@
 	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
 
-#define EXTRACT_56BITS(p) \
+#define EXTRACT_BE_S_6(p) \
+	(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
+	   ((int64_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))) : \
+	  ((int64_t)(INT64_T_CONSTANT(0xFFFFFFFF00000000U) | \
+	              ((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_BE_U_7(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) | \
@@ -197,24 +357,53 @@
 	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
 	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
 
+#define EXTRACT_BE_S_7(p) \
+	(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
+	  ((int64_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))) : \
+	    ((int64_t)(INT64_T_CONSTANT(0xFFFFFFFFFF000000U) | \
+	             ((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) \
+#define EXTRACT_LE_U_2(p) \
 	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
 	            ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
-#define EXTRACT_LE_32BITS(p) \
+#define EXTRACT_LE_S_2(p) \
+	((int16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	           ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_U_4(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) \
+#define EXTRACT_LE_S_4(p) \
+	((int32_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_U_3(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) \
+#define EXTRACT_LE_S_3(p) \
+	((int32_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_U_8(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) | \
@@ -223,3 +412,12 @@
 	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
 	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
 	            ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_S_8(p) \
+	((int64_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 5236fbb..ba8f975 100644
--- a/fad-getad.c
+++ b/fad-getad.c
@@ -42,7 +42,6 @@
 
 #include <net/if.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -190,7 +189,7 @@
 			 * We have a ":"; is it followed by a number?
 			 */
 			q = p + 1;
-			while (isdigit((unsigned char)*q))
+			while (PCAP_ISDIGIT(*q))
 				q++;
 			if (*q == '\0') {
 				/*
diff --git a/fad-gifc.c b/fad-gifc.c
index 6b16127..8940876 100644
--- a/fad-gifc.c
+++ b/fad-gifc.c
@@ -49,19 +49,13 @@
 #include <net/if.h>
 #include <netinet/in.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#else
-#define INT_MAX		2147483647
-#endif
 
 #include "pcap-int.h"
 
@@ -178,7 +172,7 @@
 		 * Don't let the buffer size get bigger than INT_MAX.
 		 */
 		if (buf_size > INT_MAX) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "interface information requires more than %u bytes",
 			    INT_MAX);
 			(void)close(fd);
@@ -399,7 +393,7 @@
 			 * We have a ":"; is it followed by a number?
 			 */
 			q = p + 1;
-			while (isdigit((unsigned char)*q))
+			while (PCAP_ISDIGIT(*q))
 				q++;
 			if (*q == '\0') {
 				/*
diff --git a/fad-glifc.c b/fad-glifc.c
index f22f56d..6b275eb 100644
--- a/fad-glifc.c
+++ b/fad-glifc.c
@@ -50,7 +50,6 @@
 #include <net/if.h>
 #include <netinet/in.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <memory.h>
 #include <stdio.h>
@@ -311,7 +310,7 @@
 			 * We have a ":"; is it followed by a number?
 			 */
 			q = p + 1;
-			while (isdigit((unsigned char)*q))
+			while (PCAP_ISDIGIT(*q))
 				q++;
 			if (*q == '\0') {
 				/*
diff --git a/fmtutils.c b/fmtutils.c
index f1a8907..5c7ddad 100644
--- a/fmtutils.c
+++ b/fmtutils.c
@@ -47,12 +47,220 @@
 #include <string.h>
 #include <errno.h>
 
-#include <pcap/pcap.h>
+#include "pcap-int.h"
 
 #include "portability.h"
 
 #include "fmtutils.h"
 
+#ifdef _WIN32
+#include "charconv.h"
+#endif
+
+/*
+ * Set the encoding.
+ */
+#ifdef _WIN32
+/*
+ * True if we shouold use UTF-8.
+ */
+static int use_utf_8;
+
+void
+pcap_fmt_set_encoding(unsigned int opts)
+{
+	if (opts == PCAP_CHAR_ENC_UTF_8)
+		use_utf_8 = 1;
+}
+#else
+void
+pcap_fmt_set_encoding(unsigned int opts _U_)
+{
+	/*
+	 * Nothing to do here.
+	 */
+}
+#endif
+
+#ifdef _WIN32
+/*
+ * Convert a null-terminated UTF-16LE string to UTF-8, putting it into
+ * a buffer starting at the specified location and stopping if we go
+ * past the specified size.  This will only put out complete UTF-8
+ * sequences.
+ *
+ * We do this ourselves because Microsoft doesn't offer a "convert and
+ * stop at a UTF-8 character boundary if we run out of space" routine.
+ */
+#define IS_LEADING_SURROGATE(c) \
+	((c) >= 0xd800 && (c) < 0xdc00)
+#define IS_TRAILING_SURROGATE(c) \
+	((c) >= 0xdc00 && (c) < 0xe000)
+#define SURROGATE_VALUE(leading, trailing) \
+	(((((leading) - 0xd800) << 10) | ((trailing) - 0xdc00)) + 0x10000)
+#define REPLACEMENT_CHARACTER	0x0FFFD
+
+static char *
+utf_16le_to_utf_8_truncated(const wchar_t *utf_16, char *utf_8,
+    size_t utf_8_len)
+{
+	wchar_t c, c2;
+	uint32_t uc;
+
+	if (utf_8_len == 0) {
+		/*
+		 * Not even enough room for a trailing '\0'.
+		 * Don't put anything into the buffer.
+		 */
+		return (utf_8);
+	}
+
+	while ((c = *utf_16++) != '\0') {
+		if (IS_LEADING_SURROGATE(c)) {
+			/*
+			 * Leading surrogate.  Must be followed by
+			 * a trailing surrogate.
+			 */
+			c2 = *utf_16;
+			if (c2 == '\0') {
+				/*
+				 * Oops, string ends with a lead
+				 * surrogate.  Try to drop in
+				 * a REPLACEMENT CHARACTER, and
+				 * don't move the string pointer,
+				 * so on the next trip through
+				 * the loop we grab the terminating
+				 * '\0' and quit.
+				 */
+				uc = REPLACEMENT_CHARACTER;
+			} else {
+				/*
+				 * OK, we can consume this 2-octet
+				 * value.
+				 */
+				utf_16++;
+				if (IS_TRAILING_SURROGATE(c2)) {
+					/*
+					 * Trailing surrogate.
+					 * This calculation will,
+					 * for c being a leading
+					 * surrogate and c2 being
+					 * a trailing surrogate,
+					 * produce a value between
+					 * 0x100000 and 0x10ffff,
+					 * so it's always going to be
+					 * a valid Unicode code point.
+					 */
+					uc = SURROGATE_VALUE(c, c2);
+				} else {
+					/*
+					 * Not a trailing surroage;
+					 * try to drop in a
+					 * REPLACEMENT CHARACTER.
+					 */
+					uc = REPLACEMENT_CHARACTER;
+				}
+			}
+		} else {
+			/*
+			 * Not a leading surrogate.
+			 */
+			if (IS_TRAILING_SURROGATE(c)) {
+				/*
+				 * Trailing surrogate without
+				 * a preceding leading surrogate.
+				 * Try to drop in a REPLACEMENT
+				 * CHARACTER.
+				 */
+				uc = REPLACEMENT_CHARACTER;
+			} else {
+				/*
+				 * This is a valid BMP character;
+				 * drop it in.
+				 */
+				uc = c;
+			}
+		}
+
+		/*
+		 * OK, uc is a valid Unicode character; how
+		 * many bytes worth of UTF-8 does it require?
+		 */
+		if (uc < 0x0080) {
+			/* 1 byte. */
+			if (utf_8_len < 2) {
+				/*
+				 * Not enough room for that byte
+				 * plus a trailing '\0'.
+				 */
+				break;
+			}
+			*utf_8++ = (char)uc;
+			utf_8_len--;
+		} else if (uc < 0x0800) {
+			/* 2 bytes. */
+			if (utf_8_len < 3) {
+				/*
+				 * Not enough room for those bytes
+				 * plus a trailing '\0'.
+				 */
+				break;
+			}
+			*utf_8++ = ((uc >> 6) & 0x3F) | 0xC0;
+			*utf_8++ = ((uc >> 0) & 0x3F) | 0x80;
+			utf_8_len -= 2;
+		} else if (uc < 0x010000) {
+			/* 3 bytes. */
+			if (utf_8_len < 4) {
+				/*
+				 * Not enough room for those bytes
+				 * plus a trailing '\0'.
+				 */
+				break;
+			}
+			*utf_8++ = ((uc >> 12) & 0x0F) | 0xE0;
+			*utf_8++ = ((uc >> 6) & 0x3F) | 0x80;
+			*utf_8++ = ((uc >> 0) & 0x3F) | 0x80;
+			utf_8_len -= 3;
+		} else {
+			/* 4 bytes. */
+			if (utf_8_len < 5) {
+				/*
+				 * Not enough room for those bytes
+				 * plus a trailing '\0'.
+				 */
+				break;
+			}
+			*utf_8++ = ((uc >> 18) & 0x03) | 0xF0;
+			*utf_8++ = ((uc >> 12) & 0x3F) | 0x80;
+			*utf_8++ = ((uc >> 6) & 0x3F) | 0x80;
+			*utf_8++ = ((uc >> 0) & 0x3F) | 0x80;
+			utf_8_len -= 3;
+		}
+	}
+
+	/*
+	 * OK, we have enough room for (at least) a trailing '\0'.
+	 * (We started out with enough room, thanks to the test
+	 * for a zero-length buffer at the beginning, and if
+	 * there wasn't enough room for any character we wanted
+	 * to put into the buffer *plus* a trailing '\0',
+	 * we'd have quit before putting it into the buffer,
+	 * and thus would have left enough room for the trailing
+	 * '\0'.)
+	 *
+	 * Drop it in.
+	 */
+	*utf_8 = '\0';
+
+	/*
+	 * Return a pointer to the terminating '\0', in case we
+	 * want to drop something in after that.
+	 */
+	return (utf_8);
+}
+#endif /* _WIN32 */
+
 /*
  * Generate an error message based on a format, arguments, and an
  * errno, with a message for the errno after the formatted output.
@@ -65,14 +273,120 @@
 	size_t msglen;
 	char *p;
 	size_t errbuflen_remaining;
-#if defined(HAVE_STRERROR_S)
-	errno_t err;
-#elif defined(HAVE_STRERROR_R)
-	int err;
-#endif
 
 	va_start(ap, fmt);
-	pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+	vsnprintf(errbuf, errbuflen, fmt, ap);
+	va_end(ap);
+	msglen = strlen(errbuf);
+
+	/*
+	 * Do we have enough space to append ": "?
+	 * Including the terminating '\0', that's 3 bytes.
+	 */
+	if (msglen + 3 > errbuflen) {
+		/* No - just give them what we've produced. */
+		return;
+	}
+	p = errbuf + msglen;
+	errbuflen_remaining = errbuflen - msglen;
+	*p++ = ':';
+	*p++ = ' ';
+	*p = '\0';
+	errbuflen_remaining -= 2;
+
+	/*
+	 * Now append the string for the error code.
+	 */
+#if defined(HAVE__WCSERROR_S)
+	/*
+	 * We have a Windows-style _wcserror_s().
+	 * Generate a UTF-16LE error message.
+	 */
+	wchar_t utf_16_errbuf[PCAP_ERRBUF_SIZE];
+	errno_t err = _wcserror_s(utf_16_errbuf, PCAP_ERRBUF_SIZE, errnum);
+	if (err != 0) {
+		/*
+		 * It doesn't appear to be documented anywhere obvious
+		 * what the error returns from _wcserror_s().
+		 */
+		snprintf(p, errbuflen_remaining, "Error %d", errnum);
+		return;
+	}
+
+	/*
+	 * Now convert it from UTF-16LE to UTF-8, dropping it in the
+	 * remaining space in the buffer, and truncating it - cleanly,
+	 * on a UTF-8 character boundary - if it doesn't fit.
+	 */
+	utf_16le_to_utf_8_truncated(utf_16_errbuf, p, errbuflen_remaining);
+
+	/*
+	 * Now, if we're not in UTF-8 mode, convert errbuf to the
+	 * local code page.
+	 */
+	if (!use_utf_8)
+		utf_8_to_acp_truncated(errbuf);
+#elif defined(HAVE_GNU_STRERROR_R)
+	/*
+	 * We have a GNU-style strerror_r(), which is *not* guaranteed to
+	 * do anything to the buffer handed to it, and which returns a
+	 * pointer to the error string, which may or may not be in
+	 * the buffer.
+	 *
+	 * It is, however, guaranteed to succeed.
+	 */
+	char strerror_buf[PCAP_ERRBUF_SIZE];
+	char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE);
+	snprintf(p, errbuflen_remaining, "%s", errstring);
+#elif defined(HAVE_POSIX_STRERROR_R)
+	/*
+	 * We have a POSIX-style strerror_r(), which is guaranteed to fill
+	 * in the buffer, but is not guaranteed to succeed.
+	 */
+	int err = strerror_r(errnum, p, errbuflen_remaining);
+	if (err == EINVAL) {
+		/*
+		 * UNIX 03 says this isn't guaranteed to produce a
+		 * fallback error message.
+		 */
+		snprintf(p, errbuflen_remaining, "Unknown error: %d",
+		    errnum);
+	} else if (err == ERANGE) {
+		/*
+		 * UNIX 03 says this isn't guaranteed to produce a
+		 * fallback error message.
+		 */
+		snprintf(p, errbuflen_remaining,
+		    "Message for error %d is too long", errnum);
+	}
+#else
+	/*
+	 * We have neither _wcserror_s() nor strerror_r(), so we're
+	 * stuck with using pcap_strerror().
+	 */
+	snprintf(p, errbuflen_remaining, "%s", pcap_strerror(errnum));
+#endif
+}
+
+#ifdef _WIN32
+/*
+ * Generate an error message based on a format, arguments, and a
+ * Win32 error, with a message for the Win32 error after the formatted output.
+ */
+void
+pcap_fmt_errmsg_for_win32_err(char *errbuf, size_t errbuflen, DWORD errnum,
+    const char *fmt, ...)
+{
+	va_list ap;
+	size_t msglen;
+	char *p;
+	size_t errbuflen_remaining;
+	DWORD retval;
+	wchar_t utf_16_errbuf[PCAP_ERRBUF_SIZE];
+	size_t utf_8_len;
+
+	va_start(ap, fmt);
+	vsnprintf(errbuf, errbuflen, fmt, ap);
 	va_end(ap);
 	msglen = strlen(errbuf);
 
@@ -94,38 +408,53 @@
 
 	/*
 	 * Now append the string for the error code.
+	 *
+	 * XXX - what language ID to use?
+	 *
+	 * For UN*Xes, pcap_strerror() may or may not return localized
+	 * strings.
+	 *
+	 * We currently don't have localized messages for libpcap, but
+	 * we might want to do so.  On the other hand, if most of these
+	 * messages are going to be read by libpcap developers and
+	 * perhaps by developers of libpcap-based applications, English
+	 * might be a better choice, so the developer doesn't have to
+	 * get the message translated if it's in a language they don't
+	 * happen to understand.
 	 */
-#if defined(HAVE_STRERROR_S)
-	err = strerror_s(p, errbuflen_remaining, errnum);
-	if (err != 0) {
+	retval = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK,
+	    NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+	    utf_16_errbuf, PCAP_ERRBUF_SIZE, NULL);
+	if (retval == 0) {
 		/*
-		 * It doesn't appear to be documented anywhere obvious
-		 * what the error returns from strerror_s().
+		 * Failed.
 		 */
-		pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum);
+		snprintf(p, errbuflen_remaining,
+		    "Couldn't get error message for error (%lu)", errnum);
+		return;
 	}
-#elif defined(HAVE_STRERROR_R)
-	err = strerror_r(errnum, p, errbuflen_remaining);
-	if (err == EINVAL) {
-		/*
-		 * UNIX 03 says this isn't guaranteed to produce a
-		 * fallback error message.
-		 */
-		pcap_snprintf(p, errbuflen_remaining, "Unknown error: %d",
-		    errnum);
-	} else if (err == ERANGE) {
-		/*
-		 * UNIX 03 says this isn't guaranteed to produce a
-		 * fallback error message.
-		 */
-		pcap_snprintf(p, errbuflen_remaining,
-		    "Message for error %d is too long", errnum);
-	}
-#else
+
 	/*
-	 * We have neither strerror_s() nor strerror_r(), so we're
-	 * stuck with using pcap_strerror().
+	 * Now convert it from UTF-16LE to UTF-8.
 	 */
-	pcap_snprintf(p, errbuflen_remaining, "%s", pcap_strerror(errnum));
-#endif
+	p = utf_16le_to_utf_8_truncated(utf_16_errbuf, p, errbuflen_remaining);
+
+	/*
+	 * Now append the error number, if it fits.
+	 */
+	utf_8_len = p - errbuf;
+	errbuflen_remaining -= utf_8_len;
+	if (utf_8_len == 0) {
+		/* The message was empty. */
+		snprintf(p, errbuflen_remaining, "(%lu)", errnum);
+	} else
+		snprintf(p, errbuflen_remaining, " (%lu)", errnum);
+
+	/*
+	 * Now, if we're not in UTF-8 mode, convert errbuf to the
+	 * local code page.
+	 */
+	if (!use_utf_8)
+		utf_8_to_acp_truncated(errbuf);
 }
+#endif
diff --git a/fmtutils.h b/fmtutils.h
index 62c78fd..ba0f66c 100644
--- a/fmtutils.h
+++ b/fmtutils.h
@@ -40,9 +40,16 @@
 extern "C" {
 #endif
 
+void	pcap_fmt_set_encoding(unsigned int);
+
 void	pcap_fmt_errmsg_for_errno(char *, size_t, int,
     PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
 
+#ifdef _WIN32
+void	pcap_fmt_errmsg_for_win32_err(char *, size_t, DWORD,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ftmacros.h b/ftmacros.h
index de8da98..3fafab8 100644
--- a/ftmacros.h
+++ b/ftmacros.h
@@ -83,22 +83,20 @@
    * least with HP's C compiler; hopefully doing so won't make it
    * *not* work with *un*-threaded code.
    */
-#elif defined(__linux__) || defined(linux) || defined(__linux)
+#else
   /*
-   * We can't turn _GNU_SOURCE on because some versions of GNU Libc
-   * will give the GNU version of strerror_r(), which returns a
-   * string pointer and doesn't necessarily fill in the buffer,
-   * rather than the standard version of strerror_r(), which
-   * returns 0 or an errno and always fills in the buffer.  We
-   * require both of the latter behaviors.
+   * Turn on _GNU_SOURCE to get everything GNU libc has to offer,
+   * including asprintf(), if we're using GNU libc.
    *
-   * So we try turning everything else on that we can.  This includes
-   * defining _XOPEN_SOURCE as 600, because we want to force crypt()
-   * to be declared on systems that use GNU libc, such as most Linux
-   * distributions.
+   * Unfortunately, one thing it has to offer is a strerror_r()
+   * that's not POSIX-compliant, but we deal with that in
+   * pcap_fmt_errmsg_for_errno().
+   *
+   * We don't limit this to, for example, Linux and Cygwin, because
+   * this might, for example, be GNU/HURD or one of Debian's kFreeBSD
+   * OSes ("GNU/FreeBSD").
    */
-  #define _POSIX_C_SOURCE 200809L
-  #define _XOPEN_SOURCE 600
+  #define _GNU_SOURCE
 
   /*
    * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get
diff --git a/gencode.c b/gencode.c
index 959a56e..2978859 100644
--- a/gencode.c
+++ b/gencode.c
@@ -50,6 +50,8 @@
 
 #include "pcap-int.h"
 
+#include "extract.h"
+
 #include "ethertype.h"
 #include "nlpid.h"
 #include "llc.h"
@@ -65,7 +67,7 @@
 #include "grammar.h"
 #include "scanner.h"
 
-#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+#if defined(linux)
 #include <linux/types.h>
 #include <linux/if_packet.h>
 #include <linux/filter.h>
@@ -137,10 +139,6 @@
 
 #define ETHERMTU	1500
 
-#ifndef ETHERTYPE_TEB
-#define ETHERTYPE_TEB 0x6558
-#endif
-
 #ifndef IPPROTO_HOPOPTS
 #define IPPROTO_HOPOPTS 0
 #endif
@@ -246,6 +244,7 @@
 struct _compiler_state {
 	jmp_buf top_ctx;
 	pcap_t *bpf_pcap;
+	int error_set;
 
 	struct icode ic;
 
@@ -277,6 +276,13 @@
 	struct addrinfo *ai;
 
 	/*
+	 * Another thing that's allocated is the result of pcap_ether_aton();
+	 * it must be freed with free().  This variable points to any
+	 * address that would need to be freed.
+	 */
+	u_char *e;
+
+	/*
 	 * Various code constructs need to know the layout of the packet.
 	 * These values give the necessary offsets from the beginning
 	 * of the packet data.
@@ -417,35 +423,61 @@
 	int cur_chunk;
 };
 
-void PCAP_NORETURN
-bpf_syntax_error(compiler_state_t *cstate, const char *msg)
+/*
+ * For use by routines outside this file.
+ */
+/* VARARGS */
+void
+bpf_set_error(compiler_state_t *cstate, const char *fmt, ...)
 {
-	bpf_error(cstate, "syntax error in filter expression: %s", msg);
-	/* NOTREACHED */
+	va_list ap;
+
+	/*
+	 * If we've already set an error, don't override it.
+	 * The lexical analyzer reports some errors by setting
+	 * the error and then returning a LEX_ERROR token, which
+	 * is not recognized by any grammar rule, and thus forces
+	 * the parse to stop.  We don't want the error reported
+	 * by the lexical analyzer to be overwritten by the syntax
+	 * error.
+	 */
+	if (!cstate->error_set) {
+		va_start(ap, fmt);
+		(void)vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+		    fmt, ap);
+		va_end(ap);
+		cstate->error_set = 1;
+	}
 }
 
+/*
+ * For use *ONLY* in routines in this file.
+ */
+static void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
 /* VARARGS */
-void PCAP_NORETURN
+static void PCAP_NORETURN
 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);
+	(void)vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+	    fmt, ap);
 	va_end(ap);
 	longjmp(cstate->top_ctx, 1);
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
-static void init_linktype(compiler_state_t *, pcap_t *);
+static int init_linktype(compiler_state_t *, pcap_t *);
 
 static void init_regs(compiler_state_t *);
 static int alloc_reg(compiler_state_t *);
 static void free_reg(compiler_state_t *, int);
 
 static void initchunks(compiler_state_t *cstate);
+static void *newchunk_nolongjmp(compiler_state_t *cstate, size_t);
 static void *newchunk(compiler_state_t *cstate, size_t);
 static void freechunks(compiler_state_t *cstate);
 static inline struct block *new_block(compiler_state_t *cstate, int);
@@ -456,21 +488,21 @@
 static void backpatch(struct block *, struct block *);
 static void merge(struct block *, struct block *);
 static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32);
+    u_int, bpf_u_int32);
 static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32);
+    u_int, bpf_u_int32);
 static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32);
+    u_int, bpf_u_int32);
 static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32);
+    u_int, bpf_u_int32);
 static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32);
+    u_int, bpf_u_int32);
 static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
-    u_int, bpf_int32, bpf_u_int32);
+    u_int, bpf_u_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 block *gen_ncmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_u_int32, int, int, bpf_u_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,
@@ -479,9 +511,9 @@
 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 block *gen_ether_linktype(compiler_state_t *, bpf_u_int32);
+static struct block *gen_ipnet_linktype(compiler_state_t *, bpf_u_int32);
+static struct block *gen_linux_sll_linktype(compiler_state_t *, bpf_u_int32);
 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 *);
@@ -489,15 +521,15 @@
 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(compiler_state_t *, int);
+static bpf_u_int32 ethertype_to_ppptype(bpf_u_int32);
+static struct block *gen_linktype(compiler_state_t *, bpf_u_int32);
 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_llc_linktype(compiler_state_t *, bpf_u_int32);
 static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
-    int, int, u_int, u_int);
+    int, bpf_u_int32, u_int, u_int);
 #ifdef INET6
 static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
-    struct in6_addr *, int, int, u_int, u_int);
+    struct in6_addr *, int, bpf_u_int32, u_int, u_int);
 #endif
 static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
 static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
@@ -506,7 +538,7 @@
 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_mpls_linktype(compiler_state_t *, bpf_u_int32);
 static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
     int, int, int);
 #ifdef INET6
@@ -518,23 +550,25 @@
     struct addrinfo *, int, int);
 #endif
 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 struct block *gen_portatom(compiler_state_t *, int, bpf_u_int32);
+static struct block *gen_portrangeatom(compiler_state_t *, u_int, bpf_u_int32,
+    bpf_u_int32);
+static struct block *gen_portatom6(compiler_state_t *, int, bpf_u_int32);
+static struct block *gen_portrangeatom6(compiler_state_t *, u_int, bpf_u_int32,
+    bpf_u_int32);
+static struct block *gen_portop(compiler_state_t *, u_int, u_int, int);
+static struct block *gen_port(compiler_state_t *, u_int, int, int);
+static struct block *gen_portrangeop(compiler_state_t *, u_int, u_int,
+    bpf_u_int32, int);
+static struct block *gen_portrange(compiler_state_t *, u_int, u_int, int, int);
+struct block *gen_portop6(compiler_state_t *, u_int, u_int, int);
+static struct block *gen_port6(compiler_state_t *, u_int, int, int);
+static struct block *gen_portrangeop6(compiler_state_t *, u_int, u_int,
+    bpf_u_int32, int);
+static struct block *gen_portrange6(compiler_state_t *, u_int, u_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 block *gen_protochain(compiler_state_t *, bpf_u_int32, int);
+static struct block *gen_proto(compiler_state_t *, bpf_u_int32, 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);
@@ -543,6 +577,9 @@
 static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
 
 static struct block *gen_ppi_dlt_check(compiler_state_t *);
+static struct block *gen_atmfield_code_internal(compiler_state_t *, int,
+    bpf_u_int32, int, int);
+static struct block *gen_atmtype_llc(compiler_state_t *);
 static struct block *gen_msg_abbrev(compiler_state_t *, int type);
 
 static void
@@ -558,7 +595,7 @@
 }
 
 static void *
-newchunk(compiler_state_t *cstate, size_t n)
+newchunk_nolongjmp(compiler_state_t *cstate, size_t n)
 {
 	struct chunk *cp;
 	int k;
@@ -576,21 +613,40 @@
 	if (n > cp->n_left) {
 		++cp;
 		k = ++cstate->cur_chunk;
-		if (k >= NCHUNKS)
-			bpf_error(cstate, "out of memory");
+		if (k >= NCHUNKS) {
+			bpf_set_error(cstate, "out of memory");
+			return (NULL);
+		}
 		size = CHUNK0SIZE << k;
 		cp->m = (void *)malloc(size);
-		if (cp->m == NULL)
-			bpf_error(cstate, "out of memory");
+		if (cp->m == NULL) {
+			bpf_set_error(cstate, "out of memory");
+			return (NULL);
+		}
 		memset((char *)cp->m, 0, size);
 		cp->n_left = size;
-		if (n > size)
-			bpf_error(cstate, "out of memory");
+		if (n > size) {
+			bpf_set_error(cstate, "out of memory");
+			return (NULL);
+		}
 	}
 	cp->n_left -= n;
 	return (void *)((char *)cp->m + cp->n_left);
 }
 
+static void *
+newchunk(compiler_state_t *cstate, size_t n)
+{
+	void *p;
+
+	p = newchunk_nolongjmp(cstate, n);
+	if (p == NULL) {
+		longjmp(cstate->top_ctx, 1);
+		/*NOTREACHED*/
+	}
+	return (p);
+}
+
 static void
 freechunks(compiler_state_t *cstate)
 {
@@ -603,14 +659,19 @@
 
 /*
  * A strdup whose allocations are freed after code generation is over.
+ * This is used by the lexical analyzer, so it can't longjmp; it just
+ * returns NULL on an allocation error, and the callers must check
+ * for it.
  */
 char *
 sdup(compiler_state_t *cstate, const char *s)
 {
 	size_t n = strlen(s) + 1;
-	char *cp = newchunk(cstate, n);
+	char *cp = newchunk_nolongjmp(cstate, n);
 
-	strlcpy(cp, s, n);
+	if (cp == NULL)
+		return (NULL);
+	pcap_strlcpy(cp, s, n);
 	return (cp);
 }
 
@@ -662,7 +723,7 @@
 	compiler_state_t cstate;
 	const char * volatile xbuf = buf;
 	yyscan_t scanner = NULL;
-	YY_BUFFER_STATE in_buffer = NULL;
+	volatile YY_BUFFER_STATE in_buffer = NULL;
 	u_int len;
 	int  rc;
 
@@ -671,7 +732,7 @@
 	 * link-layer type, so we can't use it.
 	 */
 	if (!p->activated) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "not-yet-activated pcap_t passed to pcap_compile");
 		return (-1);
 	}
@@ -697,7 +758,7 @@
 	 * filter for this pcap_t; we might be running it from userland
 	 * on captured packets to do packet classification.  We really
 	 * need a better way of handling this, but this is all that
-	 * the WinPcap code did.
+	 * the WinPcap remote capture code did.
 	 */
 	if (p->save_current_filter_op != NULL)
 		(p->save_current_filter_op)(p, buf);
@@ -708,25 +769,18 @@
 #ifdef INET6
 	cstate.ai = NULL;
 #endif
+	cstate.e = NULL;
 	cstate.ic.root = NULL;
 	cstate.ic.cur_mark = 0;
 	cstate.bpf_pcap = p;
+	cstate.error_set = 0;
 	init_regs(&cstate);
 
-	if (setjmp(cstate.top_ctx)) {
-#ifdef INET6
-		if (cstate.ai != NULL)
-			freeaddrinfo(cstate.ai);
-#endif
-		rc = -1;
-		goto quit;
-	}
-
 	cstate.netmask = mask;
 
 	cstate.snaplen = pcap_snapshot(p);
 	if (cstate.snaplen == 0) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snaplen of 0 rejects all packets");
 		rc = -1;
 		goto quit;
@@ -743,19 +797,53 @@
 	 */
 	pcap_set_extra(&cstate, scanner);
 
-	init_linktype(&cstate, p);
-	(void)pcap_parse(scanner, &cstate);
+	if (init_linktype(&cstate, p) == -1) {
+		rc = -1;
+		goto quit;
+	}
+	if (pcap_parse(scanner, &cstate) != 0) {
+#ifdef INET6
+		if (cstate.ai != NULL)
+			freeaddrinfo(cstate.ai);
+#endif
+		if (cstate.e != NULL)
+			free(cstate.e);
+		rc = -1;
+		goto quit;
+	}
 
-	if (cstate.ic.root == NULL)
+	if (cstate.ic.root == NULL) {
+		/*
+		 * Catch errors reported by gen_retblk().
+		 */
+		if (setjmp(cstate.top_ctx)) {
+			rc = -1;
+			goto quit;
+		}
 		cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
+	}
 
 	if (optimize && !cstate.no_optimize) {
-		bpf_optimize(&cstate, &cstate.ic);
+		if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
+			/* Failure */
+			rc = -1;
+			goto quit;
+		}
 		if (cstate.ic.root == NULL ||
-		    (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0))
-			bpf_error(&cstate, "expression rejects all packets");
+		    (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0)) {
+			(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "expression rejects all packets");
+			rc = -1;
+			goto quit;
+		}
 	}
-	program->bf_insns = icode_to_fcode(&cstate, &cstate.ic, cstate.ic.root, &len);
+	program->bf_insns = icode_to_fcode(&cstate.ic,
+	    cstate.ic.root, &len, p->errbuf);
+	if (program->bf_insns == NULL) {
+		/* Failure */
+		rc = -1;
+		goto quit;
+	}
 	program->bf_len = len;
 
 	rc = 0;  /* We're all okay */
@@ -851,12 +939,19 @@
 	*p = b1;
 }
 
-void
+int
 finish_parse(compiler_state_t *cstate, struct block *p)
 {
 	struct block *ppi_dlt_check;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return -1
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (-1);
+
+	/*
 	 * Insert before the statements of the first (root) block any
 	 * statements needed to load the lengths of any variable-length
 	 * headers into registers.
@@ -898,6 +993,7 @@
 	p->sense = !p->sense;
 	backpatch(p, gen_retblk(cstate, 0));
 	cstate->ic.root = p->head;
+	return (0);
 }
 
 void
@@ -929,42 +1025,42 @@
 
 static struct block *
 gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v)
+    u_int size, bpf_u_int32 v)
 {
 	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
 }
 
 static struct block *
 gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v)
+    u_int size, bpf_u_int32 v)
 {
 	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
 }
 
 static struct block *
 gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v)
+    u_int size, bpf_u_int32 v)
 {
 	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
 }
 
 static struct block *
 gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v)
+    u_int size, bpf_u_int32 v)
 {
 	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
 }
 
 static struct block *
 gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v)
+    u_int size, bpf_u_int32 v)
 {
 	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
 }
 
 static struct block *
 gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
-    u_int size, bpf_int32 v, bpf_u_int32 mask)
+    u_int size, bpf_u_int32 v, bpf_u_int32 mask)
 {
 	return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
 }
@@ -978,10 +1074,9 @@
 	b = NULL;
 	while (size >= 4) {
 		register const u_char *p = &v[size - 4];
-		bpf_int32 w = ((bpf_int32)p[0] << 24) |
-		    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
 
-		tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
+		tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W,
+		    EXTRACT_BE_U_4(p));
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
@@ -989,16 +1084,16 @@
 	}
 	while (size >= 2) {
 		register const u_char *p = &v[size - 2];
-		bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
 
-		tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
+		tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H,
+		    EXTRACT_BE_U_2(p));
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
 		size -= 2;
 	}
 	if (size > 0) {
-		tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
+		tmp = gen_cmp(cstate, offrel, offset, BPF_B, v[0]);
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
@@ -1013,9 +1108,9 @@
  * should test the opposite of "jtype".
  */
 static struct block *
-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)
+gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_u_int32 mask, int jtype, int reverse,
+    bpf_u_int32 v)
 {
 	struct slist *s, *s2;
 	struct block *b;
@@ -1036,7 +1131,7 @@
 	return b;
 }
 
-static void
+static int
 init_linktype(compiler_state_t *cstate, pcap_t *p)
 {
 	cstate->pcap_fddipad = p->fddipad;
@@ -1241,6 +1336,7 @@
 		cstate->off_linkhdr.is_variable = 1;
 		/* Fall through, 802.11 doesn't have a variable link
 		 * prefix but is otherwise the same. */
+		/* FALLTHROUGH */
 
 	case DLT_IEEE802_11:
 		/*
@@ -1330,13 +1426,20 @@
 		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
-	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket */
+	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket v1 */
 		cstate->off_linktype.constant_part = 14;
 		cstate->off_linkpl.constant_part = 16;
 		cstate->off_nl = 0;
 		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
+	case DLT_LINUX_SLL2:	/* fake header for Linux cooked socket v2 */
+		cstate->off_linktype.constant_part = 0;
+		cstate->off_linkpl.constant_part = 20;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
+		break;
+
 	case DLT_LTALK:
 		/*
 		 * LocalTalk does have a 1-byte type field in the LLAP header,
@@ -1612,12 +1715,14 @@
 			cstate->off_nl = OFFSET_NOT_SET;
 			cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		} else {
-			bpf_error(cstate, "unknown data link type %d", cstate->linktype);
+			bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
+			return (-1);
 		}
 		break;
 	}
 
 	cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
+	return (0);
 }
 
 /*
@@ -1669,6 +1774,19 @@
 {
 	struct slist *s, *s2;
 
+	/*
+	 * Squelch warnings from compilers that *don't* assume that
+	 * offrel always has a valid enum value and therefore don't
+	 * assume that we'll always go through one of the case arms.
+	 *
+	 * If we have a default case, compilers that *do* assume that
+	 * will then complain about the default case code being
+	 * unreachable.
+	 *
+	 * Damned if you do, damned if you don't.
+	 */
+	s = NULL;
+
 	switch (offrel) {
 
 	case OR_PACKET:
@@ -1732,10 +1850,6 @@
 	case OR_TRAN_IPV6:
 		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
 		break;
-
-	default:
-		abort();
-		/* NOTREACHED */
 	}
 	return s;
 }
@@ -1844,11 +1958,11 @@
  * the appropriate test.
  */
 static struct block *
-gen_ether_linktype(compiler_state_t *cstate, int proto)
+gen_ether_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	struct block *b0, *b1;
 
-	switch (proto) {
+	switch (ll_proto) {
 
 	case LLCSAP_ISONS:
 	case LLCSAP_IP:
@@ -1867,8 +1981,7 @@
 		 */
 		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 		gen_not(b0);
-		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
-			     ((proto << 8) | proto));
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (ll_proto << 8) | ll_proto);
 		gen_and(b0, b1);
 		return b1;
 
@@ -1905,8 +2018,8 @@
 		 * This generates code to check both for the
 		 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
 		 */
-		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);
+		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, LLCSAP_IPX);
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, 0xFFFF);
 		gen_or(b0, b1);
 
 		/*
@@ -1936,7 +2049,7 @@
 		 * do that before checking for the other frame
 		 * types.
 		 */
-		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ETHERTYPE_IPX);
 		gen_or(b0, b1);
 		return b1;
 
@@ -1966,9 +2079,9 @@
 		 * 0x000000 (encapsulated Ethernet) and a protocol
 		 * type of ETHERTYPE_AARP (Appletalk ARP).
 		 */
-		if (proto == ETHERTYPE_ATALK)
+		if (ll_proto == ETHERTYPE_ATALK)
 			b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
-		else	/* proto == ETHERTYPE_AARP */
+		else	/* ll_proto == ETHERTYPE_AARP */
 			b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
 		gen_and(b0, b1);
 
@@ -1977,13 +2090,13 @@
 		 * phase 1?); we just check for the Ethernet
 		 * protocol type.
 		 */
-		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
 
 		gen_or(b0, b1);
 		return b1;
 
 	default:
-		if (proto <= ETHERMTU) {
+		if (ll_proto <= ETHERMTU) {
 			/*
 			 * This is an LLC SAP value, so the frames
 			 * that match would be 802.2 frames.
@@ -1994,7 +2107,7 @@
 			 */
 			b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 			gen_not(b0);
-			b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
+			b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, ll_proto);
 			gen_and(b0, b1);
 			return b1;
 		} else {
@@ -2003,18 +2116,17 @@
 			 * the length/type field with it (if
 			 * the frame is an 802.2 frame, the length
 			 * field will be <= ETHERMTU, and, as
-			 * "proto" is > ETHERMTU, this test
+			 * "ll_proto" is > ETHERMTU, this test
 			 * will fail and the frame won't match,
 			 * which is what we want).
 			 */
-			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
-			    (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
 		}
 	}
 }
 
 static struct block *
-gen_loopback_linktype(compiler_state_t *cstate, int proto)
+gen_loopback_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	/*
 	 * For DLT_NULL, the link-layer header is a 32-bit word
@@ -2042,10 +2154,10 @@
 		 * code to compare against the result.
 		 */
 		if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
-			proto = SWAPLONG(proto);
-		proto = htonl(proto);
+			ll_proto = SWAPLONG(ll_proto);
+		ll_proto = htonl(ll_proto);
 	}
-	return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
+	return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, ll_proto));
 }
 
 /*
@@ -2053,18 +2165,17 @@
  * or IPv6 then we have an error.
  */
 static struct block *
-gen_ipnet_linktype(compiler_state_t *cstate, int proto)
+gen_ipnet_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
-	switch (proto) {
+	switch (ll_proto) {
 
 	case ETHERTYPE_IP:
-		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
-		/* NOTREACHED */
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, IPH_AF_INET);
+		/*NOTREACHED*/
 
 	case ETHERTYPE_IPV6:
-		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-		    (bpf_int32)IPH_AF_INET6);
-		/* NOTREACHED */
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, IPH_AF_INET6);
+		/*NOTREACHED*/
 
 	default:
 		break;
@@ -2076,17 +2187,17 @@
 /*
  * Generate code to match a particular packet type.
  *
- * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * "ll_proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
  * value, if <= ETHERMTU.  We use that to determine whether to
  * match the type field or to check the type field for the special
  * LINUX_SLL_P_802_2 value and then do the appropriate test.
  */
 static struct block *
-gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
+gen_linux_sll_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	struct block *b0, *b1;
 
-	switch (proto) {
+	switch (ll_proto) {
 
 	case LLCSAP_ISONS:
 	case LLCSAP_IP:
@@ -2104,8 +2215,7 @@
 		 * (i.e., other SAP values)?
 		 */
 		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));
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (ll_proto << 8) | ll_proto);
 		gen_and(b0, b1);
 		return b1;
 
@@ -2135,7 +2245,7 @@
 		 * then put a check for LINUX_SLL_P_802_2 frames
 		 * before it.
 		 */
-		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, LLCSAP_IPX);
 		b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
 		gen_or(b0, b1);
 		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
@@ -2153,7 +2263,7 @@
 		 * do that before checking for the other frame
 		 * types.
 		 */
-		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ETHERTYPE_IPX);
 		gen_or(b0, b1);
 		return b1;
 
@@ -2182,9 +2292,9 @@
 		 * 0x000000 (encapsulated Ethernet) and a protocol
 		 * type of ETHERTYPE_AARP (Appletalk ARP).
 		 */
-		if (proto == ETHERTYPE_ATALK)
+		if (ll_proto == ETHERTYPE_ATALK)
 			b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
-		else	/* proto == ETHERTYPE_AARP */
+		else	/* ll_proto == ETHERTYPE_AARP */
 			b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
 		gen_and(b0, b1);
 
@@ -2193,13 +2303,13 @@
 		 * phase 1?); we just check for the Ethernet
 		 * protocol type.
 		 */
-		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
 
 		gen_or(b0, b1);
 		return b1;
 
 	default:
-		if (proto <= ETHERMTU) {
+		if (ll_proto <= ETHERMTU) {
 			/*
 			 * This is an LLC SAP value, so the frames
 			 * that match would be 802.2 frames.
@@ -2209,7 +2319,7 @@
 			 */
 			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);
+			     ll_proto);
 			gen_and(b0, b1);
 			return b1;
 		} else {
@@ -2218,11 +2328,11 @@
 			 * the length/type field with it (if
 			 * the frame is an 802.2 frame, the length
 			 * field will be <= ETHERMTU, and, as
-			 * "proto" is > ETHERMTU, this test
+			 * "ll_proto" is > ETHERMTU, this test
 			 * will fail and the frame won't match,
 			 * which is what we want).
 			 */
-			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
 		}
 	}
 }
@@ -2736,7 +2846,7 @@
 		s2->s.k = 3;
 		sappend(s, s2);
 		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
-		s2->s.k = ~3;
+		s2->s.k = (bpf_u_int32)~3;
 		sappend(s, s2);
 		s2 = new_stmt(cstate, BPF_ST);
 		s2->s.k = cstate->off_linkpl.reg;
@@ -2817,7 +2927,7 @@
 	}
 
 	/*
-	 * If there there is no initialization yet and we need variable
+	 * If there is no initialization yet and we need variable
 	 * length offsets for VLAN, initialize them to zero
 	 */
 	if (s == NULL && cstate->is_vlan_vloffset) {
@@ -2923,33 +3033,33 @@
 /*
  * Map an Ethernet type to the equivalent PPP type.
  */
-static int
-ethertype_to_ppptype(int proto)
+static bpf_u_int32
+ethertype_to_ppptype(bpf_u_int32 ll_proto)
 {
-	switch (proto) {
+	switch (ll_proto) {
 
 	case ETHERTYPE_IP:
-		proto = PPP_IP;
+		ll_proto = PPP_IP;
 		break;
 
 	case ETHERTYPE_IPV6:
-		proto = PPP_IPV6;
+		ll_proto = PPP_IPV6;
 		break;
 
 	case ETHERTYPE_DN:
-		proto = PPP_DECNET;
+		ll_proto = PPP_DECNET;
 		break;
 
 	case ETHERTYPE_ATALK:
-		proto = PPP_APPLE;
+		ll_proto = PPP_APPLE;
 		break;
 
 	case ETHERTYPE_NS:
-		proto = PPP_NS;
+		ll_proto = PPP_NS;
 		break;
 
 	case LLCSAP_ISONS:
-		proto = PPP_OSI;
+		ll_proto = PPP_OSI;
 		break;
 
 	case LLCSAP_8021D:
@@ -2958,14 +3068,14 @@
 		 * over PPP are Spanning Tree Protocol
 		 * Bridging PDUs.
 		 */
-		proto = PPP_BRPDU;
+		ll_proto = PPP_BRPDU;
 		break;
 
 	case LLCSAP_IPX:
-		proto = PPP_IPX;
+		ll_proto = PPP_IPX;
 		break;
 	}
-	return (proto);
+	return (ll_proto);
 }
 
 /*
@@ -3021,29 +3131,14 @@
  * value, if <= ETHERMTU.
  */
 static struct block *
-gen_linktype(compiler_state_t *cstate, int proto)
+gen_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	struct block *b0, *b1, *b2;
 	const char *description;
 
 	/* are we checking MPLS-encapsulated packets? */
-	if (cstate->label_stack_depth > 0) {
-		switch (proto) {
-		case ETHERTYPE_IP:
-		case PPP_IP:
-			/* FIXME add other L3 proto IDs */
-			return gen_mpls_linktype(cstate, Q_IP);
-
-		case ETHERTYPE_IPV6:
-		case PPP_IPV6:
-			/* FIXME add other L3 proto IDs */
-			return gen_mpls_linktype(cstate, Q_IPV6);
-
-		default:
-			bpf_error(cstate, "unsupported protocol over mpls");
-			/* NOTREACHED */
-		}
-	}
+	if (cstate->label_stack_depth > 0)
+		return gen_mpls_linktype(cstate, ll_proto);
 
 	switch (cstate->linktype) {
 
@@ -3057,26 +3152,23 @@
 		else
 			b0 = NULL;
 
-		b1 = gen_ether_linktype(cstate, proto);
+		b1 = gen_ether_linktype(cstate, ll_proto);
 		if (b0 != NULL)
 			gen_and(b0, b1);
 		return b1;
 		/*NOTREACHED*/
-		break;
 
 	case DLT_C_HDLC:
-		switch (proto) {
+		switch (ll_proto) {
 
 		case LLCSAP_ISONS:
-			proto = (proto << 8 | LLCSAP_ISONS);
+			ll_proto = (ll_proto << 8 | LLCSAP_ISONS);
 			/* fall through */
 
 		default:
-			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
 			/*NOTREACHED*/
-			break;
 		}
-		break;
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
@@ -3091,34 +3183,30 @@
 		/*
 		 * Now check for the specified link-layer type.
 		 */
-		b1 = gen_llc_linktype(cstate, proto);
+		b1 = gen_llc_linktype(cstate, ll_proto);
 		gen_and(b0, b1);
 		return b1;
 		/*NOTREACHED*/
-		break;
 
 	case DLT_FDDI:
 		/*
 		 * XXX - check for LLC frames.
 		 */
-		return gen_llc_linktype(cstate, proto);
+		return gen_llc_linktype(cstate, ll_proto);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_IEEE802:
 		/*
 		 * XXX - check for LLC PDUs, as per IEEE 802.5.
 		 */
-		return gen_llc_linktype(cstate, proto);
+		return gen_llc_linktype(cstate, ll_proto);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_ATM_RFC1483:
 	case DLT_ATM_CLIP:
 	case DLT_IP_OVER_FC:
-		return gen_llc_linktype(cstate, proto);
+		return gen_llc_linktype(cstate, ll_proto);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_SUNATM:
 		/*
@@ -3128,17 +3216,15 @@
 		 *
 		 * Check for LLC encapsulation and then check the protocol.
 		 */
-		b0 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
-		b1 = gen_llc_linktype(cstate, proto);
+		b0 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+		b1 = gen_llc_linktype(cstate, ll_proto);
 		gen_and(b0, b1);
 		return b1;
 		/*NOTREACHED*/
-		break;
 
 	case DLT_LINUX_SLL:
-		return gen_linux_sll_linktype(cstate, proto);
+		return gen_linux_sll_linktype(cstate, ll_proto);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_SLIP:
 	case DLT_SLIP_BSDOS:
@@ -3150,7 +3236,7 @@
 		 * XXX - for IPv4, check for a version number of 4, and,
 		 * for IPv6, check for a version number of 6?
 		 */
-		switch (proto) {
+		switch (ll_proto) {
 
 		case ETHERTYPE_IP:
 			/* Check for a version number of 4. */
@@ -3164,31 +3250,28 @@
 			return gen_false(cstate);	/* always false */
 		}
 		/*NOTREACHED*/
-		break;
 
 	case DLT_IPV4:
 		/*
 		 * Raw IPv4, so no type field.
 		 */
-		if (proto == ETHERTYPE_IP)
+		if (ll_proto == ETHERTYPE_IP)
 			return gen_true(cstate);	/* always true */
 
 		/* Checking for something other than IPv4; always false */
 		return gen_false(cstate);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_IPV6:
 		/*
 		 * Raw IPv6, so no type field.
 		 */
-		if (proto == ETHERTYPE_IPV6)
+		if (ll_proto == ETHERTYPE_IPV6)
 			return gen_true(cstate);	/* always true */
 
 		/* Checking for something other than IPv6; always false */
 		return gen_false(cstate);
 		/*NOTREACHED*/
-		break;
 
 	case DLT_PPP:
 	case DLT_PPP_PPPD:
@@ -3198,17 +3281,16 @@
 		 * We use Ethernet protocol types inside libpcap;
 		 * map them to the corresponding PPP protocol types.
 		 */
-		proto = ethertype_to_ppptype(proto);
-		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
+		    ethertype_to_ppptype(ll_proto));
 		/*NOTREACHED*/
-		break;
 
 	case DLT_PPP_BSDOS:
 		/*
 		 * We use Ethernet protocol types inside libpcap;
 		 * map them to the corresponding PPP protocol types.
 		 */
-		switch (proto) {
+		switch (ll_proto) {
 
 		case ETHERTYPE_IP:
 			/*
@@ -3223,17 +3305,15 @@
 			return b0;
 
 		default:
-			proto = ethertype_to_ppptype(proto);
 			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
-				(bpf_int32)proto);
+			    ethertype_to_ppptype(ll_proto));
 		}
 		/*NOTREACHED*/
-		break;
 
 	case DLT_NULL:
 	case DLT_LOOP:
 	case DLT_ENC:
-		switch (proto) {
+		switch (ll_proto) {
 
 		case ETHERTYPE_IP:
 			return (gen_loopback_linktype(cstate, AF_INET));
@@ -3314,16 +3394,15 @@
 		 * af field is host byte order in contrast to the rest of
 		 * the packet.
 		 */
-		if (proto == ETHERTYPE_IP)
+		if (ll_proto == ETHERTYPE_IP)
 			return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
-			    BPF_B, (bpf_int32)AF_INET));
-		else if (proto == ETHERTYPE_IPV6)
+			    BPF_B, AF_INET));
+		else if (ll_proto == ETHERTYPE_IPV6)
 			return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
-			    BPF_B, (bpf_int32)AF_INET6));
+			    BPF_B, AF_INET6));
 		else
 			return gen_false(cstate);
 		/*NOTREACHED*/
-		break;
 #endif /* HAVE_NET_PFVAR_H */
 
 	case DLT_ARCNET:
@@ -3332,58 +3411,56 @@
 		 * XXX should we check for first fragment if the protocol
 		 * uses PHDS?
 		 */
-		switch (proto) {
+		switch (ll_proto) {
 
 		default:
 			return gen_false(cstate);
 
 		case ETHERTYPE_IPV6:
 			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-				(bpf_int32)ARCTYPE_INET6));
+				ARCTYPE_INET6));
 
 		case ETHERTYPE_IP:
 			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-				     (bpf_int32)ARCTYPE_IP);
+			    ARCTYPE_IP);
 			b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-				     (bpf_int32)ARCTYPE_IP_OLD);
+			    ARCTYPE_IP_OLD);
 			gen_or(b0, b1);
 			return (b1);
 
 		case ETHERTYPE_ARP:
 			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-				     (bpf_int32)ARCTYPE_ARP);
+			    ARCTYPE_ARP);
 			b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-				     (bpf_int32)ARCTYPE_ARP_OLD);
+			    ARCTYPE_ARP_OLD);
 			gen_or(b0, b1);
 			return (b1);
 
 		case ETHERTYPE_REVARP:
 			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-					(bpf_int32)ARCTYPE_REVARP));
+			    ARCTYPE_REVARP));
 
 		case ETHERTYPE_ATALK:
 			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
-					(bpf_int32)ARCTYPE_ATALK));
+			    ARCTYPE_ATALK));
 		}
 		/*NOTREACHED*/
-		break;
 
 	case DLT_LTALK:
-		switch (proto) {
+		switch (ll_proto) {
 		case ETHERTYPE_ATALK:
 			return gen_true(cstate);
 		default:
 			return gen_false(cstate);
 		}
 		/*NOTREACHED*/
-		break;
 
 	case DLT_FRELAY:
 		/*
 		 * XXX - assumes a 2-byte Frame Relay header with
 		 * DLCI and flags.  What if the address is longer?
 		 */
-		switch (proto) {
+		switch (ll_proto) {
 
 		case ETHERTYPE_IP:
 			/*
@@ -3420,7 +3497,6 @@
 			return gen_false(cstate);
 		}
 		/*NOTREACHED*/
-		break;
 
 	case DLT_MFR:
 		bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
@@ -3461,7 +3537,7 @@
 		return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
 
 	case DLT_IPNET:
-		return gen_ipnet_linktype(cstate, proto);
+		return gen_ipnet_linktype(cstate, ll_proto);
 
 	case DLT_LINUX_IRDA:
 		bpf_error(cstate, "IrDA link-layer type filtering not implemented");
@@ -3500,6 +3576,7 @@
 	case DLT_IEEE802_15_4_LINUX:
 	case DLT_IEEE802_15_4_NONASK_PHY:
 	case DLT_IEEE802_15_4_NOFCS:
+	case DLT_IEEE802_15_4_TAP:
 		bpf_error(cstate, "IEEE 802.15.4 link-layer type filtering not implemented");
 
 	case DLT_IEEE802_16_MAC_CPS_RADIO:
@@ -3511,7 +3588,8 @@
 	case DLT_RAIF1:
 		bpf_error(cstate, "RAIF1 link-layer type filtering not implemented");
 
-	case DLT_IPMB:
+	case DLT_IPMB_KONTRON:
+	case DLT_IPMB_LINUX:
 		bpf_error(cstate, "IPMB link-layer type filtering not implemented");
 
 	case DLT_AX25_KISS:
@@ -3537,21 +3615,17 @@
 			 * it's not, it needs to be handled specially
 			 * above.)
 			 */
-			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, ll_proto);
+			/*NOTREACHED */
 		} else {
 			/*
 			 * No; report an error.
 			 */
-			description = pcap_datalink_val_to_description(cstate->linktype);
-			if (description != NULL) {
-				bpf_error(cstate, "%s link-layer type filtering not implemented",
-				    description);
-			} else {
-				bpf_error(cstate, "DLT %u link-layer type filtering not implemented",
-				    cstate->linktype);
-			}
+			description = pcap_datalink_val_to_description_or_dlt(cstate->linktype);
+			bpf_error(cstate, "%s link-layer type filtering not implemented",
+			    description);
+			/*NOTREACHED */
 		}
-		break;
 	}
 }
 
@@ -3581,8 +3655,8 @@
 /*
  * Generate code to match frames with an LLC header.
  */
-struct block *
-gen_llc(compiler_state_t *cstate)
+static struct block *
+gen_llc_internal(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 
@@ -3600,7 +3674,7 @@
 		 * Now check for the purported DSAP and SSAP not being
 		 * 0xFF, to rule out NetWare-over-802.3.
 		 */
-		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, 0xFFFF);
 		gen_not(b1);
 		gen_and(b0, b1);
 		return b1;
@@ -3609,7 +3683,7 @@
 		/*
 		 * We check for LLC traffic.
 		 */
-		b0 = gen_atmtype_abbrev(cstate, A_LLC);
+		b0 = gen_atmtype_llc(cstate);
 		return b0;
 
 	case DLT_IEEE802:	/* Token Ring */
@@ -3647,21 +3721,42 @@
 		return b0;
 
 	default:
-		bpf_error(cstate, "'llc' not supported for linktype %d", cstate->linktype);
-		/* NOTREACHED */
+		bpf_error(cstate, "'llc' not supported for %s",
+			  pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+		/*NOTREACHED*/
 	}
 }
 
 struct block *
+gen_llc(compiler_state_t *cstate)
+{
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_llc_internal(cstate);
+}
+
+struct block *
 gen_llc_i(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 	struct slist *s;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc(cstate);
+	b0 = gen_llc_internal(cstate);
 
 	/*
 	 * Load the control byte and test the low-order bit; it must
@@ -3682,9 +3777,16 @@
 	struct block *b0, *b1;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc(cstate);
+	b0 = gen_llc_internal(cstate);
 
 	/*
 	 * Now compare the low-order 2 bit of the control byte against
@@ -3701,9 +3803,16 @@
 	struct block *b0, *b1;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc(cstate);
+	b0 = gen_llc_internal(cstate);
 
 	/*
 	 * Now compare the low-order 2 bit of the control byte against
@@ -3720,9 +3829,16 @@
 	struct block *b0, *b1;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc(cstate);
+	b0 = gen_llc_internal(cstate);
 
 	/*
 	 * Now check for an S frame with the appropriate type.
@@ -3738,9 +3854,16 @@
 	struct block *b0, *b1;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc(cstate);
+	b0 = gen_llc_internal(cstate);
 
 	/*
 	 * Now check for a U frame with the appropriate type.
@@ -3763,12 +3886,12 @@
  * protocol ID in a SNAP header.
  */
 static struct block *
-gen_llc_linktype(compiler_state_t *cstate, int proto)
+gen_llc_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	/*
 	 * XXX - handle token-ring variable-length header.
 	 */
-	switch (proto) {
+	switch (ll_proto) {
 
 	case LLCSAP_IP:
 	case LLCSAP_ISONS:
@@ -3779,15 +3902,14 @@
 		 * DSAP, as we do for other SAP values?
 		 */
 		return gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_u_int32)
-			     ((proto << 8) | proto));
+			     ((ll_proto << 8) | ll_proto));
 
 	case LLCSAP_IPX:
 		/*
 		 * XXX - are there ever SNAP frames for IPX on
 		 * non-Ethernet 802.x networks?
 		 */
-		return gen_cmp(cstate, OR_LLC, 0, BPF_B,
-		    (bpf_int32)LLCSAP_IPX);
+		return gen_cmp(cstate, OR_LLC, 0, BPF_B, LLCSAP_IPX);
 
 	case ETHERTYPE_ATALK:
 		/*
@@ -3806,12 +3928,12 @@
 		 * XXX - we don't have to check for IPX 802.3
 		 * here, but should we check for the IPX Ethertype?
 		 */
-		if (proto <= ETHERMTU) {
+		if (ll_proto <= ETHERMTU) {
 			/*
 			 * This is an LLC SAP value, so check
 			 * the DSAP.
 			 */
-			return gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LLC, 0, BPF_B, ll_proto);
 		} else {
 			/*
 			 * This is an Ethernet type; we assume that it's
@@ -3826,20 +3948,20 @@
 			 * organization code of 0x000000 (encapsulated
 			 * Ethernet), we'd do
 			 *
-			 *	return gen_snap(cstate, 0x000000, proto);
+			 *	return gen_snap(cstate, 0x000000, ll_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(cstate, OR_LLC, 6, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LLC, 6, BPF_H, ll_proto);
 		}
 	}
 }
 
 static struct block *
 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)
+    int dir, bpf_u_int32 ll_proto, u_int src_off, u_int dst_off)
 {
 	struct block *b0, *b1;
 	u_int offset;
@@ -3855,47 +3977,48 @@
 		break;
 
 	case Q_AND:
-		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);
+		b0 = gen_hostop(cstate, addr, mask, Q_SRC, ll_proto, src_off, dst_off);
+		b1 = gen_hostop(cstate, addr, mask, Q_DST, ll_proto, src_off, dst_off);
 		gen_and(b0, b1);
 		return b1;
 
-	case Q_OR:
 	case Q_DEFAULT:
-		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);
+	case Q_OR:
+		b0 = gen_hostop(cstate, addr, mask, Q_SRC, ll_proto, src_off, dst_off);
+		b1 = gen_hostop(cstate, addr, mask, Q_DST, ll_proto, src_off, dst_off);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	default:
 		abort();
+		/*NOTREACHED*/
 	}
-	b0 = gen_linktype(cstate, proto);
-	b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
+	b0 = gen_linktype(cstate, ll_proto);
+	b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, addr, mask);
 	gen_and(b0, b1);
 	return b1;
 }
@@ -3903,7 +4026,8 @@
 #ifdef INET6
 static struct block *
 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 in6_addr *mask, int dir, bpf_u_int32 ll_proto, u_int src_off,
+    u_int dst_off)
 {
 	struct block *b0, *b1;
 	u_int offset;
@@ -3920,44 +4044,45 @@
 		break;
 
 	case Q_AND:
-		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);
+		b0 = gen_hostop6(cstate, addr, mask, Q_SRC, ll_proto, src_off, dst_off);
+		b1 = gen_hostop6(cstate, addr, mask, Q_DST, ll_proto, src_off, dst_off);
 		gen_and(b0, b1);
 		return b1;
 
-	case Q_OR:
 	case Q_DEFAULT:
-		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);
+	case Q_OR:
+		b0 = gen_hostop6(cstate, addr, mask, Q_SRC, ll_proto, src_off, dst_off);
+		b1 = gen_hostop6(cstate, addr, mask, Q_DST, ll_proto, src_off, dst_off);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
-		break;
+		/*NOTREACHED*/
 
 	default:
 		abort();
+		/*NOTREACHED*/
 	}
 	/* this order is important */
 	a = (uint32_t *)addr;
@@ -3969,7 +4094,7 @@
 	gen_and(b0, b1);
 	b0 = gen_mcmp(cstate, OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
 	gen_and(b0, b1);
-	b0 = gen_linktype(cstate, proto);
+	b0 = gen_linktype(cstate, ll_proto);
 	gen_and(b0, b1);
 	return b1;
 }
@@ -4002,30 +4127,30 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
-		break;
+		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -4058,30 +4183,30 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -4114,30 +4239,30 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -4426,6 +4551,68 @@
 		gen_and(b1, b0);
 		return b0;
 
+	case Q_AND:
+		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+		gen_and(b0, b1);
+		return b1;
+
+	case Q_DEFAULT:
+	case Q_OR:
+		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+		gen_or(b0, b1);
+		return b1;
+
+	/*
+	 * XXX - add BSSID keyword?
+	 */
+	case Q_ADDR1:
+		return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
+
+	case Q_ADDR2:
+		/*
+		 * Not present in CTS or ACK control frames.
+		 */
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+			IEEE80211_FC0_TYPE_MASK);
+		gen_not(b0);
+		b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+			IEEE80211_FC0_SUBTYPE_MASK);
+		gen_not(b1);
+		b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+			IEEE80211_FC0_SUBTYPE_MASK);
+		gen_not(b2);
+		gen_and(b1, b2);
+		gen_or(b0, b2);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+		gen_and(b2, b1);
+		return b1;
+
+	case Q_ADDR3:
+		/*
+		 * Not present in control frames.
+		 */
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+			IEEE80211_FC0_TYPE_MASK);
+		gen_not(b0);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+		gen_and(b0, b1);
+		return b1;
+
+	case Q_ADDR4:
+		/*
+		 * Present only if the direction mask has both "From DS"
+		 * and "To DS" set.  Neither control frames nor management
+		 * frames should have both of those set, so we don't
+		 * check the frame type.
+		 */
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
+			IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+		gen_and(b0, b1);
+		return b1;
+
 	case Q_RA:
 		/*
 		 * Not present in management frames; addr1 in other
@@ -4496,71 +4683,9 @@
 		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 		gen_and(b2, b1);
 		return b1;
-
-	/*
-	 * XXX - add BSSID keyword?
-	 */
-	case Q_ADDR1:
-		return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
-
-	case Q_ADDR2:
-		/*
-		 * Not present in CTS or ACK control frames.
-		 */
-		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
-			IEEE80211_FC0_TYPE_MASK);
-		gen_not(b0);
-		b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
-			IEEE80211_FC0_SUBTYPE_MASK);
-		gen_not(b1);
-		b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
-			IEEE80211_FC0_SUBTYPE_MASK);
-		gen_not(b2);
-		gen_and(b1, b2);
-		gen_or(b0, b2);
-		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
-		gen_and(b2, b1);
-		return b1;
-
-	case Q_ADDR3:
-		/*
-		 * Not present in control frames.
-		 */
-		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
-			IEEE80211_FC0_TYPE_MASK);
-		gen_not(b0);
-		b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
-		gen_and(b0, b1);
-		return b1;
-
-	case Q_ADDR4:
-		/*
-		 * Present only if the direction mask has both "From DS"
-		 * and "To DS" set.  Neither control frames nor management
-		 * frames should have both of those set, so we don't
-		 * check the frame type.
-		 */
-		b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
-			IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
-		b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
-		gen_and(b0, b1);
-		return b1;
-
-	case Q_AND:
-		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
-		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
-		gen_and(b0, b1);
-		return b1;
-
-	case Q_DEFAULT:
-	case Q_OR:
-		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
-		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
-		gen_or(b0, b1);
-		return b1;
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -4595,30 +4720,30 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11");
-		break;
+		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -4665,41 +4790,68 @@
 		gen_and(b0, b1);
 		return b1;
 
-	case Q_OR:
 	case Q_DEFAULT:
+	case Q_OR:
 		/* Inefficient because we do our Calvinball dance twice */
 		b0 = gen_dnhostop(cstate, addr, Q_SRC);
 		b1 = gen_dnhostop(cstate, addr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
-	case Q_ISO:
-		bpf_error(cstate, "ISO host filtering not implemented");
+	case Q_ADDR1:
+		bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
+
+	case Q_ADDR2:
+		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
+
+	case Q_ADDR3:
+		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
+
+	case Q_ADDR4:
+		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
+
+	case Q_RA:
+		bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
+
+	case Q_TA:
+		bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		/*NOTREACHED*/
 
 	default:
 		abort();
+		/*NOTREACHED*/
 	}
 	b0 = gen_linktype(cstate, ETHERTYPE_DN);
 	/* Check for pad = 1, long header case */
 	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
-	    (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
+	    (bpf_u_int32)ntohs(0x0681), (bpf_u_int32)ntohs(0x07FF));
 	b1 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_lh,
-	    BPF_H, (bpf_int32)ntohs((u_short)addr));
+	    BPF_H, (bpf_u_int32)ntohs((u_short)addr));
 	gen_and(tmp, b1);
 	/* Check for pad = 0, long header case */
-	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));
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_u_int32)0x06,
+	    (bpf_u_int32)0x7);
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_lh, BPF_H,
+	    (bpf_u_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 	/* Check for pad = 1, short header case */
 	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
-	    (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
-	b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+	    (bpf_u_int32)ntohs(0x0281), (bpf_u_int32)ntohs(0x07FF));
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H,
+	    (bpf_u_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 	/* Check for pad = 0, short header case */
-	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));
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_u_int32)0x02,
+	    (bpf_u_int32)0x7);
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_sh, BPF_H,
+	    (bpf_u_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 
@@ -4714,13 +4866,13 @@
  * field in the IP header.
  */
 static struct block *
-gen_mpls_linktype(compiler_state_t *cstate, int proto)
+gen_mpls_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
 {
 	struct block *b0, *b1;
 
-        switch (proto) {
+        switch (ll_proto) {
 
-        case Q_IP:
+        case ETHERTYPE_IP:
                 /* match the bottom-of-stack bit */
                 b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
                 /* match the IPv4 version number */
@@ -4728,7 +4880,7 @@
                 gen_and(b0, b1);
                 return b1;
 
-       case Q_IPV6:
+        case ETHERTYPE_IPV6:
                 /* match the bottom-of-stack bit */
                 b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
                 /* match the IPv4 version number */
@@ -4736,8 +4888,10 @@
                 gen_and(b0, b1);
                 return b1;
 
-       default:
-                abort();
+        default:
+               /* FIXME add other L3 proto IDs */
+               bpf_error(cstate, "unsupported protocol over mpls");
+               /*NOTREACHED*/
         }
 }
 
@@ -4769,6 +4923,9 @@
 		}
 		return b0;
 
+	case Q_LINK:
+		bpf_error(cstate, "link-layer modifier applied to %s", typestr);
+
 	case Q_IP:
 		return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
 
@@ -4778,12 +4935,12 @@
 	case Q_ARP:
 		return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
 
-	case Q_TCP:
-		bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
-
 	case Q_SCTP:
 		bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
 
+	case Q_TCP:
+		bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
+
 	case Q_UDP:
 		bpf_error(cstate, "'udp' modifier applied to %s", typestr);
 
@@ -4796,36 +4953,24 @@
 	case Q_IGRP:
 		bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
 
-	case Q_PIM:
-		bpf_error(cstate, "'pim' modifier applied to %s", typestr);
-
-	case Q_VRRP:
-		bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
-
-	case Q_CARP:
-		bpf_error(cstate, "'carp' modifier applied to %s", typestr);
-
 	case Q_ATALK:
-		bpf_error(cstate, "ATALK host filtering not implemented");
-
-	case Q_AARP:
-		bpf_error(cstate, "AARP host filtering not implemented");
+		bpf_error(cstate, "AppleTalk host filtering not implemented");
 
 	case Q_DECNET:
 		return gen_dnhostop(cstate, addr, dir);
 
-	case Q_SCA:
-		bpf_error(cstate, "SCA host filtering not implemented");
-
 	case Q_LAT:
 		bpf_error(cstate, "LAT host filtering not implemented");
 
-	case Q_MOPDL:
-		bpf_error(cstate, "MOPDL host filtering not implemented");
+	case Q_SCA:
+		bpf_error(cstate, "SCA host filtering not implemented");
 
 	case Q_MOPRC:
 		bpf_error(cstate, "MOPRC host filtering not implemented");
 
+	case Q_MOPDL:
+		bpf_error(cstate, "MOPDL host filtering not implemented");
+
 	case Q_IPV6:
 		bpf_error(cstate, "'ip6' modifier applied to ip host");
 
@@ -4838,6 +4983,15 @@
 	case Q_ESP:
 		bpf_error(cstate, "'esp' modifier applied to %s", typestr);
 
+	case Q_PIM:
+		bpf_error(cstate, "'pim' modifier applied to %s", typestr);
+
+	case Q_VRRP:
+		bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
+
+	case Q_AARP:
+		bpf_error(cstate, "AARP host filtering not implemented");
+
 	case Q_ISO:
 		bpf_error(cstate, "ISO host filtering not implemented");
 
@@ -4859,13 +5013,37 @@
 	case Q_NETBEUI:
 		bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
 
+	case Q_ISIS_L1:
+		bpf_error(cstate, "'l1' modifier applied to %s", typestr);
+
+	case Q_ISIS_L2:
+		bpf_error(cstate, "'l2' modifier applied to %s", typestr);
+
+	case Q_ISIS_IIH:
+		bpf_error(cstate, "'iih' modifier applied to %s", typestr);
+
+	case Q_ISIS_SNP:
+		bpf_error(cstate, "'snp' modifier applied to %s", typestr);
+
+	case Q_ISIS_CSNP:
+		bpf_error(cstate, "'csnp' modifier applied to %s", typestr);
+
+	case Q_ISIS_PSNP:
+		bpf_error(cstate, "'psnp' modifier applied to %s", typestr);
+
+	case Q_ISIS_LSP:
+		bpf_error(cstate, "'lsp' modifier applied to %s", typestr);
+
 	case Q_RADIO:
 		bpf_error(cstate, "'radio' modifier applied to %s", typestr);
 
+	case Q_CARP:
+		bpf_error(cstate, "'carp' modifier applied to %s", typestr);
+
 	default:
 		abort();
 	}
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 #ifdef INET6
@@ -4898,93 +5076,114 @@
 		bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
 
 	case Q_SCTP:
-		bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'sctp' modifier applied to ip6 %s", typestr);
 
 	case Q_TCP:
-		bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'tcp' modifier applied to ip6 %s", typestr);
 
 	case Q_UDP:
-		bpf_error(cstate, "'udp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'udp' modifier applied to ip6 %s", typestr);
 
 	case Q_ICMP:
-		bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp' modifier applied to ip6 %s", typestr);
 
 	case Q_IGMP:
-		bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igmp' modifier applied to ip6 %s", typestr);
 
 	case Q_IGRP:
-		bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
-
-	case Q_PIM:
-		bpf_error(cstate, "'pim' modifier applied to %s", typestr);
-
-	case Q_VRRP:
-		bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
-
-	case Q_CARP:
-		bpf_error(cstate, "'carp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igrp' modifier applied to ip6 %s", typestr);
 
 	case Q_ATALK:
-		bpf_error(cstate, "ATALK host filtering not implemented");
-
-	case Q_AARP:
-		bpf_error(cstate, "AARP host filtering not implemented");
+		bpf_error(cstate, "AppleTalk modifier applied to ip6 %s", typestr);
 
 	case Q_DECNET:
 		bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
 
-	case Q_SCA:
-		bpf_error(cstate, "SCA host filtering not implemented");
-
 	case Q_LAT:
-		bpf_error(cstate, "LAT host filtering not implemented");
+		bpf_error(cstate, "'lat' modifier applied to ip6 %s", typestr);
 
-	case Q_MOPDL:
-		bpf_error(cstate, "MOPDL host filtering not implemented");
+	case Q_SCA:
+		bpf_error(cstate, "'sca' modifier applied to ip6 %s", typestr);
 
 	case Q_MOPRC:
-		bpf_error(cstate, "MOPRC host filtering not implemented");
+		bpf_error(cstate, "'moprc' modifier applied to ip6 %s", typestr);
+
+	case Q_MOPDL:
+		bpf_error(cstate, "'mopdl' modifier applied to ip6 %s", typestr);
 
 	case Q_IPV6:
 		return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
 
 	case Q_ICMPV6:
-		bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp6' modifier applied to ip6 %s", typestr);
 
 	case Q_AH:
-		bpf_error(cstate, "'ah' modifier applied to %s", typestr);
+		bpf_error(cstate, "'ah' modifier applied to ip6 %s", typestr);
 
 	case Q_ESP:
-		bpf_error(cstate, "'esp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esp' modifier applied to ip6 %s", typestr);
+
+	case Q_PIM:
+		bpf_error(cstate, "'pim' modifier applied to ip6 %s", typestr);
+
+	case Q_VRRP:
+		bpf_error(cstate, "'vrrp' modifier applied to ip6 %s", typestr);
+
+	case Q_AARP:
+		bpf_error(cstate, "'aarp' modifier applied to ip6 %s", typestr);
 
 	case Q_ISO:
-		bpf_error(cstate, "ISO host filtering not implemented");
+		bpf_error(cstate, "'iso' modifier applied to ip6 %s", typestr);
 
 	case Q_ESIS:
-		bpf_error(cstate, "'esis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esis' modifier applied to ip6 %s", typestr);
 
 	case Q_ISIS:
-		bpf_error(cstate, "'isis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'isis' modifier applied to ip6 %s", typestr);
 
 	case Q_CLNP:
-		bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'clnp' modifier applied to ip6 %s", typestr);
 
 	case Q_STP:
-		bpf_error(cstate, "'stp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'stp' modifier applied to ip6 %s", typestr);
 
 	case Q_IPX:
-		bpf_error(cstate, "IPX host filtering not implemented");
+		bpf_error(cstate, "'ipx' modifier applied to ip6 %s", typestr);
 
 	case Q_NETBEUI:
-		bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
+		bpf_error(cstate, "'netbeui' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_L1:
+		bpf_error(cstate, "'l1' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_L2:
+		bpf_error(cstate, "'l2' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_IIH:
+		bpf_error(cstate, "'iih' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_SNP:
+		bpf_error(cstate, "'snp' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_CSNP:
+		bpf_error(cstate, "'csnp' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_PSNP:
+		bpf_error(cstate, "'psnp' modifier applied to ip6 %s", typestr);
+
+	case Q_ISIS_LSP:
+		bpf_error(cstate, "'lsp' modifier applied to ip6 %s", typestr);
 
 	case Q_RADIO:
-		bpf_error(cstate, "'radio' modifier applied to %s", typestr);
+		bpf_error(cstate, "'radio' modifier applied to ip6 %s", typestr);
+
+	case Q_CARP:
+		bpf_error(cstate, "'carp' modifier applied to ip6 %s", typestr);
 
 	default:
 		abort();
 	}
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 #endif
 
@@ -5091,12 +5290,12 @@
 		return b1;
 	}
 	bpf_error(cstate, "illegal modifier of 'gateway'");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 #endif
 
-struct block *
-gen_proto_abbrev(compiler_state_t *cstate, int proto)
+static struct block *
+gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
 {
 	struct block *b0;
 	struct block *b1;
@@ -5335,6 +5534,19 @@
 	return b1;
 }
 
+struct block *
+gen_proto_abbrev(compiler_state_t *cstate, int proto)
+{
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_proto_abbrev_internal(cstate, proto);
+}
+
 static struct block *
 gen_ipfrag(compiler_state_t *cstate)
 {
@@ -5361,51 +5573,76 @@
  * headers).
  */
 static struct block *
-gen_portatom(compiler_state_t *cstate, int off, bpf_int32 v)
+gen_portatom(compiler_state_t *cstate, int off, bpf_u_int32 v)
 {
 	return gen_cmp(cstate, OR_TRAN_IPV4, off, BPF_H, v);
 }
 
 static struct block *
-gen_portatom6(compiler_state_t *cstate, int off, bpf_int32 v)
+gen_portatom6(compiler_state_t *cstate, int off, bpf_u_int32 v)
 {
 	return gen_cmp(cstate, OR_TRAN_IPV6, off, BPF_H, v);
 }
 
-struct block *
-gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
+static struct block *
+gen_portop(compiler_state_t *cstate, u_int port, u_int proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip proto 'proto' and not a fragment other than the first fragment */
-	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, proto);
 	b0 = gen_ipfrag(cstate);
 	gen_and(tmp, b0);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portatom(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom(cstate, 0, port);
 		break;
 
 	case Q_DST:
-		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
-		break;
-
-	case Q_OR:
-	case Q_DEFAULT:
-		tmp = gen_portatom(cstate, 0, (bpf_int32)port);
-		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
-		gen_or(tmp, b1);
+		b1 = gen_portatom(cstate, 2, port);
 		break;
 
 	case Q_AND:
-		tmp = gen_portatom(cstate, 0, (bpf_int32)port);
-		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
+		tmp = gen_portatom(cstate, 0, port);
+		b1 = gen_portatom(cstate, 2, port);
 		gen_and(tmp, b1);
 		break;
 
+	case Q_DEFAULT:
+	case Q_OR:
+		tmp = gen_portatom(cstate, 0, port);
+		b1 = gen_portatom(cstate, 2, port);
+		gen_or(tmp, b1);
+		break;
+
+	case Q_ADDR1:
+		bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for ports");
+		/*NOTREACHED*/
+
+	case Q_ADDR2:
+		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for ports");
+		/*NOTREACHED*/
+
+	case Q_ADDR3:
+		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for ports");
+		/*NOTREACHED*/
+
+	case Q_ADDR4:
+		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for ports");
+		/*NOTREACHED*/
+
+	case Q_RA:
+		bpf_error(cstate, "'ra' is not a valid qualifier for ports");
+		/*NOTREACHED*/
+
+	case Q_TA:
+		bpf_error(cstate, "'ta' is not a valid qualifier for ports");
+		/*NOTREACHED*/
+
 	default:
 		abort();
+		/*NOTREACHED*/
 	}
 	gen_and(b0, b1);
 
@@ -5413,7 +5650,7 @@
 }
 
 static struct block *
-gen_port(compiler_state_t *cstate, int port, int ip_proto, int dir)
+gen_port(compiler_state_t *cstate, u_int port, int ip_proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
@@ -5440,7 +5677,7 @@
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portop(cstate, port, ip_proto, dir);
+		b1 = gen_portop(cstate, port, (u_int)ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
@@ -5459,36 +5696,36 @@
 }
 
 struct block *
-gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
+gen_portop6(compiler_state_t *cstate, u_int port, u_int proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
 	/* XXX - catch the first fragment of a fragmented packet? */
-	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, proto);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portatom6(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom6(cstate, 0, port);
 		break;
 
 	case Q_DST:
-		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
-		break;
-
-	case Q_OR:
-	case Q_DEFAULT:
-		tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
-		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
-		gen_or(tmp, b1);
+		b1 = gen_portatom6(cstate, 2, port);
 		break;
 
 	case Q_AND:
-		tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
-		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
+		tmp = gen_portatom6(cstate, 0, port);
+		b1 = gen_portatom6(cstate, 2, port);
 		gen_and(tmp, b1);
 		break;
 
+	case Q_DEFAULT:
+	case Q_OR:
+		tmp = gen_portatom6(cstate, 0, port);
+		b1 = gen_portatom6(cstate, 2, port);
+		gen_or(tmp, b1);
+		break;
+
 	default:
 		abort();
 	}
@@ -5498,7 +5735,7 @@
 }
 
 static struct block *
-gen_port6(compiler_state_t *cstate, int port, int ip_proto, int dir)
+gen_port6(compiler_state_t *cstate, u_int port, int ip_proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
@@ -5509,7 +5746,7 @@
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portop6(cstate, port, ip_proto, dir);
+		b1 = gen_portop6(cstate, port, (u_int)ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
@@ -5529,8 +5766,8 @@
 
 /* gen_portrange code */
 static struct block *
-gen_portrangeatom(compiler_state_t *cstate, int off, bpf_int32 v1,
-    bpf_int32 v2)
+gen_portrangeatom(compiler_state_t *cstate, u_int off, bpf_u_int32 v1,
+    bpf_u_int32 v2)
 {
 	struct block *b1, *b2;
 
@@ -5538,7 +5775,7 @@
 		/*
 		 * Reverse the order of the ports, so v1 is the lower one.
 		 */
-		bpf_int32 vtemp;
+		bpf_u_int32 vtemp;
 
 		vtemp = v1;
 		v1 = v2;
@@ -5553,41 +5790,66 @@
 	return b2;
 }
 
-struct block *
-gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
-    int dir)
+static struct block *
+gen_portrangeop(compiler_state_t *cstate, u_int port1, u_int port2,
+    bpf_u_int32 proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip proto 'proto' and not a fragment other than the first fragment */
-	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, proto);
 	b0 = gen_ipfrag(cstate);
 	gen_and(tmp, b0);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom(cstate, 0, port1, port2);
 		break;
 
 	case Q_DST:
-		b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-		break;
-
-	case Q_OR:
-	case Q_DEFAULT:
-		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);
+		b1 = gen_portrangeatom(cstate, 2, port1, port2);
 		break;
 
 	case Q_AND:
-		tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom(cstate, 0, port1, port2);
+		b1 = gen_portrangeatom(cstate, 2, port1, port2);
 		gen_and(tmp, b1);
 		break;
 
+	case Q_DEFAULT:
+	case Q_OR:
+		tmp = gen_portrangeatom(cstate, 0, port1, port2);
+		b1 = gen_portrangeatom(cstate, 2, port1, port2);
+		gen_or(tmp, b1);
+		break;
+
+	case Q_ADDR1:
+		bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for port ranges");
+		/*NOTREACHED*/
+
+	case Q_ADDR2:
+		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for port ranges");
+		/*NOTREACHED*/
+
+	case Q_ADDR3:
+		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for port ranges");
+		/*NOTREACHED*/
+
+	case Q_ADDR4:
+		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for port ranges");
+		/*NOTREACHED*/
+
+	case Q_RA:
+		bpf_error(cstate, "'ra' is not a valid qualifier for port ranges");
+		/*NOTREACHED*/
+
+	case Q_TA:
+		bpf_error(cstate, "'ta' is not a valid qualifier for port ranges");
+		/*NOTREACHED*/
+
 	default:
 		abort();
+		/*NOTREACHED*/
 	}
 	gen_and(b0, b1);
 
@@ -5595,7 +5857,7 @@
 }
 
 static struct block *
-gen_portrange(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+gen_portrange(compiler_state_t *cstate, u_int port1, u_int port2, int ip_proto,
     int dir)
 {
 	struct block *b0, *b1, *tmp;
@@ -5607,7 +5869,8 @@
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portrangeop(cstate, port1, port2, ip_proto, dir);
+		b1 = gen_portrangeop(cstate, port1, port2, (bpf_u_int32)ip_proto,
+		    dir);
 		break;
 
 	case PROTO_UNDEF:
@@ -5626,8 +5889,8 @@
 }
 
 static struct block *
-gen_portrangeatom6(compiler_state_t *cstate, int off, bpf_int32 v1,
-    bpf_int32 v2)
+gen_portrangeatom6(compiler_state_t *cstate, u_int off, bpf_u_int32 v1,
+    bpf_u_int32 v2)
 {
 	struct block *b1, *b2;
 
@@ -5635,7 +5898,7 @@
 		/*
 		 * Reverse the order of the ports, so v1 is the lower one.
 		 */
-		bpf_int32 vtemp;
+		bpf_u_int32 vtemp;
 
 		vtemp = v1;
 		v1 = v2;
@@ -5650,38 +5913,38 @@
 	return b2;
 }
 
-struct block *
-gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
-    int dir)
+static struct block *
+gen_portrangeop6(compiler_state_t *cstate, u_int port1, u_int port2,
+    bpf_u_int32 proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
 	/* XXX - catch the first fragment of a fragmented packet? */
-	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, proto);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom6(cstate, 0, port1, port2);
 		break;
 
 	case Q_DST:
-		b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-		break;
-
-	case Q_OR:
-	case Q_DEFAULT:
-		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);
+		b1 = gen_portrangeatom6(cstate, 2, port1, port2);
 		break;
 
 	case Q_AND:
-		tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom6(cstate, 0, port1, port2);
+		b1 = gen_portrangeatom6(cstate, 2, port1, port2);
 		gen_and(tmp, b1);
 		break;
 
+	case Q_DEFAULT:
+	case Q_OR:
+		tmp = gen_portrangeatom6(cstate, 0, port1, port2);
+		b1 = gen_portrangeatom6(cstate, 2, port1, port2);
+		gen_or(tmp, b1);
+		break;
+
 	default:
 		abort();
 	}
@@ -5691,7 +5954,7 @@
 }
 
 static struct block *
-gen_portrange6(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+gen_portrange6(compiler_state_t *cstate, u_int port1, u_int port2, int ip_proto,
     int dir)
 {
 	struct block *b0, *b1, *tmp;
@@ -5703,7 +5966,8 @@
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portrangeop6(cstate, port1, port2, ip_proto, dir);
+		b1 = gen_portrangeop6(cstate, port1, port2, (bpf_u_int32)ip_proto,
+		    dir);
 		break;
 
 	case PROTO_UNDEF:
@@ -5773,10 +6037,10 @@
 #endif
 
 static struct block *
-gen_protochain(compiler_state_t *cstate, int v, int proto, int dir)
+gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
 {
 #ifdef NO_PROTOCHAIN
-	return gen_proto(cstate, v, proto, dir);
+	return gen_proto(cstate, v, proto);
 #else
 	struct block *b0, *b;
 	struct slist *s[100];
@@ -5793,8 +6057,8 @@
 	case Q_IPV6:
 		break;
 	case Q_DEFAULT:
-		b0 = gen_protochain(cstate, v, Q_IP, dir);
-		b = gen_protochain(cstate, v, Q_IPV6, dir);
+		b0 = gen_protochain(cstate, v, Q_IP);
+		b = gen_protochain(cstate, v, Q_IPV6);
 		gen_or(b0, b);
 		return b;
 	default:
@@ -6099,7 +6363,7 @@
  * against Q_IP and Q_IPV6.
  */
 static struct block *
-gen_proto(compiler_state_t *cstate, int v, int proto, int dir)
+gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
 {
 	struct block *b0, *b1;
 #ifndef CHASE_CHAIN
@@ -6116,6 +6380,9 @@
 		gen_or(b0, b1);
 		return b1;
 
+	case Q_LINK:
+		return gen_linktype(cstate, v);
+
 	case Q_IP:
 		/*
 		 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
@@ -6134,13 +6401,111 @@
 		 */
 		b0 = gen_linktype(cstate, ETHERTYPE_IP);
 #ifndef CHASE_CHAIN
-		b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
+		b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, v);
 #else
 		b1 = gen_protochain(cstate, v, Q_IP);
 #endif
 		gen_and(b0, b1);
 		return b1;
 
+	case Q_ARP:
+		bpf_error(cstate, "arp does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_RARP:
+		bpf_error(cstate, "rarp does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_SCTP:
+		bpf_error(cstate, "'sctp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_TCP:
+		bpf_error(cstate, "'tcp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_UDP:
+		bpf_error(cstate, "'udp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ICMP:
+		bpf_error(cstate, "'icmp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_IGMP:
+		bpf_error(cstate, "'igmp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_IGRP:
+		bpf_error(cstate, "'igrp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ATALK:
+		bpf_error(cstate, "AppleTalk encapsulation is not specifiable");
+		/*NOTREACHED*/
+
+	case Q_DECNET:
+		bpf_error(cstate, "DECNET encapsulation is not specifiable");
+		/*NOTREACHED*/
+
+	case Q_LAT:
+		bpf_error(cstate, "LAT does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_SCA:
+		bpf_error(cstate, "SCA does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_MOPRC:
+		bpf_error(cstate, "MOPRC does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_MOPDL:
+		bpf_error(cstate, "MOPDL does not encapsulate another protocol");
+		/*NOTREACHED*/
+
+	case Q_IPV6:
+		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+#ifndef CHASE_CHAIN
+		/*
+		 * Also check for a fragment header before the final
+		 * header.
+		 */
+		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
+		b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, v);
+		gen_and(b2, b1);
+		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, v);
+		gen_or(b2, b1);
+#else
+		b1 = gen_protochain(cstate, v, Q_IPV6);
+#endif
+		gen_and(b0, b1);
+		return b1;
+
+	case Q_ICMPV6:
+		bpf_error(cstate, "'icmp6 proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_AH:
+		bpf_error(cstate, "'ah proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ESP:
+		bpf_error(cstate, "'esp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_PIM:
+		bpf_error(cstate, "'pim proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_VRRP:
+		bpf_error(cstate, "'vrrp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_AARP:
+		bpf_error(cstate, "'aarp proto' is bogus");
+		/*NOTREACHED*/
+
 	case Q_ISO:
 		switch (cstate->linktype) {
 
@@ -6165,7 +6530,6 @@
 			 */
 			return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
 			/*NOTREACHED*/
-			break;
 
 		case DLT_C_HDLC:
 			/*
@@ -6174,142 +6538,88 @@
 			 */
 			b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
 			/* OSI in C-HDLC is stuffed with a fudge byte */
-			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
+			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, v);
 			gen_and(b0, b1);
 			return b1;
 
 		default:
 			b0 = gen_linktype(cstate, LLCSAP_ISONS);
-			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
+			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, v);
 			gen_and(b0, b1);
 			return b1;
 		}
 
+	case Q_ESIS:
+		bpf_error(cstate, "'esis proto' is bogus");
+		/*NOTREACHED*/
+
 	case Q_ISIS:
 		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(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
+		b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, v);
 		gen_and(b0, b1);
 		return b1;
 
-	case Q_ARP:
-		bpf_error(cstate, "arp does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_RARP:
-		bpf_error(cstate, "rarp does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_ATALK:
-		bpf_error(cstate, "atalk encapsulation is not specifiable");
-		/* NOTREACHED */
-
-	case Q_DECNET:
-		bpf_error(cstate, "decnet encapsulation is not specifiable");
-		/* NOTREACHED */
-
-	case Q_SCA:
-		bpf_error(cstate, "sca does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_LAT:
-		bpf_error(cstate, "lat does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_MOPRC:
-		bpf_error(cstate, "moprc does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_MOPDL:
-		bpf_error(cstate, "mopdl does not encapsulate another protocol");
-		/* NOTREACHED */
-
-	case Q_LINK:
-		return gen_linktype(cstate, v);
-
-	case Q_UDP:
-		bpf_error(cstate, "'udp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_TCP:
-		bpf_error(cstate, "'tcp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_SCTP:
-		bpf_error(cstate, "'sctp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_ICMP:
-		bpf_error(cstate, "'icmp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_IGMP:
-		bpf_error(cstate, "'igmp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_IGRP:
-		bpf_error(cstate, "'igrp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_PIM:
-		bpf_error(cstate, "'pim proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_VRRP:
-		bpf_error(cstate, "'vrrp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_CARP:
-		bpf_error(cstate, "'carp proto' is bogus");
-		/* NOTREACHED */
-
-	case Q_IPV6:
-		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
-#ifndef CHASE_CHAIN
-		/*
-		 * Also check for a fragment header before the final
-		 * header.
-		 */
-		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
-		b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, (bpf_int32)v);
-		gen_and(b2, b1);
-		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
-		gen_or(b2, b1);
-#else
-		b1 = gen_protochain(cstate, v, Q_IPV6);
-#endif
-		gen_and(b0, b1);
-		return b1;
-
-	case Q_ICMPV6:
-		bpf_error(cstate, "'icmp6 proto' is bogus");
-
-	case Q_AH:
-		bpf_error(cstate, "'ah proto' is bogus");
-
-	case Q_ESP:
-		bpf_error(cstate, "'ah proto' is bogus");
+	case Q_CLNP:
+		bpf_error(cstate, "'clnp proto' is not supported");
+		/*NOTREACHED*/
 
 	case Q_STP:
 		bpf_error(cstate, "'stp proto' is bogus");
+		/*NOTREACHED*/
 
 	case Q_IPX:
 		bpf_error(cstate, "'ipx proto' is bogus");
+		/*NOTREACHED*/
 
 	case Q_NETBEUI:
 		bpf_error(cstate, "'netbeui proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_L1:
+		bpf_error(cstate, "'l1 proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_L2:
+		bpf_error(cstate, "'l2 proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_IIH:
+		bpf_error(cstate, "'iih proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_SNP:
+		bpf_error(cstate, "'snp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_CSNP:
+		bpf_error(cstate, "'csnp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_PSNP:
+		bpf_error(cstate, "'psnp proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_ISIS_LSP:
+		bpf_error(cstate, "'lsp proto' is bogus");
+		/*NOTREACHED*/
 
 	case Q_RADIO:
 		bpf_error(cstate, "'radio proto' is bogus");
+		/*NOTREACHED*/
+
+	case Q_CARP:
+		bpf_error(cstate, "'carp proto' is bogus");
+		/*NOTREACHED*/
 
 	default:
 		abort();
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
@@ -6331,6 +6641,13 @@
 	int port, real_proto;
 	int port1, port2;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (q.addr) {
 
 	case Q_NET:
@@ -6603,31 +6920,42 @@
 	case Q_PROTOCHAIN:
 		real_proto = lookup_proto(cstate, name, proto);
 		if (real_proto >= 0)
-			return gen_protochain(cstate, real_proto, proto, dir);
+			return gen_protochain(cstate, real_proto, proto);
 		else
 			bpf_error(cstate, "unknown protocol: %s", name);
 
 	case Q_UNDEF:
 		syntax(cstate);
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
-    unsigned int masklen, struct qual q)
+    bpf_u_int32 masklen, struct qual q)
 {
 	register int nlen, mlen;
 	bpf_u_int32 n, m;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	nlen = __pcap_atoin(s1, &n);
+	if (nlen < 0)
+		bpf_error(cstate, "invalid IPv4 address '%s'", s1);
 	/* Promote short ipaddr */
 	n <<= 32 - nlen;
 
 	if (s2 != NULL) {
 		mlen = __pcap_atoin(s2, &m);
+		if (mlen < 0)
+			bpf_error(cstate, "invalid IPv4 address '%s'", s2);
 		/* Promote short ipaddr */
 		m <<= 32 - mlen;
 		if ((n & ~m) != 0)
@@ -6657,27 +6985,39 @@
 
 	default:
 		bpf_error(cstate, "Mask syntax for networks only");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
 {
 	bpf_u_int32 mask;
-	int proto = q.proto;
-	int dir = q.dir;
+	int proto;
+	int dir;
 	register int vlen;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	proto = q.proto;
+	dir = q.dir;
 	if (s == NULL)
 		vlen = 32;
 	else if (q.proto == Q_DECNET) {
 		vlen = __pcap_atodn(s, &v);
 		if (vlen == 0)
 			bpf_error(cstate, "malformed decnet address '%s'", s);
-	} else
+	} else {
 		vlen = __pcap_atoin(s, &v);
+		if (vlen < 0)
+			bpf_error(cstate, "invalid IPv4 address '%s'", s);
+	}
 
 	switch (q.addr) {
 
@@ -6721,8 +7061,8 @@
 
 	    {
 		struct block *b;
-		b = gen_port(cstate, (int)v, proto, dir);
-		gen_or(gen_port6(cstate, (int)v, proto, dir), b);
+		b = gen_port(cstate, v, proto, dir);
+		gen_or(gen_port6(cstate, v, proto, dir), b);
 		return b;
 	    }
 
@@ -6743,36 +7083,36 @@
 
 	    {
 		struct block *b;
-		b = gen_portrange(cstate, (int)v, (int)v, proto, dir);
-		gen_or(gen_portrange6(cstate, (int)v, (int)v, proto, dir), b);
+		b = gen_portrange(cstate, v, v, proto, dir);
+		gen_or(gen_portrange6(cstate, v, v, proto, dir), b);
 		return b;
 	    }
 
 	case Q_GATEWAY:
 		bpf_error(cstate, "'gateway' requires a name");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 
 	case Q_PROTO:
-		return gen_proto(cstate, (int)v, proto, dir);
+		return gen_proto(cstate, v, proto, dir);
 
 	case Q_PROTOCHAIN:
-		return gen_protochain(cstate, (int)v, proto, dir);
+		return gen_protochain(cstate, v, proto);
 
 	case Q_UNDEF:
 		syntax(cstate);
-		/* NOTREACHED */
+		/*NOTREACHED*/
 
 	default:
 		abort();
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 #ifdef INET6
 struct block *
 gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
-    unsigned int masklen, struct qual q)
+    bpf_u_int32 masklen, struct qual q)
 {
 	struct addrinfo *res;
 	struct in6_addr *addr;
@@ -6780,6 +7120,13 @@
 	struct block *b;
 	uint32_t *a, *m;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (s2)
 		bpf_error(cstate, "no mask %s supported", s2);
 
@@ -6791,10 +7138,10 @@
 		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(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+	if (masklen > sizeof(mask.s6_addr) * 8)
+		bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask.s6_addr) * 8));
 	memset(&mask, 0, sizeof(mask));
-	memset(&mask, 0xff, masklen / 8);
+	memset(&mask.s6_addr, 0xff, masklen / 8);
 	if (masklen % 8) {
 		mask.s6_addr[masklen / 8] =
 			(0xff << (8 - masklen % 8)) & 0xff;
@@ -6823,45 +7170,64 @@
 
 	default:
 		bpf_error(cstate, "invalid qualifier against IPv6 address");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 }
 #endif /*INET6*/
 
 struct block *
-gen_ecode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
+gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
 {
 	struct block *b, *tmp;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+		cstate->e = pcap_ether_aton(s);
+		if (cstate->e == NULL)
+			bpf_error(cstate, "malloc");
 		switch (cstate->linktype) {
 		case DLT_EN10MB:
 		case DLT_NETANALYZER:
 		case DLT_NETANALYZER_TRANSPARENT:
 			tmp = gen_prevlinkhdr_check(cstate);
-			b = gen_ehostop(cstate, eaddr, (int)q.dir);
+			b = gen_ehostop(cstate, cstate->e, (int)q.dir);
 			if (tmp != NULL)
 				gen_and(tmp, b);
-			return b;
+			break;
 		case DLT_FDDI:
-			return gen_fhostop(cstate, eaddr, (int)q.dir);
+			b = gen_fhostop(cstate, cstate->e, (int)q.dir);
+			break;
 		case DLT_IEEE802:
-			return gen_thostop(cstate, eaddr, (int)q.dir);
+			b = gen_thostop(cstate, cstate->e, (int)q.dir);
+			break;
 		case DLT_IEEE802_11:
 		case DLT_PRISM_HEADER:
 		case DLT_IEEE802_11_RADIO_AVS:
 		case DLT_IEEE802_11_RADIO:
 		case DLT_PPI:
-			return gen_wlanhostop(cstate, eaddr, (int)q.dir);
-		case DLT_IP_OVER_FC:
-			return gen_ipfchostop(cstate, eaddr, (int)q.dir);
-		default:
-			bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+			b = gen_wlanhostop(cstate, cstate->e, (int)q.dir);
 			break;
+		case DLT_IP_OVER_FC:
+			b = gen_ipfchostop(cstate, cstate->e, (int)q.dir);
+			break;
+		default:
+			free(cstate->e);
+			cstate->e = NULL;
+			bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+			/*NOTREACHED*/
 		}
+		free(cstate->e);
+		cstate->e = NULL;
+		return (b);
 	}
 	bpf_error(cstate, "ethernet address used in non-ether expression");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 void
@@ -6903,9 +7269,11 @@
  * (1, 2, or 4) at that offset into that register, making it the register
  * for "index".
  */
-struct arth *
-gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
+static struct arth *
+gen_load_internal(compiler_state_t *cstate, int proto, struct arth *inst,
+    bpf_u_int32 size)
 {
+	int size_code;
 	struct slist *s, *tmp;
 	struct block *b;
 	int regno = alloc_reg(cstate);
@@ -6915,17 +7283,18 @@
 
 	default:
 		bpf_error(cstate, "data size must be 1, 2, or 4");
+		/*NOTREACHED*/
 
 	case 1:
-		size = BPF_B;
+		size_code = BPF_B;
 		break;
 
 	case 2:
-		size = BPF_H;
+		size_code = BPF_H;
 		break;
 
 	case 4:
-		size = BPF_W;
+		size_code = BPF_W;
 		break;
 	}
 	switch (proto) {
@@ -6952,7 +7321,7 @@
 		/*
 		 * Load the item at that offset.
 		 */
-		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
 		sappend(s, tmp);
 		sappend(inst->s, s);
 		break;
@@ -6994,7 +7363,7 @@
 		 * variable-length; that header length is what we put
 		 * into the X register and then added to the index).
 		 */
-		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
 		tmp->s.k = cstate->off_linkhdr.constant_part;
 		sappend(s, tmp);
 		sappend(inst->s, s);
@@ -7041,7 +7410,7 @@
 		 * payload, and the constant part of the offset of the
 		 * start of the link-layer payload.
 		 */
-		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
 		tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		sappend(s, tmp);
 		sappend(inst->s, s);
@@ -7050,7 +7419,7 @@
 		 * Do the computation only if the packet contains
 		 * the protocol in question.
 		 */
-		b = gen_proto_abbrev(cstate, proto);
+		b = gen_proto_abbrev_internal(cstate, proto);
 		if (inst->b)
 			gen_and(inst->b, b);
 		inst->b = b;
@@ -7098,7 +7467,7 @@
 		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));
+		sappend(s, tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code));
 		tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		sappend(inst->s, s);
 
@@ -7108,10 +7477,10 @@
 		 * if this is an IP datagram and is the first or
 		 * only fragment of that datagram.
 		 */
-		gen_and(gen_proto_abbrev(cstate, proto), b = gen_ipfrag(cstate));
+		gen_and(gen_proto_abbrev_internal(cstate, proto), b = gen_ipfrag(cstate));
 		if (inst->b)
 			gen_and(inst->b, b);
-		gen_and(gen_proto_abbrev(cstate, Q_IP), b);
+		gen_and(gen_proto_abbrev_internal(cstate, Q_IP), b);
 		inst->b = b;
 		break;
 	case Q_ICMPV6:
@@ -7119,7 +7488,7 @@
         * Do the computation only if the packet contains
         * the protocol in question.
         */
-        b = gen_proto_abbrev(cstate, Q_IPV6);
+        b = gen_proto_abbrev_internal(cstate, Q_IPV6);
         if (inst->b) {
             gen_and(inst->b, b);
         }
@@ -7160,7 +7529,7 @@
         * payload, and the constant part of the offset of the
         * start of the link-layer payload.
         */
-        tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+        tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
         tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40;
 
         sappend(s, tmp);
@@ -7176,8 +7545,22 @@
 	return inst;
 }
 
-struct block *
-gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+struct arth *
+gen_load(compiler_state_t *cstate, int proto, struct arth *inst,
+    bpf_u_int32 size)
+{
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_load_internal(cstate, proto, inst, size);
+}
+
+static struct block *
+gen_relation_internal(compiler_state_t *cstate, int code, struct arth *a0,
     struct arth *a1, int reversed)
 {
 	struct slist *s0, *s1, *s2;
@@ -7220,13 +7603,36 @@
 	return b;
 }
 
+struct block *
+gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+    struct arth *a1, int reversed)
+{
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_relation_internal(cstate, code, a0, a1, reversed);
+}
+
 struct arth *
 gen_loadlen(compiler_state_t *cstate)
 {
-	int regno = alloc_reg(cstate);
-	struct arth *a = (struct arth *)newchunk(cstate, sizeof(*a));
+	int regno;
+	struct arth *a;
 	struct slist *s;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	regno = alloc_reg(cstate);
+	a = (struct arth *)newchunk(cstate, sizeof(*a));
 	s = new_stmt(cstate, BPF_LD|BPF_LEN);
 	s->next = new_stmt(cstate, BPF_ST);
 	s->next->s.k = regno;
@@ -7236,8 +7642,8 @@
 	return a;
 }
 
-struct arth *
-gen_loadi(compiler_state_t *cstate, int val)
+static struct arth *
+gen_loadi_internal(compiler_state_t *cstate, bpf_u_int32 val)
 {
 	struct arth *a;
 	struct slist *s;
@@ -7258,10 +7664,36 @@
 }
 
 struct arth *
-gen_neg(compiler_state_t *cstate, struct arth *a)
+gen_loadi(compiler_state_t *cstate, bpf_u_int32 val)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_loadi_internal(cstate, val);
+}
+
+/*
+ * The a_arg dance is to avoid annoying whining by compilers that
+ * a might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct arth *
+gen_neg(compiler_state_t *cstate, struct arth *a_arg)
+{
+	struct arth *a = a_arg;
 	struct slist *s;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	s = xfer_to_a(cstate, a);
 	sappend(a->s, s);
 	s = new_stmt(cstate, BPF_ALU|BPF_NEG);
@@ -7274,15 +7706,31 @@
 	return a;
 }
 
+/*
+ * The a0_arg dance is to avoid annoying whining by compilers that
+ * a0 might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
 struct arth *
-gen_arth(compiler_state_t *cstate, int code, struct arth *a0,
+gen_arth(compiler_state_t *cstate, int code, struct arth *a0_arg,
     struct arth *a1)
 {
+	struct arth *a0 = a0_arg;
 	struct slist *s0, *s1, *s2;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Disallow division by, or modulus by, zero; we do this here
 	 * so that it gets done even if the optimizer is disabled.
+	 *
+	 * Also disallow shifts by a value greater than 31; we do this
+	 * here, for the same reason.
 	 */
 	if (code == BPF_DIV) {
 		if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
@@ -7290,6 +7738,9 @@
 	} else if (code == BPF_MOD) {
 		if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
 			bpf_error(cstate, "modulus by zero");
+	} else if (code == BPF_LSH || code == BPF_RSH) {
+		if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k > 31)
+			bpf_error(cstate, "shift by more than 31 bits");
 	}
 	s0 = xfer_to_x(cstate, a1);
 	s1 = xfer_to_a(cstate, a0);
@@ -7337,7 +7788,7 @@
 		}
 	}
 	bpf_error(cstate, "too many registers needed to evaluate expression");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -7367,6 +7818,13 @@
 struct block *
 gen_greater(compiler_state_t *cstate, int n)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	return gen_len(cstate, BPF_JGE, n);
 }
 
@@ -7378,6 +7836,13 @@
 {
 	struct block *b;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	b = gen_len(cstate, BPF_JGT, n);
 	gen_not(b);
 
@@ -7395,24 +7860,31 @@
  * would generate code appropriate to the radio header in question.
  */
 struct block *
-gen_byteop(compiler_state_t *cstate, int op, int idx, int val)
+gen_byteop(compiler_state_t *cstate, int op, int idx, bpf_u_int32 val)
 {
 	struct block *b;
 	struct slist *s;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (op) {
 	default:
 		abort();
 
 	case '=':
-		return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, val);
 
 	case '<':
-		b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, val);
 		return b;
 
 	case '>':
-		b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, val);
 		return b;
 
 	case '|':
@@ -7440,6 +7912,13 @@
 	struct block *b0, *b1, *b2;
 	static const u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (proto) {
 
 	case Q_DEFAULT:
@@ -7471,7 +7950,7 @@
 		default:
 			bpf_error(cstate, "not a broadcast link");
 		}
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_IP:
 		/*
@@ -7483,15 +7962,15 @@
 			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);
+		b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W, 0, hostmask);
 		b2 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W,
-			      (bpf_int32)(~0 & hostmask), hostmask);
+			      ~0 & hostmask, hostmask);
 		gen_or(b1, b2);
 		gen_and(b0, b2);
 		return b2;
 	}
 	bpf_error(cstate, "only link-layer/IP broadcast filters supported");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 /*
@@ -7518,6 +7997,13 @@
 	register struct block *b0, *b1, *b2;
 	register struct slist *s;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (proto) {
 
 	case Q_DEFAULT:
@@ -7675,18 +8161,65 @@
 
 	case Q_IP:
 		b0 = gen_linktype(cstate, ETHERTYPE_IP);
-		b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, (bpf_int32)224);
+		b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, 224);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_IPV6:
 		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
-		b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, (bpf_int32)255);
+		b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, 255);
 		gen_and(b0, b1);
 		return b1;
 	}
 	bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
-	/* NOTREACHED */
+	/*NOTREACHED*/
+}
+
+struct block *
+gen_ifindex(compiler_state_t *cstate, int ifindex)
+{
+	register struct block *b0;
+
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
+	 * Only some data link types support ifindex qualifiers.
+	 */
+	switch (cstate->linktype) {
+	case DLT_LINUX_SLL2:
+		/* match packets on this interface */
+		b0 = gen_cmp(cstate, OR_LINKHDR, 4, BPF_W, ifindex);
+		break;
+        default:
+#if defined(linux)
+		/*
+		 * This is Linux; we require PF_PACKET support.
+		 * If this is a *live* capture, we can look at
+		 * special meta-data in the filter expression;
+		 * if it's a savefile, we can't.
+		 */
+		if (cstate->bpf_pcap->rfile != NULL) {
+			/* We have a FILE *, so this is a savefile */
+			bpf_error(cstate, "ifindex not supported on %s when reading savefiles",
+			    pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+			b0 = NULL;
+			/*NOTREACHED*/
+		}
+		/* match ifindex */
+		b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_IFINDEX, BPF_W,
+		             ifindex);
+#else /* defined(linux) */
+		bpf_error(cstate, "ifindex not supported on %s",
+		    pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+		/*NOTREACHED*/
+#endif /* defined(linux) */
+	}
+	return (b0);
 }
 
 /*
@@ -7704,13 +8237,20 @@
 	register struct block *b0;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Only some data link types support inbound/outbound qualifiers.
 	 */
 	switch (cstate->linktype) {
 	case DLT_SLIP:
-		b0 = gen_relation(cstate, BPF_JEQ,
-			  gen_load(cstate, Q_LINK, gen_loadi(cstate, 0), 1),
-			  gen_loadi(cstate, 0),
+		b0 = gen_relation_internal(cstate, BPF_JEQ,
+			  gen_load_internal(cstate, Q_LINK, gen_loadi_internal(cstate, 0), 1),
+			  gen_loadi_internal(cstate, 0),
 			  dir);
 		break;
 
@@ -7733,10 +8273,19 @@
 		}
 		break;
 
+	case DLT_LINUX_SLL2:
+		/* match outgoing packets */
+		b0 = gen_cmp(cstate, OR_LINKHDR, 10, BPF_B, LINUX_SLL_OUTGOING);
+		if (!dir) {
+			/* to filter on inbound traffic, invert the match */
+			gen_not(b0);
+		}
+		break;
+
 #ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
 		b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
-		    (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
+		    ((dir == 0) ? PF_IN : PF_OUT));
 		break;
 #endif
 
@@ -7800,19 +8349,18 @@
 		 * with newer capture APIs, allowing it to be saved
 		 * in pcapng files.
 		 */
-#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+#if defined(linux)
 		/*
-		 * This is Linux with PF_PACKET support.
+		 * This is Linux; we require PF_PACKET support.
 		 * If this is a *live* capture, we can look at
 		 * special meta-data in the filter expression;
 		 * if it's a savefile, we can't.
 		 */
 		if (cstate->bpf_pcap->rfile != NULL) {
 			/* We have a FILE *, so this is a savefile */
-			bpf_error(cstate, "inbound/outbound not supported on linktype %d when reading savefiles",
-			    cstate->linktype);
-			b0 = NULL;
-			/* NOTREACHED */
+			bpf_error(cstate, "inbound/outbound not supported on %s when reading savefiles",
+			    pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+			/*NOTREACHED*/
 		}
 		/* match outgoing packets */
 		b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
@@ -7821,11 +8369,11 @@
 			/* to filter on inbound traffic, invert the match */
 			gen_not(b0);
 		}
-#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
-		bpf_error(cstate, "inbound/outbound not supported on linktype %d",
-		    cstate->linktype);
-		/* NOTREACHED */
-#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
+#else /* defined(linux) */
+		bpf_error(cstate, "inbound/outbound not supported on %s",
+		    pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+		/*NOTREACHED*/
+#endif /* defined(linux) */
 	}
 	return (b0);
 }
@@ -7838,18 +8386,26 @@
 	struct block *b0;
 	u_int len, off;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "ifname supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 	len = sizeof(((struct pfloghdr *)0)->ifname);
 	off = offsetof(struct pfloghdr, ifname);
 	if (strlen(ifname) >= len) {
 		bpf_error(cstate, "ifname interface names can only be %d characters",
 		    len-1);
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
-	b0 = gen_bcmp(cstate, OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
+	b0 = gen_bcmp(cstate, OR_LINKHDR, off, (u_int)strlen(ifname),
+	    (const u_char *)ifname);
 	return (b0);
 }
 
@@ -7859,19 +8415,26 @@
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "ruleset supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
 		bpf_error(cstate, "ruleset names can only be %ld characters",
 		    (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
-	    strlen(ruleset), (const u_char *)ruleset);
+	    (u_int)strlen(ruleset), (const u_char *)ruleset);
 	return (b0);
 }
 
@@ -7881,13 +8444,20 @@
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "rnr supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
-		 (bpf_int32)rnr);
+		 (bpf_u_int32)rnr);
 	return (b0);
 }
 
@@ -7897,13 +8467,20 @@
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "srnr supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
-	    (bpf_int32)srnr);
+	    (bpf_u_int32)srnr);
 	return (b0);
 }
 
@@ -7913,13 +8490,20 @@
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "reason supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
-	    (bpf_int32)reason);
+	    (bpf_u_int32)reason);
 	return (b0);
 }
 
@@ -7929,88 +8513,150 @@
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	if (cstate->linktype != DLT_PFLOG) {
 		bpf_error(cstate, "action supported only on PF linktype");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
-	    (bpf_int32)action);
+	    (bpf_u_int32)action);
 	return (b0);
 }
 #else /* !HAVE_NET_PFVAR_H */
 struct block *
 gen_pf_ifname(compiler_state_t *cstate, const char *ifname _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_pf_reason(compiler_state_t *cstate, int reason _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 struct block *
 gen_pf_action(compiler_state_t *cstate, int action _U_)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 #endif /* HAVE_NET_PFVAR_H */
 
 /* IEEE 802.11 wireless header */
 struct block *
-gen_p80211_type(compiler_state_t *cstate, int type, int mask)
+gen_p80211_type(compiler_state_t *cstate, bpf_u_int32 type, bpf_u_int32 mask)
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	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(cstate, OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
-		    (bpf_int32)mask);
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, type, mask);
 		break;
 
 	default:
 		bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
 	return (b0);
 }
 
 struct block *
-gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
+gen_p80211_fcdir(compiler_state_t *cstate, bpf_u_int32 fcdir)
 {
 	struct block *b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (cstate->linktype) {
 
 	case DLT_IEEE802_11:
@@ -8021,34 +8667,47 @@
 
 	default:
 		bpf_error(cstate, "frame direction supported only with 802.11 headers");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 
-	b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
-		(bpf_u_int32)IEEE80211_FC1_DIR_MASK);
+	b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, fcdir,
+	    IEEE80211_FC1_DIR_MASK);
 
 	return (b0);
 }
 
 struct block *
-gen_acode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
+gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
 {
+	struct block *b;
+
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (cstate->linktype) {
 
 	case DLT_ARCNET:
 	case DLT_ARCNET_LINUX:
 		if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
-		    q.proto == Q_LINK)
-			return (gen_ahostop(cstate, eaddr, (int)q.dir));
-		else {
+		    q.proto == Q_LINK) {
+			cstate->e = pcap_ether_aton(s);
+			if (cstate->e == NULL)
+				bpf_error(cstate, "malloc");
+			b = gen_ahostop(cstate, cstate->e, (int)q.dir);
+			free(cstate->e);
+			cstate->e = NULL;
+			return (b);
+		} else
 			bpf_error(cstate, "ARCnet address used in non-arc expression");
-			/* NOTREACHED */
-		}
-		break;
+ 		/*NOTREACHED*/
 
 	default:
 		bpf_error(cstate, "aid supported only on ARCnet");
-		/* NOTREACHED */
+		/*NOTREACHED*/
 	}
 }
 
@@ -8080,30 +8739,30 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11");
-		break;
+ 		/*NOTREACHED*/
 	}
 	abort();
-	/* NOTREACHED */
+	/*NOTREACHED*/
 }
 
 static struct block *
@@ -8123,19 +8782,24 @@
 }
 
 static struct block *
-gen_vlan_vid_test(compiler_state_t *cstate, int vlan_num)
+gen_vlan_vid_test(compiler_state_t *cstate, bpf_u_int32 vlan_num)
 {
-	return gen_mcmp(cstate, OR_LINKPL, 0, BPF_H, (bpf_int32)vlan_num, 0x0fff);
+	if (vlan_num > 0x0fff) {
+		bpf_error(cstate, "VLAN tag %u greater than maximum %u",
+		    vlan_num, 0x0fff);
+	}
+	return gen_mcmp(cstate, OR_LINKPL, 0, BPF_H, vlan_num, 0x0fff);
 }
 
 static struct block *
-gen_vlan_no_bpf_extensions(compiler_state_t *cstate, int vlan_num)
+gen_vlan_no_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+    int has_vlan_tag)
 {
 	struct block *b0, *b1;
 
 	b0 = gen_vlan_tpid_test(cstate);
 
-	if (vlan_num >= 0) {
+	if (has_vlan_tag) {
 		b1 = gen_vlan_vid_test(cstate, vlan_num);
 		gen_and(b0, b1);
 		b0 = b1;
@@ -8154,7 +8818,8 @@
 #if defined(SKF_AD_VLAN_TAG_PRESENT)
 /* add v to variable part of off */
 static void
-gen_vlan_vloffset_add(compiler_state_t *cstate, bpf_abs_offset *off, int v, struct slist *s)
+gen_vlan_vloffset_add(compiler_state_t *cstate, bpf_abs_offset *off,
+    bpf_u_int32 v, struct slist *s)
 {
 	struct slist *s2;
 
@@ -8218,12 +8883,15 @@
 	sappend(s, s2);
 	sjeq->s.jt = s2;
 
-	/* jump to the test in b_vid (bypass loading VID from packet data) */
+	/* Jump to the test in b_vid. We need to jump one instruction before
+	 * the end of the b_vid block so that we only skip loading the TCI
+	 * from packet data and not the 'and' instruction extractging VID.
+	 */
 	cnt = 0;
 	for (s2 = b_vid->stmts; s2; s2 = s2->next)
 		cnt++;
 	s2 = new_stmt(cstate, JMP(BPF_JA));
-	s2->s.k = cnt;
+	s2->s.k = cnt - 1;
 	sappend(s, s2);
 
 	/* insert our statements at the beginning of b_vid */
@@ -8240,7 +8908,8 @@
  * update variable part of the offsets
  */
 static struct block *
-gen_vlan_bpf_extensions(compiler_state_t *cstate, int vlan_num)
+gen_vlan_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+    int has_vlan_tag)
 {
         struct block *b0, *b_tpid, *b_vid = NULL;
         struct slist *s;
@@ -8256,7 +8925,7 @@
 
 	/*
 	 * This is tricky. We need to insert the statements updating variable
-	 * parts of offsets before the the traditional TPID and VID tests so
+	 * parts of offsets before the traditional TPID and VID tests so
 	 * that they are called whenever SKF_AD_VLAN_TAG_PRESENT fails but
 	 * we do not want this update to affect those checks. That's why we
 	 * generate both test blocks first and insert the statements updating
@@ -8265,14 +8934,14 @@
 	 * function but gen_vlan_bpf_extensions() isn't called in that case.
 	 */
 	b_tpid = gen_vlan_tpid_test(cstate);
-	if (vlan_num >= 0)
+	if (has_vlan_tag)
 		b_vid = gen_vlan_vid_test(cstate, vlan_num);
 
 	gen_vlan_patch_tpid_test(cstate, b_tpid);
 	gen_or(b0, b_tpid);
 	b0 = b_tpid;
 
-	if (vlan_num >= 0) {
+	if (has_vlan_tag) {
 		gen_vlan_patch_vid_test(cstate, b_vid);
 		gen_and(b0, b_vid);
 		b0 = b_vid;
@@ -8286,10 +8955,17 @@
  * support IEEE 802.1Q VLAN trunk over ethernet
  */
 struct block *
-gen_vlan(compiler_state_t *cstate, int vlan_num)
+gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
 {
 	struct	block	*b0;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	/* can't check for VLAN-encapsulated packets inside MPLS */
 	if (cstate->label_stack_depth > 0)
 		bpf_error(cstate, "no VLAN match after MPLS");
@@ -8340,24 +9016,27 @@
 			 * Do we need special VLAN handling?
 			 */
 			if (cstate->bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
-				b0 = gen_vlan_bpf_extensions(cstate, vlan_num);
+				b0 = gen_vlan_bpf_extensions(cstate, vlan_num,
+				    has_vlan_tag);
 			else
-				b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
+				b0 = gen_vlan_no_bpf_extensions(cstate,
+				    vlan_num, has_vlan_tag);
 		} else
 #endif
-			b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
+			b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num,
+			    has_vlan_tag);
                 break;
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
 	case DLT_IEEE802_11_RADIO_AVS:
 	case DLT_IEEE802_11_RADIO:
-		b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
+		b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num, has_vlan_tag);
 		break;
 
 	default:
-		bpf_error(cstate, "no VLAN support for data link type %d",
-		      cstate->linktype);
+		bpf_error(cstate, "no VLAN support for %s",
+		      pcap_datalink_val_to_description_or_dlt(cstate->linktype));
 		/*NOTREACHED*/
 	}
 
@@ -8368,12 +9047,25 @@
 
 /*
  * support for MPLS
+ *
+ * The label_num_arg dance is to avoid annoying whining by compilers that
+ * label_num might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
  */
 struct block *
-gen_mpls(compiler_state_t *cstate, int label_num)
+gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
+    int has_label_num)
 {
+	volatile bpf_u_int32 label_num = label_num_arg;
 	struct	block	*b0, *b1;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
         if (cstate->label_stack_depth > 0) {
             /* just match the bottom-of-stack bit clear */
             b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
@@ -8400,17 +9092,20 @@
                      * leave it for now */
 
             default:
-                    bpf_error(cstate, "no MPLS support for data link type %d",
-                          cstate->linktype);
+                    bpf_error(cstate, "no MPLS support for %s",
+                          pcap_datalink_val_to_description_or_dlt(cstate->linktype));
                     /*NOTREACHED*/
-                    break;
             }
         }
 
 	/* If a specific MPLS label is requested, check it */
-	if (label_num >= 0) {
+	if (has_label_num) {
+		if (label_num > 0xFFFFF) {
+			bpf_error(cstate, "MPLS label %u greater than maximum %u",
+			    label_num, 0xFFFFF);
+		}
 		label_num = label_num << 12; /* label is shifted 12 bits on the wire */
-		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
+		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, label_num,
 		    0xfffff000); /* only compare the first 20 bits */
 		gen_and(b0, b1);
 		b0 = b1;
@@ -8442,24 +9137,41 @@
 struct block *
 gen_pppoed(compiler_state_t *cstate)
 {
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	/* check for PPPoE discovery */
-	return gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOED);
+	return gen_linktype(cstate, ETHERTYPE_PPPOED);
 }
 
 struct block *
-gen_pppoes(compiler_state_t *cstate, int sess_num)
+gen_pppoes(compiler_state_t *cstate, bpf_u_int32 sess_num, int has_sess_num)
 {
 	struct block *b0, *b1;
 
 	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	/*
 	 * Test against the PPPoE session link-layer type.
 	 */
-	b0 = gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOES);
+	b0 = gen_linktype(cstate, ETHERTYPE_PPPOES);
 
 	/* If a specific session is requested, check PPPoE session id */
-	if (sess_num >= 0) {
-		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W,
-		    (bpf_int32)sess_num, 0x0000ffff);
+	if (has_sess_num) {
+		if (sess_num > 0x0000ffff) {
+			bpf_error(cstate, "PPPoE session number %u greater than maximum %u",
+			    sess_num, 0x0000ffff);
+		}
+		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, sess_num, 0x0000ffff);
 		gen_and(b0, b1);
 		b0 = b1;
 	}
@@ -8469,29 +9181,8 @@
 	 * the PPP packet, and note that this is PPPoE rather than
 	 * raw PPP.
 	 *
-	 * XXX - this is a bit of a kludge.  If we were to split the
-	 * compiler into a parser that parses an expression and
-	 * generates an expression tree, and a code generator that
-	 * takes an expression tree (which could come from our
-	 * parser or from some other parser) and generates BPF code,
-	 * we could perhaps make the offsets parameters of routines
-	 * and, in the handler for an "AND" node, pass to subnodes
-	 * other than the PPPoE node the adjusted offsets.
-	 *
-	 * This would mean that "pppoes" would, instead of changing the
-	 * behavior of *all* tests after it, change only the behavior
-	 * of tests ANDed with it.  That would change the documented
-	 * semantics of "pppoes", which might break some expressions.
-	 * However, it would mean that "(pppoes and ip) or ip" would check
-	 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
-	 * checking only for VLAN-encapsulated IP, so that could still
-	 * be considered worth doing; it wouldn't break expressions
-	 * that are of the form "pppoes and ..." which I suspect are the
-	 * most common expressions involving "pppoes".  "pppoes or ..."
-	 * doesn't necessarily do what the user would really want, now,
-	 * as all the "or ..." tests would be done assuming PPPoE, even
-	 * though the "or" could be viewed as meaning "or, if this isn't
-	 * a PPPoE packet...".
+	 * XXX - this is a bit of a kludge.  See the comments in
+	 * gen_vlan().
 	 *
 	 * The "network-layer" protocol is PPPoE, which has a 6-byte
 	 * PPPoE header, followed by a PPP packet.
@@ -8520,8 +9211,8 @@
  * specified. Parameterized to handle both IPv4 and IPv6. */
 static struct block *
 gen_geneve_check(compiler_state_t *cstate,
-    struct block *(*gen_portfn)(compiler_state_t *, int, int, int),
-    enum e_offrel offrel, int vni)
+    struct block *(*gen_portfn)(compiler_state_t *, u_int, int, int),
+    enum e_offrel offrel, bpf_u_int32 vni, int has_vni)
 {
 	struct block *b0, *b1;
 
@@ -8530,14 +9221,17 @@
 	/* Check that we are operating on version 0. Otherwise, we
 	 * can't decode the rest of the fields. The version is 2 bits
 	 * in the first byte of the Geneve header. */
-	b1 = gen_mcmp(cstate, offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
+	b1 = gen_mcmp(cstate, offrel, 8, BPF_B, 0, 0xc0);
 	gen_and(b0, b1);
 	b0 = b1;
 
-	if (vni >= 0) {
+	if (has_vni) {
+		if (vni > 0xffffff) {
+			bpf_error(cstate, "Geneve VNI %u greater than maximum %u",
+			    vni, 0xffffff);
+		}
 		vni <<= 8; /* VNI is in the upper 3 bytes */
-		b1 = gen_mcmp(cstate, offrel, 12, BPF_W, (bpf_int32)vni,
-			      0xffffff00);
+		b1 = gen_mcmp(cstate, offrel, 12, BPF_W, vni, 0xffffff00);
 		gen_and(b0, b1);
 		b0 = b1;
 	}
@@ -8551,12 +9245,12 @@
  *   needed) into register A to be used later to compute
  *   the inner packet offsets. */
 static struct block *
-gen_geneve4(compiler_state_t *cstate, int vni)
+gen_geneve4(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
 {
 	struct block *b0, *b1;
 	struct slist *s, *s1;
 
-	b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni);
+	b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni, has_vni);
 
 	/* Load the IP header length into A. */
 	s = gen_loadx_iphdrlen(cstate);
@@ -8577,12 +9271,12 @@
 }
 
 static struct block *
-gen_geneve6(compiler_state_t *cstate, int vni)
+gen_geneve6(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
 {
 	struct block *b0, *b1;
 	struct slist *s, *s1;
 
-	b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni);
+	b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni, has_vni);
 
 	/* Load the IP header length. We need to account for a
 	 * variable length link prefix if there is one. */
@@ -8755,13 +9449,20 @@
 
 /* Check to see if this is a Geneve packet. */
 struct block *
-gen_geneve(compiler_state_t *cstate, int vni)
+gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
 {
 	struct block *b0, *b1;
 	struct slist *s;
 
-	b0 = gen_geneve4(cstate, vni);
-	b1 = gen_geneve6(cstate, vni);
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	b0 = gen_geneve4(cstate, vni, has_vni);
+	b1 = gen_geneve6(cstate, vni, has_vni);
 
 	gen_or(b0, b1);
 	b0 = b1;
@@ -8811,9 +9512,9 @@
 	return b0;
 }
 
-struct block *
-gen_atmfield_code(compiler_state_t *cstate, int atmfield, bpf_int32 jvalue,
-    bpf_u_int32 jtype, int reverse)
+static struct block *
+gen_atmfield_code_internal(compiler_state_t *cstate, int atmfield,
+    bpf_u_int32 jvalue, int jtype, int reverse)
 {
 	struct block *b0;
 
@@ -8824,8 +9525,8 @@
 			bpf_error(cstate, "'vpi' supported only on raw ATM");
 		if (cstate->off_vpi == OFFSET_NOT_SET)
 			abort();
-		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
-		    reverse, jvalue);
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B,
+		    0xffffffffU, jtype, reverse, jvalue);
 		break;
 
 	case A_VCI:
@@ -8833,22 +9534,22 @@
 			bpf_error(cstate, "'vci' supported only on raw ATM");
 		if (cstate->off_vci == OFFSET_NOT_SET)
 			abort();
-		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
-		    reverse, jvalue);
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H,
+		    0xffffffffU, jtype, reverse, jvalue);
 		break;
 
 	case A_PROTOTYPE:
 		if (cstate->off_proto == OFFSET_NOT_SET)
 			abort();	/* XXX - this isn't on FreeBSD */
-		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
-		    reverse, jvalue);
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B,
+		    0x0fU, jtype, reverse, jvalue);
 		break;
 
 	case A_MSGTYPE:
 		if (cstate->off_payload == OFFSET_NOT_SET)
 			abort();
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
-		    0xffffffff, jtype, reverse, jvalue);
+		    0xffffffffU, jtype, reverse, jvalue);
 		break;
 
 	case A_CALLREFTYPE:
@@ -8856,8 +9557,8 @@
 			bpf_error(cstate, "'callref' supported only on raw ATM");
 		if (cstate->off_proto == OFFSET_NOT_SET)
 			abort();
-		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
-		    jtype, reverse, jvalue);
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B,
+		    0xffffffffU, jtype, reverse, jvalue);
 		break;
 
 	default:
@@ -8866,28 +9567,80 @@
 	return b0;
 }
 
+static struct block *
+gen_atmtype_metac(compiler_state_t *cstate)
+{
+	struct block *b0, *b1;
+
+	b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+	b1 = gen_atmfield_code_internal(cstate, A_VCI, 1, BPF_JEQ, 0);
+	gen_and(b0, b1);
+	return b1;
+}
+
+static struct block *
+gen_atmtype_sc(compiler_state_t *cstate)
+{
+	struct block *b0, *b1;
+
+	b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+	b1 = gen_atmfield_code_internal(cstate, A_VCI, 5, BPF_JEQ, 0);
+	gen_and(b0, b1);
+	return b1;
+}
+
+static struct block *
+gen_atmtype_llc(compiler_state_t *cstate)
+{
+	struct block *b0;
+
+	b0 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+	cstate->linktype = cstate->prevlinktype;
+	return b0;
+}
+
+struct block *
+gen_atmfield_code(compiler_state_t *cstate, int atmfield,
+    bpf_u_int32 jvalue, int jtype, int reverse)
+{
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	return gen_atmfield_code_internal(cstate, atmfield, jvalue, jtype,
+	    reverse);
+}
+
 struct block *
 gen_atmtype_abbrev(compiler_state_t *cstate, int type)
 {
 	struct block *b0, *b1;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (type) {
 
 	case A_METAC:
 		/* Get all packets in Meta signalling Circuit */
 		if (!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);
+		b1 = gen_atmtype_metac(cstate);
 		break;
 
 	case A_BCC:
 		/* Get all packets in Broadcast Circuit*/
 		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);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 2, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -8895,8 +9648,8 @@
 		/* Get all cells in Segment OAM F4 circuit*/
 		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);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -8904,8 +9657,8 @@
 		/* Get all cells in End-to-End OAM F4 Circuit*/
 		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);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -8913,17 +9666,15 @@
 		/*  Get all packets in connection Signalling Circuit */
 		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);
+		b1 = gen_atmtype_sc(cstate);
 		break;
 
 	case A_ILMIC:
 		/* Get all packets in ILMI Circuit */
 		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);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 16, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -8931,7 +9682,7 @@
 		/* Get all LANE packets */
 		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);
+		b1 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
 
 		/*
 		 * Arrange that all subsequent tests assume LANE
@@ -8954,8 +9705,7 @@
 		/* Get all LLC-encapsulated packets */
 		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;
+		b1 = gen_atmtype_llc(cstate);
 		break;
 
 	default:
@@ -8976,6 +9726,13 @@
 {
 	struct block *b0, *b1;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (type) {
 
 	case M_FISU:
@@ -8984,7 +9741,8 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B,
+		    0x3fU, BPF_JEQ, 0, 0U);
 		break;
 
 	case M_LSSU:
@@ -8992,8 +9750,10 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B,
+		    0x3fU, BPF_JGT, 1, 2U);
+		b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B,
+		    0x3fU, BPF_JGT, 0, 0U);
 		gen_and(b1, b0);
 		break;
 
@@ -9002,7 +9762,8 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B,
+		    0x3fU, BPF_JGT, 0, 2U);
 		break;
 
 	case MH_FISU:
@@ -9011,7 +9772,8 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H,
+		    0xff80U, BPF_JEQ, 0, 0U);
 		break;
 
 	case MH_LSSU:
@@ -9019,8 +9781,10 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H,
+		    0xff80U, BPF_JGT, 1, 0x0100U);
+		b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H,
+		    0xff80U, BPF_JGT, 0, 0U);
 		gen_and(b1, b0);
 		break;
 
@@ -9029,7 +9793,8 @@
 		     (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);
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H,
+		    0xff80U, BPF_JGT, 0, 0x0100U);
 		break;
 
 	default:
@@ -9038,17 +9803,34 @@
 	return b0;
 }
 
+/*
+ * The jvalue_arg dance is to avoid annoying whining by compilers that
+ * jvalue might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
 struct block *
-gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, bpf_u_int32 jvalue,
-    bpf_u_int32 jtype, int reverse)
+gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
+    bpf_u_int32 jvalue_arg, int jtype, int reverse)
 {
+	volatile bpf_u_int32 jvalue = jvalue_arg;
 	struct block *b0;
 	bpf_u_int32 val1 , val2 , val3;
-	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;
+	u_int newoff_sio;
+	u_int newoff_opc;
+	u_int newoff_dpc;
+	u_int newoff_sls;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
+	newoff_sio = cstate->off_sio;
+	newoff_opc = cstate->off_opc;
+	newoff_dpc = cstate->off_dpc;
+	newoff_sls = cstate->off_sls;
 	switch (mtp3field) {
 
 	case MH_SIO:
@@ -9062,12 +9844,14 @@
 		if(jvalue > 255)
 		        bpf_error(cstate, "sio value %u too big; max value = 255",
 		            jvalue);
-		b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
-		    (u_int)jtype, reverse, (u_int)jvalue);
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffffU,
+		    jtype, reverse, jvalue);
 		break;
 
 	case MH_OPC:
-		newoff_opc+=3;
+		newoff_opc += 3;
+
+		/* FALLTHROUGH */
         case M_OPC:
 	        if (cstate->off_opc == OFFSET_NOT_SET)
 			bpf_error(cstate, "'opc' supported only on SS7");
@@ -9084,8 +9868,8 @@
 		val3 = jvalue & 0x00000003;
 		val3 = val3 <<22;
 		jvalue = val1 + val2 + val3;
-		b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
-		    (u_int)jtype, reverse, (u_int)jvalue);
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0fU,
+		    jtype, reverse, jvalue);
 		break;
 
 	case MH_DPC:
@@ -9106,12 +9890,14 @@
 		val2 = jvalue & 0x00003f00;
 		val2 = val2 << 8;
 		jvalue = val1 + val2;
-		b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
-		    (u_int)jtype, reverse, (u_int)jvalue);
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000U,
+		    jtype, reverse, jvalue);
 		break;
 
 	case MH_SLS:
-	  newoff_sls+=3;
+		newoff_sls += 3;
+		/* FALLTHROUGH */
+
 	case M_SLS:
 	        if (cstate->off_sls == OFFSET_NOT_SET)
 			bpf_error(cstate, "'sls' supported only on SS7");
@@ -9122,8 +9908,8 @@
 		/* 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(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0,
-		    (u_int)jtype,reverse, (u_int)jvalue);
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0U,
+		    jtype, reverse, jvalue);
 		break;
 
 	default:
@@ -9144,27 +9930,27 @@
 	switch (type) {
 
 	case A_SETUP:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
 		break;
 
 	case A_CALLPROCEED:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
 		break;
 
 	case A_CONNECT:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
 		break;
 
 	case A_CONNECTACK:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
 		break;
 
 	case A_RELEASE:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
 		break;
 
 	case A_RELEASE_DONE:
-		b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
 		break;
 
 	default:
@@ -9178,22 +9964,34 @@
 {
 	struct block *b0, *b1;
 
+	/*
+	 * Catch errors reported by us and routines below us, and return NULL
+	 * on an error.
+	 */
+	if (setjmp(cstate->top_ctx))
+		return (NULL);
+
 	switch (type) {
 
 	case A_OAM:
 		if (!cstate->is_atm)
 			bpf_error(cstate, "'oam' supported only on raw ATM");
-		b1 = gen_atmmulti_abbrev(cstate, A_OAMF4);
+		/* OAM F4 type */
+		b0 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
+		gen_or(b0, b1);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+		gen_and(b0, b1);
 		break;
 
 	case A_OAMF4:
 		if (!cstate->is_atm)
 			bpf_error(cstate, "'oamf4' supported only on raw ATM");
 		/* OAM F4 type */
-		b0 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
+		b0 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+		b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
 		gen_or(b0, b1);
-		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -9215,7 +10013,7 @@
 		gen_or(b0, b1);
 		b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
 		gen_or(b0, b1);
-		b0 = gen_atmtype_abbrev(cstate, A_SC);
+		b0 = gen_atmtype_sc(cstate);
 		gen_and(b0, b1);
 		break;
 
@@ -9231,7 +10029,7 @@
 		gen_or(b0, b1);
 		b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
 		gen_or(b0, b1);
-		b0 = gen_atmtype_abbrev(cstate, A_METAC);
+		b0 = gen_atmtype_metac(cstate);
 		gen_and(b0, b1);
 		break;
 
diff --git a/gencode.h b/gencode.h
index 88def5a..053e85f 100644
--- a/gencode.h
+++ b/gencode.h
@@ -113,16 +113,14 @@
 #define Q_ISIS_L2       32
 /* PDU types */
 #define Q_ISIS_IIH      33
-#define Q_ISIS_LAN_IIH  34
-#define Q_ISIS_PTP_IIH  35
-#define Q_ISIS_SNP      36
-#define Q_ISIS_CSNP     37
-#define Q_ISIS_PSNP     38
-#define Q_ISIS_LSP      39
+#define Q_ISIS_SNP      34
+#define Q_ISIS_CSNP     35
+#define Q_ISIS_PSNP     36
+#define Q_ISIS_LSP      37
 
-#define Q_RADIO		40
+#define Q_RADIO		38
 
-#define Q_CARP		41
+#define Q_CARP		39
 
 /* Directional qualifiers. */
 
@@ -202,11 +200,14 @@
 
 struct slist;
 
+/*
+ * A single statement, corresponding to an instruction in a block.
+ */
 struct stmt {
-	int code;
-	struct slist *jt;	/*only for relative jump in block*/
-	struct slist *jf;	/*only for relative jump in block*/
-	bpf_int32 k;
+	int code;		/* opcode */
+	struct slist *jt;	/* only for relative jump in block */
+	struct slist *jf;	/* only for relative jump in block */
+	bpf_u_int32 k;		/* k field */
 };
 
 struct slist {
@@ -233,17 +234,27 @@
  */
 #define N_ATOMS (BPF_MEMWORDS+2)
 
+/*
+ * Control flow graph of a program.
+ * This corresponds to an edge in the CFG.
+ * It's a directed graph, so an edge has a predecessor and a successor.
+ */
 struct edge {
-	int id;
-	int code;
+	u_int id;
+	int code;		/* opcode for branch corresponding to this edge */
 	uset edom;
-	struct block *succ;
-	struct block *pred;
+	struct block *succ;	/* successor vertex */
+	struct block *pred;	/* predecessor vertex */
 	struct edge *next;	/* link list of incoming edges for a node */
 };
 
+/*
+ * A block is a vertex in the CFG.
+ * It has a list of statements, with the final statement being a
+ * branch to successor blocks.
+ */
 struct block {
-	int id;
+	u_int id;
 	struct slist *stmts;	/* side effect stmts */
 	struct stmt s;		/* branch stmt */
 	int mark;
@@ -252,18 +263,18 @@
 	int level;
 	int offset;
 	int sense;
-	struct edge et;
-	struct edge ef;
+	struct edge et;		/* edge corresponding to the jt branch */
+	struct edge ef;		/* edge corresponding to the jf branch */
 	struct block *head;
 	struct block *link;	/* link field used by optimizer */
 	uset dom;
 	uset closure;
-	struct edge *in_edges;
+	struct edge *in_edges;	/* first edge in the set (linked list) of edges with this as a successor */
 	atomset def, kill;
 	atomset in_use;
 	atomset out_use;
-	int oval;
-	int val[N_ATOMS];
+	int oval;		/* value ID for value tested in branch stmt */
+	bpf_u_int32 val[N_ATOMS];
 };
 
 /*
@@ -288,8 +299,8 @@
 
 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_loadi(compiler_state_t *, bpf_u_int32);
+struct arth *gen_load(compiler_state_t *, int, struct arth *, bpf_u_int32);
 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 *);
@@ -299,13 +310,13 @@
 void gen_not(struct block *);
 
 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_ecode(compiler_state_t *, const char *, struct qual);
+struct block *gen_acode(compiler_state_t *, const char *, struct qual);
 struct block *gen_mcode(compiler_state_t *, const char *, const char *,
-    unsigned int, struct qual);
+    bpf_u_int32, struct qual);
 #ifdef INET6
 struct block *gen_mcode6(compiler_state_t *, const char *, const char *,
-    unsigned int, struct qual);
+    bpf_u_int32, struct qual);
 #endif
 struct block *gen_ncode(compiler_state_t *, const char *, bpf_u_int32,
     struct qual);
@@ -314,9 +325,10 @@
     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_byteop(compiler_state_t *, int, int, bpf_u_int32);
 struct block *gen_broadcast(compiler_state_t *, int);
 struct block *gen_multicast(compiler_state_t *, int);
+struct block *gen_ifindex(compiler_state_t *, int);
 struct block *gen_inbound(compiler_state_t *, int);
 
 struct block *gen_llc(compiler_state_t *);
@@ -326,50 +338,32 @@
 struct block *gen_llc_s_subtype(compiler_state_t *, bpf_u_int32);
 struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
 
-struct block *gen_vlan(compiler_state_t *, int);
-struct block *gen_mpls(compiler_state_t *, int);
+struct block *gen_vlan(compiler_state_t *, bpf_u_int32, int);
+struct block *gen_mpls(compiler_state_t *, bpf_u_int32, int);
 
 struct block *gen_pppoed(compiler_state_t *);
-struct block *gen_pppoes(compiler_state_t *, int);
+struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);
 
-struct block *gen_geneve(compiler_state_t *, int);
+struct block *gen_geneve(compiler_state_t *, bpf_u_int32, int);
 
-struct block *gen_atmfield_code(compiler_state_t *, int, bpf_int32,
-    bpf_u_int32, int);
-struct block *gen_atmtype_abbrev(compiler_state_t *, int type);
-struct block *gen_atmmulti_abbrev(compiler_state_t *, int type);
+struct block *gen_atmfield_code(compiler_state_t *, int, bpf_u_int32,
+    int, int);
+struct block *gen_atmtype_abbrev(compiler_state_t *, int);
+struct block *gen_atmmulti_abbrev(compiler_state_t *, int);
 
-struct block *gen_mtp2type_abbrev(compiler_state_t *, int type);
+struct block *gen_mtp2type_abbrev(compiler_state_t *, int);
 struct block *gen_mtp3field_code(compiler_state_t *, int, bpf_u_int32,
-    bpf_u_int32, int);
+    int, int);
 
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_ifname(compiler_state_t *, const char *);
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_rnr(compiler_state_t *, int);
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_srnr(compiler_state_t *, int);
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_ruleset(compiler_state_t *, char *);
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_reason(compiler_state_t *, int);
-#ifndef HAVE_NET_PFVAR_H
-PCAP_NORETURN
-#endif
 struct block *gen_pf_action(compiler_state_t *, int);
 
-struct block *gen_p80211_type(compiler_state_t *, int, int);
-struct block *gen_p80211_fcdir(compiler_state_t *, int);
+struct block *gen_p80211_type(compiler_state_t *, bpf_u_int32, bpf_u_int32);
+struct block *gen_p80211_fcdir(compiler_state_t *, bpf_u_int32);
 
 /*
  * Representation of a program as a tree of blocks, plus current mark.
@@ -386,16 +380,15 @@
 	int cur_mark;
 };
 
-void bpf_optimize(compiler_state_t *, struct icode *ic);
-void PCAP_NORETURN bpf_syntax_error(compiler_state_t *, const char *);
-void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
+int bpf_optimize(struct icode *, char *);
+void bpf_set_error(compiler_state_t *, const char *, ...)
     PCAP_PRINTFLIKE(2, 3);
 
-void finish_parse(compiler_state_t *, struct block *);
+int finish_parse(compiler_state_t *, struct block *);
 char *sdup(compiler_state_t *, const char *);
 
-struct bpf_insn *icode_to_fcode(compiler_state_t *, struct icode *,
-    struct block *, u_int *);
+struct bpf_insn *icode_to_fcode(struct icode *, struct block *, u_int *,
+    char *);
 void sappend(struct slist *, struct slist *);
 
 /*
diff --git a/grammar.c b/grammar.c
index 2be760b..f7697e2 100644
--- a/grammar.c
+++ b/grammar.c
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.5.1.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 /* Identify Bison output.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.5.1"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -66,9 +70,8 @@
 #define yydebug         pcap_debug
 #define yynerrs         pcap_nerrs
 
-
-/* Copy the first part of user declarations.  */
-#line 26 "grammar.y" /* yacc.c:339  */
+/* First part of user prologue.  */
+#line 26 "grammar.y"
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -262,13 +265,12 @@
 	return (-1);
 }
 
-static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+static const struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
-static PCAP_NORETURN_DEF void
+static void
 yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
 {
-	bpf_syntax_error(cstate, msg);
-	/* NOTREACHED */
+	bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
 #ifdef HAVE_NET_PFVAR_H
@@ -282,8 +284,8 @@
 		if (pcap_strcasecmp(reason, reasons[i]) == 0)
 			return (i);
 	}
-	bpf_error(cstate, "unknown PF reason");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "unknown PF reason");
+	return (-1);
 }
 
 static int
@@ -306,35 +308,54 @@
 		return (PF_NORDR);
 #endif
 	else {
-		bpf_error(cstate, "unknown PF action");
-		/*NOTREACHED*/
+		bpf_set_error(cstate, "unknown PF action");
+		return (-1);
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
-static PCAP_NORETURN_DEF int
+static int
 pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
 {
-	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+	return (-1);
 }
 
-static PCAP_NORETURN_DEF int
+static int
 pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
 {
-	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+	return (-1);
 }
 #endif /* HAVE_NET_PFVAR_H */
 
+/*
+ * For calls that might return an "an error occurred" value.
+ */
+#define CHECK_INT_VAL(val)	if (val == -1) YYABORT
+#define CHECK_PTR_VAL(val)	if (val == NULL) YYABORT
+
 DIAG_OFF_BISON_BYACC
 
-#line 332 "grammar.c" /* yacc.c:339  */
+#line 340 "grammar.c"
 
-# ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
+# ifndef YY_CAST
+#  ifdef __cplusplus
+#   define YY_CAST(Type, Val) static_cast<Type> (Val)
+#   define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
 #  else
-#   define YY_NULLPTR 0
+#   define YY_CAST(Type, Val) ((Type) (Val))
+#   define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+#  endif
+# endif
+# ifndef YY_NULLPTR
+#  if defined __cplusplus
+#   if 201103L <= __cplusplus
+#    define YY_NULLPTR nullptr
+#   else
+#    define YY_NULLPTR 0
+#   endif
+#  else
+#   define YY_NULLPTR ((void*)0)
 #  endif
 # endif
 
@@ -346,8 +367,8 @@
 # define YYERROR_VERBOSE 0
 #endif
 
-/* In a future release of Bison, this section will be replaced
-   by #include "grammar.h".  */
+/* Use api.header.include to #include this header
+   instead of duplicating it here.  */
 #ifndef YY_PCAP_GRAMMAR_H_INCLUDED
 # define YY_PCAP_GRAMMAR_H_INCLUDED
 /* Debug traces.  */
@@ -479,9 +500,10 @@
     HOPC = 371,
     HDPC = 372,
     HSLS = 373,
-    OR = 374,
-    AND = 375,
-    UMINUS = 376
+    LEX_ERROR = 374,
+    OR = 375,
+    AND = 376,
+    UMINUS = 377
   };
 #endif
 /* Tokens.  */
@@ -601,20 +623,19 @@
 #define HOPC 371
 #define HDPC 372
 #define HSLS 373
-#define OR 374
-#define AND 375
-#define UMINUS 376
+#define LEX_ERROR 374
+#define OR 375
+#define AND 376
+#define UMINUS 377
 
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
 union YYSTYPE
 {
-#line 286 "grammar.y" /* yacc.c:355  */
+#line 291 "grammar.y"
 
 	int i;
 	bpf_u_int32 h;
-	u_char *e;
 	char *s;
 	struct stmt *stmt;
 	struct arth *a;
@@ -626,9 +647,9 @@
 	} blk;
 	struct block *rblk;
 
-#line 630 "grammar.c" /* yacc.c:355  */
-};
+#line 651 "grammar.c"
 
+};
 typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
@@ -640,36 +661,81 @@
 
 #endif /* !YY_PCAP_GRAMMAR_H_INCLUDED  */
 
-/* Copy the second part of user declarations.  */
 
-#line 646 "grammar.c" /* yacc.c:358  */
 
 #ifdef short
 # undef short
 #endif
 
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+   <limits.h> and (if available) <stdint.h> are included
+   so that the code can choose integer types of a good width.  */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+#  include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+#  define YY_STDINT_H
+# endif
 #endif
 
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+/* Narrow types that promote to a signed type and that can represent a
+   signed or unsigned integer of at least N bits.  In tables they can
+   save space and decrease cache pressure.  Promoting to a signed type
+   helps avoid bugs in integer arithmetic.  */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
 #else
 typedef signed char yytype_int8;
 #endif
 
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
 #else
-typedef unsigned short int yytype_uint16;
+typedef short yytype_int16;
 #endif
 
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
+#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST8_TYPE__ yytype_uint8;
+#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
+       && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
 #else
-typedef short int yytype_int16;
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+       && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+#  define YYPTRDIFF_T __PTRDIFF_TYPE__
+#  define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+#  ifndef ptrdiff_t
+#   include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  endif
+#  define YYPTRDIFF_T ptrdiff_t
+#  define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+#  define YYPTRDIFF_T long
+#  define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
 #endif
 
 #ifndef YYSIZE_T
@@ -677,15 +743,27 @@
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
-#  define YYSIZE_T unsigned int
+#  define YYSIZE_T unsigned
 # endif
 #endif
 
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#define YYSIZE_MAXIMUM                                  \
+  YY_CAST (YYPTRDIFF_T,                                 \
+           (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1)  \
+            ? YYPTRDIFF_MAXIMUM                         \
+            : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int16 yy_state_t;
+
+/* State numbers in computations.  */
+typedef int yy_state_fast_t;
 
 #ifndef YY_
 # if defined YYENABLE_NLS && YYENABLE_NLS
@@ -699,30 +777,19 @@
 # endif
 #endif
 
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__                                               \
-      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
-     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+#ifndef YY_ATTRIBUTE_PURE
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+#  define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
 # else
-#  define YY_ATTRIBUTE(Spec) /* empty */
+#  define YY_ATTRIBUTE_PURE
 # endif
 #endif
 
-#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
-#endif
-
 #ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
-#endif
-
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+#  define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 # else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+#  define YY_ATTRIBUTE_UNUSED
 # endif
 #endif
 
@@ -733,13 +800,13 @@
 # define YYUSE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                            \
+    _Pragma ("GCC diagnostic push")                                     \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")              \
     _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END      \
     _Pragma ("GCC diagnostic pop")
 #else
 # define YY_INITIAL_VALUE(Value) Value
@@ -752,6 +819,20 @@
 # define YY_INITIAL_VALUE(Value) /* Nothing. */
 #endif
 
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN                          \
+    _Pragma ("GCC diagnostic push")                            \
+    _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END            \
+    _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
+
+#define YY_ASSERT(E) ((void) (0 && (E)))
 
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
@@ -828,17 +909,17 @@
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss_alloc;
+  yy_state_t yyss_alloc;
   YYSTYPE yyvs_alloc;
 };
 
 /* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
 
 /* The size of an array large to enough to hold all stacks, each with
    N elements.  */
 # define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+     ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
 # define YYCOPY_NEEDED 1
@@ -851,11 +932,11 @@
 # define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
     do                                                                  \
       {                                                                 \
-        YYSIZE_T yynewbytes;                                            \
+        YYPTRDIFF_T yynewbytes;                                         \
         YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
         Stack = &yyptr->Stack_alloc;                                    \
-        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-        yyptr += yynewbytes / sizeof (*yyptr);                          \
+        yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / YYSIZEOF (*yyptr);                        \
       }                                                                 \
     while (0)
 
@@ -867,12 +948,12 @@
 # ifndef YYCOPY
 #  if defined __GNUC__ && 1 < __GNUC__
 #   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+      __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
 #  else
 #   define YYCOPY(Dst, Src, Count)              \
       do                                        \
         {                                       \
-          YYSIZE_T yyi;                         \
+          YYPTRDIFF_T yyi;                      \
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
@@ -884,10 +965,10 @@
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   788
+#define YYLAST   775
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  139
+#define YYNTOKENS  140
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  47
 /* YYNRULES -- Number of rules.  */
@@ -895,31 +976,32 @@
 /* YYNSTATES -- Number of states.  */
 #define YYNSTATES  294
 
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   376
+#define YYMAXUTOK   377
 
+
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
 #define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+  (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
+   as returned by yylex.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,   121,     2,     2,     2,   137,   123,     2,
-     130,   129,   126,   124,     2,   125,     2,   127,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,   136,     2,
-     133,   132,   131,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,   122,     2,     2,     2,   138,   124,     2,
+     131,   130,   127,   125,     2,   126,     2,   128,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,   137,     2,
+     134,   133,   132,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,   134,     2,   135,   138,     2,     2,     2,     2,     2,
+       2,   135,     2,   136,   139,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,   122,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,   123,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -944,36 +1026,36 @@
       85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
       95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
      105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
-     115,   116,   117,   118,   119,   120,   128
+     115,   116,   117,   118,   119,   120,   121,   129
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
+static const yytype_int16 yyrline[] =
 {
-       0,   360,   360,   364,   366,   368,   369,   370,   371,   372,
-     374,   376,   378,   379,   381,   383,   384,   386,   388,   401,
-     410,   419,   428,   437,   439,   441,   443,   444,   445,   447,
-     449,   451,   452,   454,   455,   456,   457,   458,   459,   461,
-     462,   463,   464,   466,   468,   469,   470,   471,   472,   473,
-     476,   477,   480,   481,   482,   483,   484,   485,   486,   487,
-     488,   489,   490,   491,   494,   495,   496,   497,   500,   502,
-     503,   504,   505,   506,   507,   508,   509,   510,   511,   512,
-     513,   514,   515,   516,   517,   518,   519,   520,   521,   522,
-     523,   524,   525,   526,   527,   528,   529,   530,   531,   532,
-     533,   534,   535,   536,   537,   538,   539,   540,   542,   543,
-     544,   545,   546,   547,   548,   549,   550,   551,   552,   553,
-     554,   555,   556,   557,   558,   559,   560,   563,   564,   565,
-     566,   567,   568,   571,   576,   579,   583,   586,   587,   593,
-     594,   614,   630,   631,   652,   655,   656,   669,   670,   673,
-     676,   677,   678,   680,   681,   682,   684,   685,   687,   688,
-     689,   690,   691,   692,   693,   694,   695,   696,   697,   698,
-     699,   700,   701,   703,   704,   705,   706,   707,   709,   710,
-     712,   713,   714,   715,   716,   717,   718,   720,   721,   722,
-     723,   726,   727,   729,   730,   731,   732,   734,   741,   742,
-     745,   746,   747,   748,   749,   750,   753,   754,   755,   756,
-     757,   758,   759,   760,   762,   763,   764,   765,   767,   780,
-     781
+       0,   362,   362,   366,   368,   370,   371,   372,   373,   374,
+     376,   378,   380,   381,   383,   385,   386,   388,   390,   409,
+     420,   431,   432,   433,   435,   437,   439,   440,   441,   443,
+     445,   447,   448,   450,   451,   452,   453,   454,   462,   464,
+     465,   466,   467,   469,   471,   472,   473,   474,   475,   476,
+     479,   480,   483,   484,   485,   486,   487,   488,   489,   490,
+     491,   492,   493,   494,   497,   498,   499,   500,   503,   505,
+     506,   507,   508,   509,   510,   511,   512,   513,   514,   515,
+     516,   517,   518,   519,   520,   521,   522,   523,   524,   525,
+     526,   527,   528,   529,   530,   531,   532,   533,   534,   535,
+     536,   537,   538,   539,   540,   541,   542,   543,   545,   546,
+     547,   548,   549,   550,   551,   552,   553,   554,   555,   556,
+     557,   558,   559,   560,   561,   562,   563,   566,   567,   568,
+     569,   570,   571,   574,   579,   582,   586,   589,   590,   599,
+     600,   623,   640,   641,   665,   668,   669,   685,   686,   689,
+     692,   693,   694,   696,   697,   698,   700,   701,   703,   704,
+     705,   706,   707,   708,   709,   710,   711,   712,   713,   714,
+     715,   716,   717,   719,   720,   721,   722,   723,   725,   726,
+     728,   729,   730,   731,   732,   733,   734,   736,   737,   738,
+     739,   742,   743,   745,   746,   747,   748,   750,   757,   758,
+     761,   762,   763,   764,   765,   766,   769,   770,   771,   772,
+     773,   774,   775,   776,   778,   779,   780,   781,   783,   796,
+     797
 };
 #endif
 
@@ -996,23 +1078,23 @@
   "NETBEUI", "LANE", "LLC", "METAC", "BCC", "SC", "ILMIC", "OAMF4EC",
   "OAMF4SC", "OAM", "OAMF4", "CONNECTMSG", "METACONNECT", "VPI", "VCI",
   "RADIO", "FISU", "LSSU", "MSU", "HFISU", "HLSSU", "HMSU", "SIO", "OPC",
-  "DPC", "SLS", "HSIO", "HOPC", "HDPC", "HSLS", "OR", "AND", "'!'", "'|'",
-  "'&'", "'+'", "'-'", "'*'", "'/'", "UMINUS", "')'", "'('", "'>'", "'='",
-  "'<'", "'['", "']'", "':'", "'%'", "'^'", "$accept", "prog", "null",
-  "expr", "and", "or", "id", "nid", "not", "paren", "pid", "qid", "term",
-  "head", "rterm", "pqual", "dqual", "aqual", "ndaqual", "pname", "other",
-  "pfvar", "p80211", "type", "subtype", "type_subtype", "pllc", "dir",
-  "reason", "action", "relop", "irelop", "arth", "narth", "byteop", "pnum",
-  "atmtype", "atmmultitype", "atmfield", "atmvalue", "atmfieldvalue",
-  "atmlistvalue", "mtp2type", "mtp3field", "mtp3value", "mtp3fieldvalue",
-  "mtp3listvalue", YY_NULLPTR
+  "DPC", "SLS", "HSIO", "HOPC", "HDPC", "HSLS", "LEX_ERROR", "OR", "AND",
+  "'!'", "'|'", "'&'", "'+'", "'-'", "'*'", "'/'", "UMINUS", "')'", "'('",
+  "'>'", "'='", "'<'", "'['", "']'", "':'", "'%'", "'^'", "$accept",
+  "prog", "null", "expr", "and", "or", "id", "nid", "not", "paren", "pid",
+  "qid", "term", "head", "rterm", "pqual", "dqual", "aqual", "ndaqual",
+  "pname", "other", "pfvar", "p80211", "type", "subtype", "type_subtype",
+  "pllc", "dir", "reason", "action", "relop", "irelop", "arth", "narth",
+  "byteop", "pnum", "atmtype", "atmmultitype", "atmfield", "atmvalue",
+  "atmfieldvalue", "atmlistvalue", "mtp2type", "mtp3field", "mtp3value",
+  "mtp3fieldvalue", "mtp3listvalue", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
 /* YYTOKNUM[NUM] -- (External) token number corresponding to the
    (internal) symbol number NUM (which must be that of a token).  */
-static const yytype_uint16 yytoknum[] =
+static const yytype_int16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
@@ -1026,55 +1108,55 @@
      345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
      355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
      365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
-     375,    33,   124,    38,    43,    45,    42,    47,   376,    41,
-      40,    62,    61,    60,    91,    93,    58,    37,    94
+     375,   376,    33,   124,    38,    43,    45,    42,    47,   377,
+      41,    40,    62,    61,    60,    91,    93,    58,    37,    94
 };
 # endif
 
-#define YYPACT_NINF -216
+#define YYPACT_NINF (-216)
 
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-216)))
+#define yypact_value_is_default(Yyn) \
+  ((Yyn) == YYPACT_NINF)
 
-#define YYTABLE_NINF -42
+#define YYTABLE_NINF (-42)
 
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yyn) \
   0
 
   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
      STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
-    -216,    24,   257,  -216,     0,    12,    17,  -216,  -216,  -216,
+    -216,    32,   257,  -216,    -1,    12,    28,  -216,  -216,  -216,
     -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
-    -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,    16,
-      25,    29,    72,   -18,    55,  -216,  -216,  -216,  -216,  -216,
-    -216,   -25,   -25,  -216,   -25,   -25,  -216,  -216,  -216,  -216,
+    -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,    25,
+      37,    31,    43,   -25,    48,  -216,  -216,  -216,  -216,  -216,
+    -216,   -36,   -36,  -216,   -36,   -36,  -216,  -216,  -216,  -216,
     -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
     -216,   -24,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
     -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
     -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
-     604,  -216,   -30,   489,   489,  -216,   125,  -216,   734,     3,
-    -216,  -216,  -216,   183,  -216,  -216,  -216,  -216,    -5,  -216,
-      39,  -216,  -216,   -54,  -216,  -216,  -216,  -216,  -216,  -216,
-    -216,  -216,  -216,   -25,  -216,  -216,  -216,  -216,  -216,  -216,
-     604,   -16,  -108,  -216,  -216,   373,   373,  -216,  -103,   -10,
-       2,  -216,  -216,    -7,    11,  -216,  -216,  -216,   125,   125,
-    -216,    -3,    21,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
-    -216,  -216,   -12,    77,    -9,  -216,  -216,  -216,  -216,  -216,
-    -216,    78,  -216,  -216,  -216,   604,  -216,  -216,  -216,   604,
-     604,   604,   604,   604,   604,   604,   604,  -216,  -216,  -216,
-     604,   604,   604,   604,  -216,   111,   113,   114,  -216,  -216,
-    -216,   115,   124,   126,  -216,  -216,  -216,  -216,  -216,  -216,
-    -216,   131,     2,   575,  -216,   373,   373,  -216,    10,  -216,
-    -216,  -216,  -216,  -216,   112,   137,   138,  -216,  -216,    47,
-     -30,     2,   173,   176,   178,   186,  -216,  -216,   143,  -216,
-    -216,  -216,  -216,  -216,  -216,   127,   -64,   -64,   580,   598,
-    -104,  -104,  -108,  -108,   575,   575,   575,   575,  -216,   -98,
-    -216,  -216,  -216,   -47,  -216,  -216,  -216,   -49,  -216,  -216,
-    -216,  -216,   125,   125,  -216,  -216,  -216,  -216,    -1,  -216,
-     156,  -216,   111,  -216,   115,  -216,  -216,  -216,  -216,  -216,
-      59,  -216,  -216,  -216
+     607,  -216,    54,   491,   491,  -216,   -34,  -216,   721,     2,
+    -216,  -216,  -216,   105,  -216,  -216,  -216,  -216,    17,  -216,
+      21,  -216,  -216,    33,  -216,  -216,  -216,  -216,  -216,  -216,
+    -216,  -216,  -216,   -36,  -216,  -216,  -216,  -216,  -216,  -216,
+     607,     6,    38,  -216,  -216,   374,   374,  -216,  -100,   -20,
+      29,  -216,  -216,    11,     8,  -216,  -216,  -216,   -34,   -34,
+    -216,    60,    65,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
+    -216,  -216,    -6,   109,     1,  -216,  -216,  -216,  -216,  -216,
+    -216,    80,  -216,  -216,  -216,   607,  -216,  -216,  -216,   607,
+     607,   607,   607,   607,   607,   607,   607,  -216,  -216,  -216,
+     607,   607,   607,   607,  -216,   127,   135,   147,  -216,  -216,
+    -216,   156,   157,   158,  -216,  -216,  -216,  -216,  -216,  -216,
+    -216,   159,    29,   181,  -216,   374,   374,  -216,    10,  -216,
+    -216,  -216,  -216,  -216,   136,   161,   162,  -216,  -216,    74,
+      54,    29,   201,   202,   204,   205,  -216,  -216,   163,  -216,
+    -216,  -216,  -216,  -216,  -216,    64,   -56,   -56,   578,   582,
+     -77,   -77,    38,    38,   181,   181,   181,   181,  -216,   -97,
+    -216,  -216,  -216,   -83,  -216,  -216,  -216,   -54,  -216,  -216,
+    -216,  -216,   -34,   -34,  -216,  -216,  -216,  -216,     4,  -216,
+     172,  -216,   127,  -216,   156,  -216,  -216,  -216,  -216,  -216,
+      75,  -216,  -216,  -216
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -1117,11 +1199,11 @@
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -216,  -216,  -216,   193,   -34,  -215,   -90,  -135,     7,    -2,
-    -216,  -216,   -80,  -216,  -216,  -216,  -216,    26,  -216,     9,
+    -216,  -216,  -216,   210,   -15,  -215,   -90,  -135,     7,    -2,
+    -216,  -216,   -80,  -216,  -216,  -216,  -216,    45,  -216,     9,
     -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,  -216,
-     -43,     5,   -26,   -92,  -216,   -37,  -216,  -216,  -216,  -216,
-    -175,  -216,  -216,  -216,  -216,  -174,  -216
+      50,    63,   -66,   -78,  -216,   -37,  -216,  -216,  -216,  -216,
+    -178,  -216,  -216,  -216,  -216,  -179,  -216
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
@@ -1139,175 +1221,173 @@
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
-      94,   224,   139,   -41,   124,   125,   146,   126,   127,    93,
-     -13,    99,    26,   137,   228,   273,   133,   134,   128,   118,
-     258,   133,   185,   186,     3,   236,   221,   262,   241,   190,
-     191,   281,   194,   190,   191,   129,   287,   111,   139,   123,
-     123,   119,   123,   123,   282,   214,   219,   237,   284,   112,
-     242,   176,   177,   178,   113,   217,   220,   140,   288,   150,
-     183,   184,   185,   186,   132,   196,   116,   202,   206,   207,
-     -29,   -29,   133,   190,   191,   114,   200,   208,   209,   210,
-     223,   228,   283,   153,   115,   155,   212,   156,   157,   133,
-     134,    94,    94,   140,   149,   176,   177,   178,   218,   218,
-      93,    93,    99,    99,   213,    91,   195,   291,   201,   117,
-     292,   150,   231,   197,   121,   203,   232,   233,   175,   222,
-     225,   123,   -41,   -41,   139,    91,   187,   188,   189,   -13,
-     -13,   223,   -41,   216,   216,   137,   239,   175,   226,   -13,
-     234,   235,   215,   215,    99,    99,   149,   123,   194,   245,
-     260,   261,   200,   246,   247,   248,   249,   250,   251,   252,
-     253,   264,    26,   265,   254,   255,   256,   257,   266,    91,
-     187,   188,   189,   268,   269,   270,   271,   274,   218,   267,
-     275,   276,   285,   286,   141,   142,   143,   144,   145,   277,
-     278,   179,   180,   290,   293,    92,   272,   244,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   216,    94,     0,     0,     0,     0,     0,
-       0,     0,   215,   215,    99,    99,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   150,   150,     0,     0,   176,
-     177,   178,     0,     0,     0,     0,    89,   179,   180,   181,
-     182,   183,   184,   185,   186,    91,     0,    -3,     0,     0,
-       0,     0,   279,   280,   190,   191,     0,     0,     4,     5,
+      94,    26,   -41,    26,   124,   125,   146,   126,   127,    93,
+     -13,    99,   118,   137,   228,   273,   139,   258,   128,   224,
+     133,   134,   262,   133,   132,   141,   142,   143,   144,   145,
+     221,   236,     3,   281,   119,   129,   111,   133,   241,   123,
+     123,   287,   123,   123,   282,   214,   219,   283,   284,   112,
+     185,   186,   139,   237,   194,   217,   220,   140,   200,   150,
+     242,   190,   191,   288,   213,   113,   -29,   -29,   116,   183,
+     184,   185,   186,   176,   177,   178,   223,   176,   177,   178,
+     117,   228,   190,   191,   114,   153,   212,   155,    89,   156,
+     157,    94,    94,   140,   149,    91,   115,    91,   218,   218,
+      93,    93,    99,    99,   291,   292,   195,   121,   201,   245,
+     222,   150,   231,   246,   247,   248,   249,   250,   251,   252,
+     253,   123,   -41,   -41,   254,   255,   256,   257,   179,   180,
+     -13,   -13,   -41,   216,   216,   137,   226,   175,   139,   225,
+     -13,   175,   215,   215,    99,    99,   149,   123,    91,   187,
+     188,   189,    91,   187,   188,   189,   206,   207,   196,   223,
+     202,   176,   177,   178,   194,   208,   209,   210,   239,   179,
+     180,   197,   260,   203,   133,   134,   190,   191,   218,   267,
+     232,   233,   285,   286,   261,   234,   235,   181,   182,   183,
+     184,   185,   186,   200,   264,   265,   266,   268,   269,   270,
+     279,   280,   190,   191,   271,   274,   275,   276,   277,   290,
+     278,   293,    92,   216,    94,   272,   244,     0,     0,     0,
+       0,     0,   215,   215,    99,    99,     0,     0,   181,   182,
+     183,   184,   185,   186,     0,   150,   150,   187,   188,   189,
+       0,     0,     0,   190,   191,   179,   180,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    -3,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     4,     5,
      149,   149,     6,     7,     8,     9,    10,    11,    12,    13,
       14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
       24,    25,     0,     0,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,     0,     0,   181,   182,   183,   184,   185,
-     186,     0,    35,     0,   187,   188,   189,     0,     0,     0,
-     190,   191,     0,    36,    37,    38,    39,    40,    41,    42,
+      32,    33,    34,     0,   181,   182,   183,   184,   185,   186,
+       0,     0,    35,     0,     0,     0,     0,     0,     0,   190,
+     191,     0,     0,    36,    37,    38,    39,    40,    41,    42,
       43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
       53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
       63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
       73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
-      83,    84,    85,    86,    87,    88,     0,     0,    89,     0,
-       0,     0,    90,     0,     4,     5,     0,    91,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,     0,     0,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    35,     0,
-       0,     0,   141,   142,   143,   144,   145,     0,     0,    36,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
-      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
-      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
-      87,    88,     0,     0,    89,     0,     0,     0,    90,     0,
-       4,     5,     0,    91,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,     0,     0,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    35,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
-      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,     0,     0,
-      89,     0,     0,     0,    90,     0,     0,     0,     0,    91,
+      83,    84,    85,    86,    87,    88,     0,     0,     0,    89,
+       0,     0,     0,    90,     0,     4,     5,     0,    91,     6,
        7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,   179,
-     180,    26,     0,     0,   179,   180,     0,     0,     0,     0,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,     0,
+       0,    26,    27,    28,    29,    30,    31,    32,    33,    34,
        0,     0,     0,     0,     0,     0,     0,     0,     0,    35,
-       0,     0,   179,   180,     0,     0,     0,     0,     0,     0,
-      36,    37,    38,    39,    40,     0,     0,     0,     0,     0,
+       0,     0,     0,   141,   142,   143,   144,   145,     0,     0,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
       46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
-      56,    57,    58,    59,     0,     0,     0,   181,   182,   183,
-     184,   185,   186,   182,   183,   184,   185,   186,    74,     0,
-       0,     0,   190,   191,     0,     0,     0,   190,   191,     0,
-       0,     0,   183,   184,   185,   186,     0,     0,     0,    90,
-       0,     0,     0,     0,    91,   190,   191,   151,   152,   153,
-     154,   155,     0,   156,   157,     0,     0,   158,   159,     0,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+      86,    87,    88,     0,     0,     0,    89,     0,     0,     0,
+      90,     0,     4,     5,     0,    91,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,     0,     0,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    35,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
+       0,     0,     0,    89,     0,     0,     0,    90,     0,     0,
+       0,     0,    91,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,   179,   180,    26,     0,   179,   180,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   160,
-     161,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     162,   163,   164,   165,   166,   167,   168,   169,   170
+       0,     0,    35,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    36,    37,    38,    39,    40,     0,     0,
+       0,     0,     0,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,     0,     0,     0,
+       0,     0,   182,   183,   184,   185,   186,   183,   184,   185,
+     186,    74,     0,     0,     0,     0,   190,   191,     0,     0,
+     190,   191,     0,     0,   151,   152,   153,   154,   155,     0,
+     156,   157,     0,    90,   158,   159,     0,     0,    91,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   160,   161,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   162,   163,   164,
+     165,   166,   167,   168,   169,   170
 };
 
 static const yytype_int16 yycheck[] =
 {
-       2,     8,    94,     0,    41,    42,    96,    44,    45,     2,
-       0,     2,    37,    93,   149,   230,   119,   120,    42,    37,
-     195,   119,   126,   127,     0,    37,   129,   201,    37,   137,
-     138,   129,    37,   137,   138,    59,    37,    37,   130,    41,
-      42,    59,    44,    45,   259,   135,   136,    59,   263,    37,
-      59,    56,    57,    58,    37,   135,   136,    94,    59,    96,
-     124,   125,   126,   127,    90,   108,    37,   110,   122,   123,
-     119,   120,   119,   137,   138,    59,    37,   131,   132,   133,
-     129,   216,   129,     5,    59,     7,   123,     9,    10,   119,
-     120,    93,    94,   130,    96,    56,    57,    58,   135,   136,
-      93,    94,    93,    94,   130,   130,   108,   282,   110,    37,
-     284,   148,   149,   108,    59,   110,   119,   120,   134,   129,
-     127,   123,   119,   120,   216,   130,   131,   132,   133,   119,
-     120,   129,   129,   135,   136,   215,    59,   134,   127,   129,
-     119,   120,   135,   136,   135,   136,   148,   149,    37,   175,
-      37,    37,    37,   179,   180,   181,   182,   183,   184,   185,
-     186,    37,    37,    37,   190,   191,   192,   193,    37,   130,
-     131,   132,   133,    61,    37,    37,   129,     4,   215,   216,
-       4,     3,   272,   273,    59,    60,    61,    62,    63,     3,
-      47,    64,    65,    37,   135,     2,   230,   171,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   215,   216,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   215,   216,   215,   216,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   272,   273,    -1,    -1,    56,
-      57,    58,    -1,    -1,    -1,    -1,   121,    64,    65,   122,
-     123,   124,   125,   126,   127,   130,    -1,     0,    -1,    -1,
-      -1,    -1,   135,   136,   137,   138,    -1,    -1,    11,    12,
+       2,    37,     0,    37,    41,    42,    96,    44,    45,     2,
+       0,     2,    37,    93,   149,   230,    94,   195,    42,     8,
+     120,   121,   201,   120,    90,    59,    60,    61,    62,    63,
+     130,    37,     0,   130,    59,    59,    37,   120,    37,    41,
+      42,    37,    44,    45,   259,   135,   136,   130,   263,    37,
+     127,   128,   130,    59,    37,   135,   136,    94,    37,    96,
+      59,   138,   139,    59,   130,    37,   120,   121,    37,   125,
+     126,   127,   128,    56,    57,    58,   130,    56,    57,    58,
+      37,   216,   138,   139,    59,     5,   123,     7,   122,     9,
+      10,    93,    94,   130,    96,   131,    59,   131,   135,   136,
+      93,    94,    93,    94,   282,   284,   108,    59,   110,   175,
+     130,   148,   149,   179,   180,   181,   182,   183,   184,   185,
+     186,   123,   120,   121,   190,   191,   192,   193,    64,    65,
+     120,   121,   130,   135,   136,   215,   128,   135,   216,   128,
+     130,   135,   135,   136,   135,   136,   148,   149,   131,   132,
+     133,   134,   131,   132,   133,   134,   123,   124,   108,   130,
+     110,    56,    57,    58,    37,   132,   133,   134,    59,    64,
+      65,   108,    37,   110,   120,   121,   138,   139,   215,   216,
+     120,   121,   272,   273,    37,   120,   121,   123,   124,   125,
+     126,   127,   128,    37,    37,    37,    37,    61,    37,    37,
+     136,   137,   138,   139,   130,     4,     4,     3,     3,    37,
+      47,   136,     2,   215,   216,   230,   171,    -1,    -1,    -1,
+      -1,    -1,   215,   216,   215,   216,    -1,    -1,   123,   124,
+     125,   126,   127,   128,    -1,   272,   273,   132,   133,   134,
+      -1,    -1,    -1,   138,   139,    64,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,     0,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    11,    12,
      272,   273,    15,    16,    17,    18,    19,    20,    21,    22,
       23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
       33,    34,    -1,    -1,    37,    38,    39,    40,    41,    42,
-      43,    44,    45,    -1,    -1,   122,   123,   124,   125,   126,
-     127,    -1,    55,    -1,   131,   132,   133,    -1,    -1,    -1,
-     137,   138,    -1,    66,    67,    68,    69,    70,    71,    72,
+      43,    44,    45,    -1,   123,   124,   125,   126,   127,   128,
+      -1,    -1,    55,    -1,    -1,    -1,    -1,    -1,    -1,   138,
+     139,    -1,    -1,    66,    67,    68,    69,    70,    71,    72,
       73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
       83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
       93,    94,    95,    96,    97,    98,    99,   100,   101,   102,
      103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
-     113,   114,   115,   116,   117,   118,    -1,    -1,   121,    -1,
-      -1,    -1,   125,    -1,    11,    12,    -1,   130,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    -1,    -1,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,    -1,
-      -1,    -1,    59,    60,    61,    62,    63,    -1,    -1,    66,
-      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
-      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
-      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
-      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
-     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   118,    -1,    -1,   121,    -1,    -1,    -1,   125,    -1,
-      11,    12,    -1,   130,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    -1,    -1,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
-      91,    92,    93,    94,    95,    96,    97,    98,    99,   100,
-     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
-     111,   112,   113,   114,   115,   116,   117,   118,    -1,    -1,
-     121,    -1,    -1,    -1,   125,    -1,    -1,    -1,    -1,   130,
+     113,   114,   115,   116,   117,   118,    -1,    -1,    -1,   122,
+      -1,    -1,    -1,   126,    -1,    11,    12,    -1,   131,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    64,
-      65,    37,    -1,    -1,    64,    65,    -1,    -1,    -1,    -1,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    -1,
+      -1,    37,    38,    39,    40,    41,    42,    43,    44,    45,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,
-      -1,    -1,    64,    65,    -1,    -1,    -1,    -1,    -1,    -1,
-      66,    67,    68,    69,    70,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    59,    60,    61,    62,    63,    -1,    -1,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
       76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
-      86,    87,    88,    89,    -1,    -1,    -1,   122,   123,   124,
-     125,   126,   127,   123,   124,   125,   126,   127,   104,    -1,
-      -1,    -1,   137,   138,    -1,    -1,    -1,   137,   138,    -1,
-      -1,    -1,   124,   125,   126,   127,    -1,    -1,    -1,   125,
-      -1,    -1,    -1,    -1,   130,   137,   138,     3,     4,     5,
-       6,     7,    -1,     9,    10,    -1,    -1,    13,    14,    -1,
+      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
+      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,   111,   112,   113,   114,   115,
+     116,   117,   118,    -1,    -1,    -1,   122,    -1,    -1,    -1,
+     126,    -1,    11,    12,    -1,   131,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    -1,    -1,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    55,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
+      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
+      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
+     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
+      -1,    -1,    -1,   122,    -1,    -1,    -1,   126,    -1,    -1,
+      -1,    -1,   131,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    64,    65,    37,    -1,    64,    65,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    35,
-      36,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      46,    47,    48,    49,    50,    51,    52,    53,    54
+      -1,    -1,    55,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    66,    67,    68,    69,    70,    -1,    -1,
+      -1,    -1,    -1,    76,    77,    78,    79,    80,    81,    82,
+      83,    84,    85,    86,    87,    88,    89,    -1,    -1,    -1,
+      -1,    -1,   124,   125,   126,   127,   128,   125,   126,   127,
+     128,   104,    -1,    -1,    -1,    -1,   138,   139,    -1,    -1,
+     138,   139,    -1,    -1,     3,     4,     5,     6,     7,    -1,
+       9,    10,    -1,   126,    13,    14,    -1,    -1,   131,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    35,    36,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    46,    47,    48,
+      49,    50,    51,    52,    53,    54
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,   140,   141,     0,    11,    12,    15,    16,    17,    18,
+       0,   141,   142,     0,    11,    12,    15,    16,    17,    18,
       19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
       29,    30,    31,    32,    33,    34,    37,    38,    39,    40,
       41,    42,    43,    44,    45,    55,    66,    67,    68,    69,
@@ -1315,60 +1395,60 @@
       80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
       90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
      100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   121,
-     125,   130,   142,   147,   148,   151,   152,   153,   154,   158,
-     159,   160,   165,   171,   172,   174,   175,   176,   177,   181,
-     182,    37,    37,    37,    59,    59,    37,    37,    37,    59,
-     167,    59,   168,   148,   174,   174,   174,   174,    42,    59,
-     148,   158,   171,   119,   120,   143,   144,   151,   142,   172,
-     174,    59,    60,    61,    62,    63,   145,   146,   147,   148,
-     174,     3,     4,     5,     6,     7,     9,    10,    13,    14,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   122,
+     126,   131,   143,   148,   149,   152,   153,   154,   155,   159,
+     160,   161,   166,   172,   173,   175,   176,   177,   178,   182,
+     183,    37,    37,    37,    59,    59,    37,    37,    37,    59,
+     168,    59,   169,   149,   175,   175,   175,   175,    42,    59,
+     149,   159,   172,   120,   121,   144,   145,   152,   143,   173,
+     175,    59,    60,    61,    62,    63,   146,   147,   148,   149,
+     175,     3,     4,     5,     6,     7,     9,    10,    13,    14,
       35,    36,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,   155,   156,   157,   161,   134,    56,    57,    58,    64,
-      65,   122,   123,   124,   125,   126,   127,   131,   132,   133,
-     137,   138,   169,   170,    37,   148,   169,   170,   178,   179,
-      37,   148,   169,   170,   183,   184,   122,   123,   131,   132,
-     133,   173,   174,   171,   145,   147,   148,   151,   174,   145,
-     151,   129,   129,   129,     8,   127,   127,   145,   146,   149,
-     150,   174,   119,   120,   119,   120,    37,    59,   162,    59,
-     164,    37,    59,   166,   156,   171,   171,   171,   171,   171,
-     171,   171,   171,   171,   171,   171,   171,   171,   179,   180,
-      37,    37,   184,   185,    37,    37,    37,   174,    61,    37,
-      37,   129,   143,   144,     4,     4,     3,     3,    47,   135,
-     136,   129,   144,   129,   144,   145,   145,    37,    59,   163,
-      37,   179,   184,   135
+      54,   156,   157,   158,   162,   135,    56,    57,    58,    64,
+      65,   123,   124,   125,   126,   127,   128,   132,   133,   134,
+     138,   139,   170,   171,    37,   149,   170,   171,   179,   180,
+      37,   149,   170,   171,   184,   185,   123,   124,   132,   133,
+     134,   174,   175,   172,   146,   148,   149,   152,   175,   146,
+     152,   130,   130,   130,     8,   128,   128,   146,   147,   150,
+     151,   175,   120,   121,   120,   121,    37,    59,   163,    59,
+     165,    37,    59,   167,   157,   172,   172,   172,   172,   172,
+     172,   172,   172,   172,   172,   172,   172,   172,   180,   181,
+      37,    37,   185,   186,    37,    37,    37,   175,    61,    37,
+      37,   130,   144,   145,     4,     4,     3,     3,    47,   136,
+     137,   130,   145,   130,   145,   146,   146,    37,    59,   164,
+      37,   180,   185,   136
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,   139,   140,   140,   141,   142,   142,   142,   142,   142,
-     143,   144,   145,   145,   145,   146,   146,   146,   146,   146,
-     146,   146,   146,   146,   147,   148,   149,   149,   149,   150,
-     150,   151,   151,   152,   152,   152,   152,   152,   152,   153,
-     153,   153,   153,   153,   153,   153,   153,   153,   153,   153,
-     154,   154,   155,   155,   155,   155,   155,   155,   155,   155,
-     155,   155,   155,   155,   156,   156,   156,   156,   157,   158,
-     158,   158,   158,   158,   158,   158,   158,   158,   158,   158,
-     158,   158,   158,   158,   158,   158,   158,   158,   158,   158,
-     158,   158,   158,   158,   158,   158,   158,   158,   158,   158,
-     158,   158,   158,   158,   158,   158,   158,   158,   159,   159,
+       0,   140,   141,   141,   142,   143,   143,   143,   143,   143,
+     144,   145,   146,   146,   146,   147,   147,   147,   147,   147,
+     147,   147,   147,   147,   148,   149,   150,   150,   150,   151,
+     151,   152,   152,   153,   153,   153,   153,   153,   153,   154,
+     154,   154,   154,   154,   154,   154,   154,   154,   154,   154,
+     155,   155,   156,   156,   156,   156,   156,   156,   156,   156,
+     156,   156,   156,   156,   157,   157,   157,   157,   158,   159,
      159,   159,   159,   159,   159,   159,   159,   159,   159,   159,
-     159,   159,   159,   159,   159,   159,   159,   160,   160,   160,
-     160,   160,   160,   161,   161,   161,   161,   162,   162,   163,
-     163,   164,   165,   165,   165,   166,   166,   167,   167,   168,
-     169,   169,   169,   170,   170,   170,   171,   171,   172,   172,
-     172,   172,   172,   172,   172,   172,   172,   172,   172,   172,
-     172,   172,   172,   173,   173,   173,   173,   173,   174,   174,
-     175,   175,   175,   175,   175,   175,   175,   176,   176,   176,
-     176,   177,   177,   178,   178,   178,   178,   179,   180,   180,
-     181,   181,   181,   181,   181,   181,   182,   182,   182,   182,
-     182,   182,   182,   182,   183,   183,   183,   183,   184,   185,
-     185
+     159,   159,   159,   159,   159,   159,   159,   159,   159,   159,
+     159,   159,   159,   159,   159,   159,   159,   159,   159,   159,
+     159,   159,   159,   159,   159,   159,   159,   159,   160,   160,
+     160,   160,   160,   160,   160,   160,   160,   160,   160,   160,
+     160,   160,   160,   160,   160,   160,   160,   161,   161,   161,
+     161,   161,   161,   162,   162,   162,   162,   163,   163,   164,
+     164,   165,   166,   166,   166,   167,   167,   168,   168,   169,
+     170,   170,   170,   171,   171,   171,   172,   172,   173,   173,
+     173,   173,   173,   173,   173,   173,   173,   173,   173,   173,
+     173,   173,   173,   174,   174,   174,   174,   174,   175,   175,
+     176,   176,   176,   176,   176,   176,   176,   177,   177,   177,
+     177,   178,   178,   179,   179,   179,   179,   180,   181,   181,
+     182,   182,   182,   182,   182,   182,   183,   183,   183,   183,
+     183,   183,   183,   183,   184,   184,   184,   184,   185,   186,
+     186
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yyr2[] =
 {
        0,     2,     2,     1,     0,     1,     3,     3,     3,     3,
        1,     1,     1,     1,     3,     1,     3,     3,     1,     3,
@@ -1408,22 +1488,22 @@
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, cstate, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
+#define YYBACKUP(Token, Value)                                    \
+  do                                                              \
+    if (yychar == YYEMPTY)                                        \
+      {                                                           \
+        yychar = (Token);                                         \
+        yylval = (Value);                                         \
+        YYPOPSTACK (yylen);                                       \
+        yystate = *yyssp;                                         \
+        goto yybackup;                                            \
+      }                                                           \
+    else                                                          \
+      {                                                           \
+        yyerror (yyscanner, cstate, YY_("syntax error: cannot back up")); \
+        YYERROR;                                                  \
+      }                                                           \
+  while (0)
 
 /* Error token number */
 #define YYTERROR        1
@@ -1463,39 +1543,41 @@
 } while (0)
 
 
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO.  |
+`-----------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
+  FILE *yyoutput = yyo;
+  YYUSE (yyoutput);
   YYUSE (yyscanner);
   YYUSE (cstate);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+    YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
 # endif
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO.  |
+`---------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
 {
-  YYFPRINTF (yyoutput, "%s %s (",
+  YYFPRINTF (yyo, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner, cstate);
-  YYFPRINTF (yyoutput, ")");
+  yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner, cstate);
+  YYFPRINTF (yyo, ")");
 }
 
 /*------------------------------------------------------------------.
@@ -1504,7 +1586,7 @@
 `------------------------------------------------------------------*/
 
 static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -1527,20 +1609,20 @@
 `------------------------------------------------*/
 
 static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, void *yyscanner, compiler_state_t *cstate)
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, int yyrule, void *yyscanner, compiler_state_t *cstate)
 {
-  unsigned long int yylno = yyrline[yyrule];
+  int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
              yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr,
-                       yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       yystos[+yyssp[yyi + 1 - yynrhs]],
+                       &yyvsp[(yyi + 1) - (yynrhs)]
                                               , yyscanner, cstate);
       YYFPRINTF (stderr, "\n");
     }
@@ -1584,13 +1666,13 @@
 
 # ifndef yystrlen
 #  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
+#   define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
 #  else
 /* Return the length of YYSTR.  */
-static YYSIZE_T
+static YYPTRDIFF_T
 yystrlen (const char *yystr)
 {
-  YYSIZE_T yylen;
+  YYPTRDIFF_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
     continue;
   return yylen;
@@ -1626,12 +1708,12 @@
    backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
    null, do not copy; instead, return the length of what the result
    would have been.  */
-static YYSIZE_T
+static YYPTRDIFF_T
 yytnamerr (char *yyres, const char *yystr)
 {
   if (*yystr == '"')
     {
-      YYSIZE_T yyn = 0;
+      YYPTRDIFF_T yyn = 0;
       char const *yyp = yystr;
 
       for (;;)
@@ -1644,7 +1726,10 @@
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
+            else
+              goto append;
+
+          append:
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -1659,10 +1744,10 @@
     do_not_strip_quotes: ;
     }
 
-  if (! yyres)
+  if (yyres)
+    return yystpcpy (yyres, yystr) - yyres;
+  else
     return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
 }
 # endif
 
@@ -1675,19 +1760,19 @@
    *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
    required number of bytes is too large to store.  */
 static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
+yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+                yy_state_t *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
   const char *yyformat = YY_NULLPTR;
-  /* Arguments of yyformat. */
+  /* Arguments of yyformat: reported tokens (one for the "unexpected",
+     one per "expected"). */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
+  /* Actual size of YYARG. */
   int yycount = 0;
+  /* Cumulated lengths of YYARG.  */
+  YYPTRDIFF_T yysize = 0;
 
   /* There are many possibilities here to consider:
      - If this state is a consistent state with a default action, then
@@ -1714,7 +1799,9 @@
   */
   if (yytoken != YYEMPTY)
     {
-      int yyn = yypact[*yyssp];
+      int yyn = yypact[+*yyssp];
+      YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+      yysize = yysize0;
       yyarg[yycount++] = yytname[yytoken];
       if (!yypact_value_is_default (yyn))
         {
@@ -1739,11 +1826,12 @@
                   }
                 yyarg[yycount++] = yytname[yyx];
                 {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  YYPTRDIFF_T yysize1
+                    = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+                    yysize = yysize1;
+                  else
                     return 2;
-                  yysize = yysize1;
                 }
               }
         }
@@ -1755,6 +1843,7 @@
       case N:                               \
         yyformat = S;                       \
       break
+    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1765,10 +1854,13 @@
     }
 
   {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    /* Don't count the "%s"s in the final size, but reserve room for
+       the terminator.  */
+    YYPTRDIFF_T yysize1 = yysize + (yystrlen (yyformat) - 2 * yycount) + 1;
+    if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+      yysize = yysize1;
+    else
       return 2;
-    yysize = yysize1;
   }
 
   if (*yymsg_alloc < yysize)
@@ -1794,8 +1886,8 @@
         }
       else
         {
-          yyp++;
-          yyformat++;
+          ++yyp;
+          ++yyformat;
         }
   }
   return 0;
@@ -1844,7 +1936,7 @@
     /* Number of syntax errors so far.  */
     int yynerrs;
 
-    int yystate;
+    yy_state_fast_t yystate;
     /* Number of tokens to shift before error messages enabled.  */
     int yyerrstatus;
 
@@ -1856,16 +1948,16 @@
        to reallocate them elsewhere.  */
 
     /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
+    yy_state_t yyssa[YYINITDEPTH];
+    yy_state_t *yyss;
+    yy_state_t *yyssp;
 
     /* The semantic value stack.  */
     YYSTYPE yyvsa[YYINITDEPTH];
     YYSTYPE *yyvs;
     YYSTYPE *yyvsp;
 
-    YYSIZE_T yystacksize;
+    YYPTRDIFF_T yystacksize;
 
   int yyn;
   int yyresult;
@@ -1879,7 +1971,7 @@
   /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
   char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+  YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
 #endif
 
 #define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
@@ -1900,46 +1992,54 @@
   yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
+
 /*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
+| yynewstate -- push a new state, which is found in yystate.  |
 `------------------------------------------------------------*/
- yynewstate:
+yynewstate:
   /* In all cases, when you get here, the value and location stacks
      have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
- yysetstate:
-  *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yysetstate -- set current state (the top of the stack) to yystate.  |
+`--------------------------------------------------------------------*/
+yysetstate:
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+  YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
+  YY_IGNORE_USELESS_CAST_BEGIN
+  *yyssp = YY_CAST (yy_state_t, yystate);
+  YY_IGNORE_USELESS_CAST_END
 
   if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+    goto yyexhaustedlab;
+#else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
+      YYPTRDIFF_T yysize = yyssp - yyss + 1;
 
-#ifdef yyoverflow
+# if defined yyoverflow
       {
         /* Give user a chance to reallocate the stack.  Use copies of
            these so that the &'s don't force the real ones into
            memory.  */
+        yy_state_t *yyss1 = yyss;
         YYSTYPE *yyvs1 = yyvs;
-        yytype_int16 *yyss1 = yyss;
 
         /* Each stack pointer address is followed by the size of the
            data in use in that stack, in bytes.  This used to be a
            conditional around just the two extra args, but that might
            be undefined if yyoverflow is a macro.  */
         yyoverflow (YY_("memory exhausted"),
-                    &yyss1, yysize * sizeof (*yyssp),
-                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yyss1, yysize * YYSIZEOF (*yyssp),
+                    &yyvs1, yysize * YYSIZEOF (*yyvsp),
                     &yystacksize);
-
         yyss = yyss1;
         yyvs = yyvs1;
       }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
         goto yyexhaustedlab;
@@ -1948,42 +2048,43 @@
         yystacksize = YYMAXDEPTH;
 
       {
-        yytype_int16 *yyss1 = yyss;
+        yy_state_t *yyss1 = yyss;
         union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+          YY_CAST (union yyalloc *,
+                   YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
         if (! yyptr)
           goto yyexhaustedlab;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
       }
 # endif
-#endif /* no yyoverflow */
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
+      YY_IGNORE_USELESS_CAST_BEGIN
+      YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+                  YY_CAST (long, yystacksize)));
+      YY_IGNORE_USELESS_CAST_END
 
       if (yyss + yystacksize - 1 <= yyssp)
         YYABORT;
     }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
   if (yystate == YYFINAL)
     YYACCEPT;
 
   goto yybackup;
 
+
 /*-----------.
 | yybackup.  |
 `-----------*/
 yybackup:
-
   /* Do appropriate processing given the current state.  Read a
      lookahead token if we need one and don't already have one.  */
 
@@ -2033,15 +2134,13 @@
 
   /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
   yystate = yyn;
   YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
   YY_IGNORE_MAYBE_UNINITIALIZED_END
 
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
   goto yynewstate;
 
 
@@ -2056,7 +2155,7 @@
 
 
 /*-----------------------------.
-| yyreduce -- Do a reduction.  |
+| yyreduce -- do a reduction.  |
 `-----------------------------*/
 yyreduce:
   /* yyn is the number of a rule to reduce with.  */
@@ -2076,852 +2175,857 @@
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-        case 2:
-#line 361 "grammar.y" /* yacc.c:1646  */
-    {
-	finish_parse(cstate, (yyvsp[0].blk).b);
+  case 2:
+#line 363 "grammar.y"
+{
+	CHECK_INT_VAL(finish_parse(cstate, (yyvsp[0].blk).b));
 }
-#line 2085 "grammar.c" /* yacc.c:1646  */
+#line 2184 "grammar.c"
     break;
 
   case 4:
-#line 366 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).q = qerr; }
-#line 2091 "grammar.c" /* yacc.c:1646  */
+#line 368 "grammar.y"
+                                { (yyval.blk).q = qerr; }
+#line 2190 "grammar.c"
     break;
 
   case 6:
-#line 369 "grammar.y" /* yacc.c:1646  */
-    { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2097 "grammar.c" /* yacc.c:1646  */
+#line 371 "grammar.y"
+                                { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2196 "grammar.c"
     break;
 
   case 7:
-#line 370 "grammar.y" /* yacc.c:1646  */
-    { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2103 "grammar.c" /* yacc.c:1646  */
+#line 372 "grammar.y"
+                                { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2202 "grammar.c"
     break;
 
   case 8:
-#line 371 "grammar.y" /* yacc.c:1646  */
-    { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2109 "grammar.c" /* yacc.c:1646  */
+#line 373 "grammar.y"
+                                { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2208 "grammar.c"
     break;
 
   case 9:
-#line 372 "grammar.y" /* yacc.c:1646  */
-    { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2115 "grammar.c" /* yacc.c:1646  */
+#line 374 "grammar.y"
+                                { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2214 "grammar.c"
     break;
 
   case 10:
-#line 374 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2121 "grammar.c" /* yacc.c:1646  */
+#line 376 "grammar.y"
+                                { (yyval.blk) = (yyvsp[-1].blk); }
+#line 2220 "grammar.c"
     break;
 
   case 11:
-#line 376 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2127 "grammar.c" /* yacc.c:1646  */
+#line 378 "grammar.y"
+                                { (yyval.blk) = (yyvsp[-1].blk); }
+#line 2226 "grammar.c"
     break;
 
   case 13:
-#line 379 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
-						   (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2134 "grammar.c" /* yacc.c:1646  */
+#line 381 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
+						   (yyval.blk).q = (yyvsp[-1].blk).q))); }
+#line 2233 "grammar.c"
     break;
 
   case 14:
-#line 381 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2140 "grammar.c" /* yacc.c:1646  */
+#line 383 "grammar.y"
+                                { (yyval.blk) = (yyvsp[-1].blk); }
+#line 2239 "grammar.c"
     break;
 
   case 15:
-#line 383 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_scode(cstate, (yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2146 "grammar.c" /* yacc.c:1646  */
+#line 385 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_PTR_VAL(((yyval.blk).b = gen_scode(cstate, (yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q))); }
+#line 2245 "grammar.c"
     break;
 
   case 16:
-#line 384 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
-				    (yyval.blk).q = (yyvsp[-3].blk).q); }
-#line 2153 "grammar.c" /* yacc.c:1646  */
+#line 386 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[-2].s)); CHECK_PTR_VAL(((yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
+				    (yyval.blk).q = (yyvsp[-3].blk).q))); }
+#line 2252 "grammar.c"
     break;
 
   case 17:
-#line 386 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), (yyvsp[0].s), 0,
-				    (yyval.blk).q = (yyvsp[-3].blk).q); }
-#line 2160 "grammar.c" /* yacc.c:1646  */
+#line 388 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[-2].s)); CHECK_PTR_VAL(((yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), (yyvsp[0].s), 0,
+				    (yyval.blk).q = (yyvsp[-3].blk).q))); }
+#line 2259 "grammar.c"
     break;
 
   case 18:
-#line 388 "grammar.y" /* yacc.c:1646  */
-    {
+#line 390 "grammar.y"
+                                {
+				  CHECK_PTR_VAL((yyvsp[0].s));
 				  /* Decide how to parse HID based on proto */
 				  (yyval.blk).q = (yyvsp[-1].blk).q;
-				  if ((yyval.blk).q.addr == Q_PORT)
-				  	bpf_error(cstate, "'port' modifier applied to ip host");
-				  else if ((yyval.blk).q.addr == Q_PORTRANGE)
-				  	bpf_error(cstate, "'portrange' modifier applied to ip host");
-				  else if ((yyval.blk).q.addr == Q_PROTO)
-				  	bpf_error(cstate, "'proto' modifier applied to ip host");
-				  else if ((yyval.blk).q.addr == Q_PROTOCHAIN)
-				  	bpf_error(cstate, "'protochain' modifier applied to ip host");
-				  (yyval.blk).b = gen_ncode(cstate, (yyvsp[0].s), 0, (yyval.blk).q);
+				  if ((yyval.blk).q.addr == Q_PORT) {
+				  	bpf_set_error(cstate, "'port' modifier applied to ip host");
+				  	YYABORT;
+				  } else if ((yyval.blk).q.addr == Q_PORTRANGE) {
+				  	bpf_set_error(cstate, "'portrange' modifier applied to ip host");
+				  	YYABORT;
+				  } else if ((yyval.blk).q.addr == Q_PROTO) {
+				  	bpf_set_error(cstate, "'proto' modifier applied to ip host");
+				  	YYABORT;
+				  } else if ((yyval.blk).q.addr == Q_PROTOCHAIN) {
+				  	bpf_set_error(cstate, "'protochain' modifier applied to ip host");
+				  	YYABORT;
+				  }
+				  CHECK_PTR_VAL(((yyval.blk).b = gen_ncode(cstate, (yyvsp[0].s), 0, (yyval.blk).q)));
 				}
-#line 2178 "grammar.c" /* yacc.c:1646  */
+#line 2283 "grammar.c"
     break;
 
   case 19:
-#line 401 "grammar.y" /* yacc.c:1646  */
-    {
+#line 409 "grammar.y"
+                                {
+				  CHECK_PTR_VAL((yyvsp[-2].s));
 #ifdef INET6
-				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
-				    (yyval.blk).q = (yyvsp[-3].blk).q);
+				  CHECK_PTR_VAL(((yyval.blk).b = gen_mcode6(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
+				    (yyval.blk).q = (yyvsp[-3].blk).q)));
 #else
-				  bpf_error(cstate, "'ip6addr/prefixlen' not supported "
+				  bpf_set_error(cstate, "'ip6addr/prefixlen' not supported "
 					"in this configuration");
+				  YYABORT;
 #endif /*INET6*/
 				}
-#line 2192 "grammar.c" /* yacc.c:1646  */
+#line 2299 "grammar.c"
     break;
 
   case 20:
-#line 410 "grammar.y" /* yacc.c:1646  */
-    {
+#line 420 "grammar.y"
+                                {
+				  CHECK_PTR_VAL((yyvsp[0].s));
 #ifdef INET6
-				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[0].s), 0, 128,
-				    (yyval.blk).q = (yyvsp[-1].blk).q);
+				  CHECK_PTR_VAL(((yyval.blk).b = gen_mcode6(cstate, (yyvsp[0].s), 0, 128,
+				    (yyval.blk).q = (yyvsp[-1].blk).q)));
 #else
-				  bpf_error(cstate, "'ip6addr' not supported "
+				  bpf_set_error(cstate, "'ip6addr' not supported "
 					"in this configuration");
+				  YYABORT;
 #endif /*INET6*/
 				}
-#line 2206 "grammar.c" /* yacc.c:1646  */
+#line 2315 "grammar.c"
     break;
 
   case 21:
-#line 419 "grammar.y" /* yacc.c:1646  */
-    {
-				  (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
-				   * with it.
-				   */
-				  free((yyvsp[0].e));
-				}
-#line 2220 "grammar.c" /* yacc.c:1646  */
+#line 431 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_PTR_VAL(((yyval.blk).b = gen_ecode(cstate, (yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q))); }
+#line 2321 "grammar.c"
     break;
 
   case 22:
-#line 428 "grammar.y" /* yacc.c:1646  */
-    {
-				  (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
-				   * with it.
-				   */
-				  free((yyvsp[0].e));
-				}
-#line 2234 "grammar.c" /* yacc.c:1646  */
+#line 432 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_PTR_VAL(((yyval.blk).b = gen_acode(cstate, (yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q))); }
+#line 2327 "grammar.c"
     break;
 
   case 23:
-#line 437 "grammar.y" /* yacc.c:1646  */
-    { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2240 "grammar.c" /* yacc.c:1646  */
+#line 433 "grammar.y"
+                                { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2333 "grammar.c"
     break;
 
   case 24:
-#line 439 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2246 "grammar.c" /* yacc.c:1646  */
+#line 435 "grammar.y"
+                                { (yyval.blk) = (yyvsp[-1].blk); }
+#line 2339 "grammar.c"
     break;
 
   case 25:
-#line 441 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2252 "grammar.c" /* yacc.c:1646  */
+#line 437 "grammar.y"
+                                { (yyval.blk) = (yyvsp[-1].blk); }
+#line 2345 "grammar.c"
     break;
 
   case 27:
-#line 444 "grammar.y" /* yacc.c:1646  */
-    { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2258 "grammar.c" /* yacc.c:1646  */
+#line 440 "grammar.y"
+                                { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2351 "grammar.c"
     break;
 
   case 28:
-#line 445 "grammar.y" /* yacc.c:1646  */
-    { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2264 "grammar.c" /* yacc.c:1646  */
+#line 441 "grammar.y"
+                                { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2357 "grammar.c"
     break;
 
   case 29:
-#line 447 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
-						   (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2271 "grammar.c" /* yacc.c:1646  */
+#line 443 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
+						   (yyval.blk).q = (yyvsp[-1].blk).q))); }
+#line 2364 "grammar.c"
     break;
 
   case 32:
-#line 452 "grammar.y" /* yacc.c:1646  */
-    { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2277 "grammar.c" /* yacc.c:1646  */
+#line 448 "grammar.y"
+                                { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 2370 "grammar.c"
     break;
 
   case 33:
-#line 454 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 2283 "grammar.c" /* yacc.c:1646  */
+#line 450 "grammar.y"
+                                { QSET((yyval.blk).q, (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 2376 "grammar.c"
     break;
 
   case 34:
-#line 455 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-1].i), (yyvsp[0].i), Q_DEFAULT); }
-#line 2289 "grammar.c" /* yacc.c:1646  */
+#line 451 "grammar.y"
+                                { QSET((yyval.blk).q, (yyvsp[-1].i), (yyvsp[0].i), Q_DEFAULT); }
+#line 2382 "grammar.c"
     break;
 
   case 35:
-#line 456 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2295 "grammar.c" /* yacc.c:1646  */
+#line 452 "grammar.y"
+                                { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
+#line 2388 "grammar.c"
     break;
 
   case 36:
-#line 457 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTO); }
-#line 2301 "grammar.c" /* yacc.c:1646  */
+#line 453 "grammar.y"
+                                { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTO); }
+#line 2394 "grammar.c"
     break;
 
   case 37:
-#line 458 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTOCHAIN); }
-#line 2307 "grammar.c" /* yacc.c:1646  */
+#line 454 "grammar.y"
+                                {
+#ifdef NO_PROTOCHAIN
+				  bpf_set_error(cstate, "protochain not supported");
+				  YYABORT;
+#else
+				  QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTOCHAIN);
+#endif
+				}
+#line 2407 "grammar.c"
     break;
 
   case 38:
-#line 459 "grammar.y" /* yacc.c:1646  */
-    { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2313 "grammar.c" /* yacc.c:1646  */
+#line 462 "grammar.y"
+                                { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
+#line 2413 "grammar.c"
     break;
 
   case 39:
-#line 461 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk) = (yyvsp[0].blk); }
-#line 2319 "grammar.c" /* yacc.c:1646  */
+#line 464 "grammar.y"
+                                { (yyval.blk) = (yyvsp[0].blk); }
+#line 2419 "grammar.c"
     break;
 
   case 40:
-#line 462 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = (yyvsp[-2].blk).q; }
-#line 2325 "grammar.c" /* yacc.c:1646  */
+#line 465 "grammar.y"
+                                { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = (yyvsp[-2].blk).q; }
+#line 2425 "grammar.c"
     break;
 
   case 41:
-#line 463 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_proto_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2331 "grammar.c" /* yacc.c:1646  */
+#line 466 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_proto_abbrev(cstate, (yyvsp[0].i)))); (yyval.blk).q = qerr; }
+#line 2431 "grammar.c"
     break;
 
   case 42:
-#line 464 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 0);
+#line 467 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 0)));
 				  (yyval.blk).q = qerr; }
-#line 2338 "grammar.c" /* yacc.c:1646  */
+#line 2438 "grammar.c"
     break;
 
   case 43:
-#line 466 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 1);
+#line 469 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 1)));
 				  (yyval.blk).q = qerr; }
-#line 2345 "grammar.c" /* yacc.c:1646  */
+#line 2445 "grammar.c"
     break;
 
   case 44:
-#line 468 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[0].rblk); (yyval.blk).q = qerr; }
-#line 2351 "grammar.c" /* yacc.c:1646  */
+#line 471 "grammar.y"
+                                { (yyval.blk).b = (yyvsp[0].rblk); (yyval.blk).q = qerr; }
+#line 2451 "grammar.c"
     break;
 
   case 45:
-#line 469 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmtype_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2357 "grammar.c" /* yacc.c:1646  */
+#line 472 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_atmtype_abbrev(cstate, (yyvsp[0].i)))); (yyval.blk).q = qerr; }
+#line 2457 "grammar.c"
     break;
 
   case 46:
-#line 470 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmmulti_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2363 "grammar.c" /* yacc.c:1646  */
+#line 473 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_atmmulti_abbrev(cstate, (yyvsp[0].i)))); (yyval.blk).q = qerr; }
+#line 2463 "grammar.c"
     break;
 
   case 47:
-#line 471 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2369 "grammar.c" /* yacc.c:1646  */
+#line 474 "grammar.y"
+                                { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
+#line 2469 "grammar.c"
     break;
 
   case 48:
-#line 472 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp2type_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2375 "grammar.c" /* yacc.c:1646  */
+#line 475 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_mtp2type_abbrev(cstate, (yyvsp[0].i)))); (yyval.blk).q = qerr; }
+#line 2475 "grammar.c"
     break;
 
   case 49:
-#line 473 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2381 "grammar.c" /* yacc.c:1646  */
+#line 476 "grammar.y"
+                                { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
+#line 2481 "grammar.c"
     break;
 
   case 51:
-#line 477 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_DEFAULT; }
-#line 2387 "grammar.c" /* yacc.c:1646  */
+#line 480 "grammar.y"
+                                { (yyval.i) = Q_DEFAULT; }
+#line 2487 "grammar.c"
     break;
 
   case 52:
-#line 480 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_SRC; }
-#line 2393 "grammar.c" /* yacc.c:1646  */
+#line 483 "grammar.y"
+                                { (yyval.i) = Q_SRC; }
+#line 2493 "grammar.c"
     break;
 
   case 53:
-#line 481 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_DST; }
-#line 2399 "grammar.c" /* yacc.c:1646  */
+#line 484 "grammar.y"
+                                { (yyval.i) = Q_DST; }
+#line 2499 "grammar.c"
     break;
 
   case 54:
-#line 482 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_OR; }
-#line 2405 "grammar.c" /* yacc.c:1646  */
+#line 485 "grammar.y"
+                                { (yyval.i) = Q_OR; }
+#line 2505 "grammar.c"
     break;
 
   case 55:
-#line 483 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_OR; }
-#line 2411 "grammar.c" /* yacc.c:1646  */
+#line 486 "grammar.y"
+                                { (yyval.i) = Q_OR; }
+#line 2511 "grammar.c"
     break;
 
   case 56:
-#line 484 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_AND; }
-#line 2417 "grammar.c" /* yacc.c:1646  */
+#line 487 "grammar.y"
+                                { (yyval.i) = Q_AND; }
+#line 2517 "grammar.c"
     break;
 
   case 57:
-#line 485 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_AND; }
-#line 2423 "grammar.c" /* yacc.c:1646  */
+#line 488 "grammar.y"
+                                { (yyval.i) = Q_AND; }
+#line 2523 "grammar.c"
     break;
 
   case 58:
-#line 486 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ADDR1; }
-#line 2429 "grammar.c" /* yacc.c:1646  */
+#line 489 "grammar.y"
+                                { (yyval.i) = Q_ADDR1; }
+#line 2529 "grammar.c"
     break;
 
   case 59:
-#line 487 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ADDR2; }
-#line 2435 "grammar.c" /* yacc.c:1646  */
+#line 490 "grammar.y"
+                                { (yyval.i) = Q_ADDR2; }
+#line 2535 "grammar.c"
     break;
 
   case 60:
-#line 488 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ADDR3; }
-#line 2441 "grammar.c" /* yacc.c:1646  */
+#line 491 "grammar.y"
+                                { (yyval.i) = Q_ADDR3; }
+#line 2541 "grammar.c"
     break;
 
   case 61:
-#line 489 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ADDR4; }
-#line 2447 "grammar.c" /* yacc.c:1646  */
+#line 492 "grammar.y"
+                                { (yyval.i) = Q_ADDR4; }
+#line 2547 "grammar.c"
     break;
 
   case 62:
-#line 490 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_RA; }
-#line 2453 "grammar.c" /* yacc.c:1646  */
+#line 493 "grammar.y"
+                                { (yyval.i) = Q_RA; }
+#line 2553 "grammar.c"
     break;
 
   case 63:
-#line 491 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_TA; }
-#line 2459 "grammar.c" /* yacc.c:1646  */
+#line 494 "grammar.y"
+                                { (yyval.i) = Q_TA; }
+#line 2559 "grammar.c"
     break;
 
   case 64:
-#line 494 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_HOST; }
-#line 2465 "grammar.c" /* yacc.c:1646  */
+#line 497 "grammar.y"
+                                { (yyval.i) = Q_HOST; }
+#line 2565 "grammar.c"
     break;
 
   case 65:
-#line 495 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_NET; }
-#line 2471 "grammar.c" /* yacc.c:1646  */
+#line 498 "grammar.y"
+                                { (yyval.i) = Q_NET; }
+#line 2571 "grammar.c"
     break;
 
   case 66:
-#line 496 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_PORT; }
-#line 2477 "grammar.c" /* yacc.c:1646  */
+#line 499 "grammar.y"
+                                { (yyval.i) = Q_PORT; }
+#line 2577 "grammar.c"
     break;
 
   case 67:
-#line 497 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_PORTRANGE; }
-#line 2483 "grammar.c" /* yacc.c:1646  */
+#line 500 "grammar.y"
+                                { (yyval.i) = Q_PORTRANGE; }
+#line 2583 "grammar.c"
     break;
 
   case 68:
-#line 500 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_GATEWAY; }
-#line 2489 "grammar.c" /* yacc.c:1646  */
+#line 503 "grammar.y"
+                                { (yyval.i) = Q_GATEWAY; }
+#line 2589 "grammar.c"
     break;
 
   case 69:
-#line 502 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_LINK; }
-#line 2495 "grammar.c" /* yacc.c:1646  */
+#line 505 "grammar.y"
+                                { (yyval.i) = Q_LINK; }
+#line 2595 "grammar.c"
     break;
 
   case 70:
-#line 503 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_IP; }
-#line 2501 "grammar.c" /* yacc.c:1646  */
+#line 506 "grammar.y"
+                                { (yyval.i) = Q_IP; }
+#line 2601 "grammar.c"
     break;
 
   case 71:
-#line 504 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ARP; }
-#line 2507 "grammar.c" /* yacc.c:1646  */
+#line 507 "grammar.y"
+                                { (yyval.i) = Q_ARP; }
+#line 2607 "grammar.c"
     break;
 
   case 72:
-#line 505 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_RARP; }
-#line 2513 "grammar.c" /* yacc.c:1646  */
+#line 508 "grammar.y"
+                                { (yyval.i) = Q_RARP; }
+#line 2613 "grammar.c"
     break;
 
   case 73:
-#line 506 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_SCTP; }
-#line 2519 "grammar.c" /* yacc.c:1646  */
+#line 509 "grammar.y"
+                                { (yyval.i) = Q_SCTP; }
+#line 2619 "grammar.c"
     break;
 
   case 74:
-#line 507 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_TCP; }
-#line 2525 "grammar.c" /* yacc.c:1646  */
+#line 510 "grammar.y"
+                                { (yyval.i) = Q_TCP; }
+#line 2625 "grammar.c"
     break;
 
   case 75:
-#line 508 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_UDP; }
-#line 2531 "grammar.c" /* yacc.c:1646  */
+#line 511 "grammar.y"
+                                { (yyval.i) = Q_UDP; }
+#line 2631 "grammar.c"
     break;
 
   case 76:
-#line 509 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ICMP; }
-#line 2537 "grammar.c" /* yacc.c:1646  */
+#line 512 "grammar.y"
+                                { (yyval.i) = Q_ICMP; }
+#line 2637 "grammar.c"
     break;
 
   case 77:
-#line 510 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_IGMP; }
-#line 2543 "grammar.c" /* yacc.c:1646  */
+#line 513 "grammar.y"
+                                { (yyval.i) = Q_IGMP; }
+#line 2643 "grammar.c"
     break;
 
   case 78:
-#line 511 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_IGRP; }
-#line 2549 "grammar.c" /* yacc.c:1646  */
+#line 514 "grammar.y"
+                                { (yyval.i) = Q_IGRP; }
+#line 2649 "grammar.c"
     break;
 
   case 79:
-#line 512 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_PIM; }
-#line 2555 "grammar.c" /* yacc.c:1646  */
+#line 515 "grammar.y"
+                                { (yyval.i) = Q_PIM; }
+#line 2655 "grammar.c"
     break;
 
   case 80:
-#line 513 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_VRRP; }
-#line 2561 "grammar.c" /* yacc.c:1646  */
+#line 516 "grammar.y"
+                                { (yyval.i) = Q_VRRP; }
+#line 2661 "grammar.c"
     break;
 
   case 81:
-#line 514 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_CARP; }
-#line 2567 "grammar.c" /* yacc.c:1646  */
+#line 517 "grammar.y"
+                                { (yyval.i) = Q_CARP; }
+#line 2667 "grammar.c"
     break;
 
   case 82:
-#line 515 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ATALK; }
-#line 2573 "grammar.c" /* yacc.c:1646  */
+#line 518 "grammar.y"
+                                { (yyval.i) = Q_ATALK; }
+#line 2673 "grammar.c"
     break;
 
   case 83:
-#line 516 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_AARP; }
-#line 2579 "grammar.c" /* yacc.c:1646  */
+#line 519 "grammar.y"
+                                { (yyval.i) = Q_AARP; }
+#line 2679 "grammar.c"
     break;
 
   case 84:
-#line 517 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_DECNET; }
-#line 2585 "grammar.c" /* yacc.c:1646  */
+#line 520 "grammar.y"
+                                { (yyval.i) = Q_DECNET; }
+#line 2685 "grammar.c"
     break;
 
   case 85:
-#line 518 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_LAT; }
-#line 2591 "grammar.c" /* yacc.c:1646  */
+#line 521 "grammar.y"
+                                { (yyval.i) = Q_LAT; }
+#line 2691 "grammar.c"
     break;
 
   case 86:
-#line 519 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_SCA; }
-#line 2597 "grammar.c" /* yacc.c:1646  */
+#line 522 "grammar.y"
+                                { (yyval.i) = Q_SCA; }
+#line 2697 "grammar.c"
     break;
 
   case 87:
-#line 520 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_MOPDL; }
-#line 2603 "grammar.c" /* yacc.c:1646  */
+#line 523 "grammar.y"
+                                { (yyval.i) = Q_MOPDL; }
+#line 2703 "grammar.c"
     break;
 
   case 88:
-#line 521 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_MOPRC; }
-#line 2609 "grammar.c" /* yacc.c:1646  */
+#line 524 "grammar.y"
+                                { (yyval.i) = Q_MOPRC; }
+#line 2709 "grammar.c"
     break;
 
   case 89:
-#line 522 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_IPV6; }
-#line 2615 "grammar.c" /* yacc.c:1646  */
+#line 525 "grammar.y"
+                                { (yyval.i) = Q_IPV6; }
+#line 2715 "grammar.c"
     break;
 
   case 90:
-#line 523 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ICMPV6; }
-#line 2621 "grammar.c" /* yacc.c:1646  */
+#line 526 "grammar.y"
+                                { (yyval.i) = Q_ICMPV6; }
+#line 2721 "grammar.c"
     break;
 
   case 91:
-#line 524 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_AH; }
-#line 2627 "grammar.c" /* yacc.c:1646  */
+#line 527 "grammar.y"
+                                { (yyval.i) = Q_AH; }
+#line 2727 "grammar.c"
     break;
 
   case 92:
-#line 525 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ESP; }
-#line 2633 "grammar.c" /* yacc.c:1646  */
+#line 528 "grammar.y"
+                                { (yyval.i) = Q_ESP; }
+#line 2733 "grammar.c"
     break;
 
   case 93:
-#line 526 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISO; }
-#line 2639 "grammar.c" /* yacc.c:1646  */
+#line 529 "grammar.y"
+                                { (yyval.i) = Q_ISO; }
+#line 2739 "grammar.c"
     break;
 
   case 94:
-#line 527 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ESIS; }
-#line 2645 "grammar.c" /* yacc.c:1646  */
+#line 530 "grammar.y"
+                                { (yyval.i) = Q_ESIS; }
+#line 2745 "grammar.c"
     break;
 
   case 95:
-#line 528 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS; }
-#line 2651 "grammar.c" /* yacc.c:1646  */
+#line 531 "grammar.y"
+                                { (yyval.i) = Q_ISIS; }
+#line 2751 "grammar.c"
     break;
 
   case 96:
-#line 529 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_L1; }
-#line 2657 "grammar.c" /* yacc.c:1646  */
+#line 532 "grammar.y"
+                                { (yyval.i) = Q_ISIS_L1; }
+#line 2757 "grammar.c"
     break;
 
   case 97:
-#line 530 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_L2; }
-#line 2663 "grammar.c" /* yacc.c:1646  */
+#line 533 "grammar.y"
+                                { (yyval.i) = Q_ISIS_L2; }
+#line 2763 "grammar.c"
     break;
 
   case 98:
-#line 531 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_IIH; }
-#line 2669 "grammar.c" /* yacc.c:1646  */
+#line 534 "grammar.y"
+                                { (yyval.i) = Q_ISIS_IIH; }
+#line 2769 "grammar.c"
     break;
 
   case 99:
-#line 532 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_LSP; }
-#line 2675 "grammar.c" /* yacc.c:1646  */
+#line 535 "grammar.y"
+                                { (yyval.i) = Q_ISIS_LSP; }
+#line 2775 "grammar.c"
     break;
 
   case 100:
-#line 533 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_SNP; }
-#line 2681 "grammar.c" /* yacc.c:1646  */
+#line 536 "grammar.y"
+                                { (yyval.i) = Q_ISIS_SNP; }
+#line 2781 "grammar.c"
     break;
 
   case 101:
-#line 534 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_PSNP; }
-#line 2687 "grammar.c" /* yacc.c:1646  */
+#line 537 "grammar.y"
+                                { (yyval.i) = Q_ISIS_PSNP; }
+#line 2787 "grammar.c"
     break;
 
   case 102:
-#line 535 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_ISIS_CSNP; }
-#line 2693 "grammar.c" /* yacc.c:1646  */
+#line 538 "grammar.y"
+                                { (yyval.i) = Q_ISIS_CSNP; }
+#line 2793 "grammar.c"
     break;
 
   case 103:
-#line 536 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_CLNP; }
-#line 2699 "grammar.c" /* yacc.c:1646  */
+#line 539 "grammar.y"
+                                { (yyval.i) = Q_CLNP; }
+#line 2799 "grammar.c"
     break;
 
   case 104:
-#line 537 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_STP; }
-#line 2705 "grammar.c" /* yacc.c:1646  */
+#line 540 "grammar.y"
+                                { (yyval.i) = Q_STP; }
+#line 2805 "grammar.c"
     break;
 
   case 105:
-#line 538 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_IPX; }
-#line 2711 "grammar.c" /* yacc.c:1646  */
+#line 541 "grammar.y"
+                                { (yyval.i) = Q_IPX; }
+#line 2811 "grammar.c"
     break;
 
   case 106:
-#line 539 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_NETBEUI; }
-#line 2717 "grammar.c" /* yacc.c:1646  */
+#line 542 "grammar.y"
+                                { (yyval.i) = Q_NETBEUI; }
+#line 2817 "grammar.c"
     break;
 
   case 107:
-#line 540 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = Q_RADIO; }
-#line 2723 "grammar.c" /* yacc.c:1646  */
+#line 543 "grammar.y"
+                                { (yyval.i) = Q_RADIO; }
+#line 2823 "grammar.c"
     break;
 
   case 108:
-#line 542 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_broadcast(cstate, (yyvsp[-1].i)); }
-#line 2729 "grammar.c" /* yacc.c:1646  */
+#line 545 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_broadcast(cstate, (yyvsp[-1].i)))); }
+#line 2829 "grammar.c"
     break;
 
   case 109:
-#line 543 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_multicast(cstate, (yyvsp[-1].i)); }
-#line 2735 "grammar.c" /* yacc.c:1646  */
+#line 546 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_multicast(cstate, (yyvsp[-1].i)))); }
+#line 2835 "grammar.c"
     break;
 
   case 110:
-#line 544 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_less(cstate, (yyvsp[0].i)); }
-#line 2741 "grammar.c" /* yacc.c:1646  */
+#line 547 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_less(cstate, (yyvsp[0].i)))); }
+#line 2841 "grammar.c"
     break;
 
   case 111:
-#line 545 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_greater(cstate, (yyvsp[0].i)); }
-#line 2747 "grammar.c" /* yacc.c:1646  */
+#line 548 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_greater(cstate, (yyvsp[0].i)))); }
+#line 2847 "grammar.c"
     break;
 
   case 112:
-#line 546 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_byteop(cstate, (yyvsp[-1].i), (yyvsp[-2].i), (yyvsp[0].i)); }
-#line 2753 "grammar.c" /* yacc.c:1646  */
+#line 549 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_byteop(cstate, (yyvsp[-1].i), (yyvsp[-2].i), (yyvsp[0].i)))); }
+#line 2853 "grammar.c"
     break;
 
   case 113:
-#line 547 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_inbound(cstate, 0); }
-#line 2759 "grammar.c" /* yacc.c:1646  */
+#line 550 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_inbound(cstate, 0))); }
+#line 2859 "grammar.c"
     break;
 
   case 114:
-#line 548 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_inbound(cstate, 1); }
-#line 2765 "grammar.c" /* yacc.c:1646  */
+#line 551 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_inbound(cstate, 1))); }
+#line 2865 "grammar.c"
     break;
 
   case 115:
-#line 549 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_vlan(cstate, (yyvsp[0].i)); }
-#line 2771 "grammar.c" /* yacc.c:1646  */
+#line 552 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_vlan(cstate, (bpf_u_int32)(yyvsp[0].i), 1))); }
+#line 2871 "grammar.c"
     break;
 
   case 116:
-#line 550 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_vlan(cstate, -1); }
-#line 2777 "grammar.c" /* yacc.c:1646  */
+#line 553 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_vlan(cstate, 0, 0))); }
+#line 2877 "grammar.c"
     break;
 
   case 117:
-#line 551 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_mpls(cstate, (yyvsp[0].i)); }
-#line 2783 "grammar.c" /* yacc.c:1646  */
+#line 554 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_mpls(cstate, (bpf_u_int32)(yyvsp[0].i), 1))); }
+#line 2883 "grammar.c"
     break;
 
   case 118:
-#line 552 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_mpls(cstate, -1); }
-#line 2789 "grammar.c" /* yacc.c:1646  */
+#line 555 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_mpls(cstate, 0, 0))); }
+#line 2889 "grammar.c"
     break;
 
   case 119:
-#line 553 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoed(cstate); }
-#line 2795 "grammar.c" /* yacc.c:1646  */
+#line 556 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pppoed(cstate))); }
+#line 2895 "grammar.c"
     break;
 
   case 120:
-#line 554 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoes(cstate, (yyvsp[0].i)); }
-#line 2801 "grammar.c" /* yacc.c:1646  */
+#line 557 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pppoes(cstate, (bpf_u_int32)(yyvsp[0].i), 1))); }
+#line 2901 "grammar.c"
     break;
 
   case 121:
-#line 555 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoes(cstate, -1); }
-#line 2807 "grammar.c" /* yacc.c:1646  */
+#line 558 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pppoes(cstate, 0, 0))); }
+#line 2907 "grammar.c"
     break;
 
   case 122:
-#line 556 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_geneve(cstate, (yyvsp[0].i)); }
-#line 2813 "grammar.c" /* yacc.c:1646  */
+#line 559 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_geneve(cstate, (bpf_u_int32)(yyvsp[0].i), 1))); }
+#line 2913 "grammar.c"
     break;
 
   case 123:
-#line 557 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_geneve(cstate, -1); }
-#line 2819 "grammar.c" /* yacc.c:1646  */
+#line 560 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_geneve(cstate, 0, 0))); }
+#line 2919 "grammar.c"
     break;
 
   case 124:
-#line 558 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2825 "grammar.c" /* yacc.c:1646  */
+#line 561 "grammar.y"
+                                { (yyval.rblk) = (yyvsp[0].rblk); }
+#line 2925 "grammar.c"
     break;
 
   case 125:
-#line 559 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2831 "grammar.c" /* yacc.c:1646  */
+#line 562 "grammar.y"
+                                { (yyval.rblk) = (yyvsp[0].rblk); }
+#line 2931 "grammar.c"
     break;
 
   case 126:
-#line 560 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2837 "grammar.c" /* yacc.c:1646  */
+#line 563 "grammar.y"
+                                { (yyval.rblk) = (yyvsp[0].rblk); }
+#line 2937 "grammar.c"
     break;
 
   case 127:
-#line 563 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_ifname(cstate, (yyvsp[0].s)); }
-#line 2843 "grammar.c" /* yacc.c:1646  */
+#line 566 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_PTR_VAL(((yyval.rblk) = gen_pf_ifname(cstate, (yyvsp[0].s)))); }
+#line 2943 "grammar.c"
     break;
 
   case 128:
-#line 564 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_ruleset(cstate, (yyvsp[0].s)); }
-#line 2849 "grammar.c" /* yacc.c:1646  */
+#line 567 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_PTR_VAL(((yyval.rblk) = gen_pf_ruleset(cstate, (yyvsp[0].s)))); }
+#line 2949 "grammar.c"
     break;
 
   case 129:
-#line 565 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_rnr(cstate, (yyvsp[0].i)); }
-#line 2855 "grammar.c" /* yacc.c:1646  */
+#line 568 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pf_rnr(cstate, (yyvsp[0].i)))); }
+#line 2955 "grammar.c"
     break;
 
   case 130:
-#line 566 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_srnr(cstate, (yyvsp[0].i)); }
-#line 2861 "grammar.c" /* yacc.c:1646  */
+#line 569 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pf_srnr(cstate, (yyvsp[0].i)))); }
+#line 2961 "grammar.c"
     break;
 
   case 131:
-#line 567 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_reason(cstate, (yyvsp[0].i)); }
-#line 2867 "grammar.c" /* yacc.c:1646  */
+#line 570 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pf_reason(cstate, (yyvsp[0].i)))); }
+#line 2967 "grammar.c"
     break;
 
   case 132:
-#line 568 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_action(cstate, (yyvsp[0].i)); }
-#line 2873 "grammar.c" /* yacc.c:1646  */
+#line 571 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_pf_action(cstate, (yyvsp[0].i)))); }
+#line 2973 "grammar.c"
     break;
 
   case 133:
-#line 572 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[-2].i) | (yyvsp[0].i),
+#line 575 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_p80211_type(cstate, (yyvsp[-2].i) | (yyvsp[0].i),
 					IEEE80211_FC0_TYPE_MASK |
-					IEEE80211_FC0_SUBTYPE_MASK);
+					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
-#line 2882 "grammar.c" /* yacc.c:1646  */
+#line 2982 "grammar.c"
     break;
 
   case 134:
-#line 576 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
-					IEEE80211_FC0_TYPE_MASK);
+#line 579 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
+					IEEE80211_FC0_TYPE_MASK)));
 				}
-#line 2890 "grammar.c" /* yacc.c:1646  */
+#line 2990 "grammar.c"
     break;
 
   case 135:
-#line 579 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
+#line 582 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
 					IEEE80211_FC0_TYPE_MASK |
-					IEEE80211_FC0_SUBTYPE_MASK);
+					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
-#line 2899 "grammar.c" /* yacc.c:1646  */
+#line 2999 "grammar.c"
     break;
 
   case 136:
-#line 583 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_fcdir(cstate, (yyvsp[0].i)); }
-#line 2905 "grammar.c" /* yacc.c:1646  */
+#line 586 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_p80211_fcdir(cstate, (yyvsp[0].i)))); }
+#line 3005 "grammar.c"
     break;
 
   case 138:
-#line 587 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = str2tok((yyvsp[0].s), ieee80211_types);
-				  if ((yyval.i) == -1)
-				  	bpf_error(cstate, "unknown 802.11 type name");
+#line 590 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s));
+				  (yyval.i) = str2tok((yyvsp[0].s), ieee80211_types);
+				  if ((yyval.i) == -1) {
+				  	bpf_set_error(cstate, "unknown 802.11 type name");
+				  	YYABORT;
+				  }
 				}
-#line 2914 "grammar.c" /* yacc.c:1646  */
+#line 3017 "grammar.c"
     break;
 
   case 140:
-#line 594 "grammar.y" /* yacc.c:1646  */
-    { const struct tok *types = NULL;
+#line 600 "grammar.y"
+                                { const struct tok *types = NULL;
 				  int i;
+				  CHECK_PTR_VAL((yyvsp[0].s));
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error(cstate, "unknown 802.11 type");
-						break;
+						bpf_set_error(cstate, "unknown 802.11 type");
+						YYABORT;
 					}
 					if ((yyvsp[(-1) - (1)].i) == ieee80211_type_subtypes[i].type) {
 						types = ieee80211_type_subtypes[i].tok;
@@ -2930,20 +3034,23 @@
 				  }
 
 				  (yyval.i) = str2tok((yyvsp[0].s), types);
-				  if ((yyval.i) == -1)
-					bpf_error(cstate, "unknown 802.11 subtype name");
+				  if ((yyval.i) == -1) {
+					bpf_set_error(cstate, "unknown 802.11 subtype name");
+					YYABORT;
+				  }
 				}
-#line 2937 "grammar.c" /* yacc.c:1646  */
+#line 3043 "grammar.c"
     break;
 
   case 141:
-#line 614 "grammar.y" /* yacc.c:1646  */
-    { int i;
+#line 623 "grammar.y"
+                                { int i;
+				  CHECK_PTR_VAL((yyvsp[0].s));
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error(cstate, "unknown 802.11 type name");
-						break;
+						bpf_set_error(cstate, "unknown 802.11 type name");
+						YYABORT;
 					}
 					(yyval.i) = str2tok((yyvsp[0].s), ieee80211_type_subtypes[i].tok);
 					if ((yyval.i) != -1) {
@@ -2952,49 +3059,53 @@
 					}
 				  }
 				}
-#line 2956 "grammar.c" /* yacc.c:1646  */
+#line 3063 "grammar.c"
     break;
 
   case 142:
-#line 630 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_llc(cstate); }
-#line 2962 "grammar.c" /* yacc.c:1646  */
+#line 640 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_llc(cstate))); }
+#line 3069 "grammar.c"
     break;
 
   case 143:
-#line 631 "grammar.y" /* yacc.c:1646  */
-    { if (pcap_strcasecmp((yyvsp[0].s), "i") == 0)
-					(yyval.rblk) = gen_llc_i(cstate);
-				  else if (pcap_strcasecmp((yyvsp[0].s), "s") == 0)
-					(yyval.rblk) = gen_llc_s(cstate);
-				  else if (pcap_strcasecmp((yyvsp[0].s), "u") == 0)
-					(yyval.rblk) = gen_llc_u(cstate);
-				  else {
+#line 641 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s));
+				  if (pcap_strcasecmp((yyvsp[0].s), "i") == 0) {
+					CHECK_PTR_VAL(((yyval.rblk) = gen_llc_i(cstate)));
+				  } else if (pcap_strcasecmp((yyvsp[0].s), "s") == 0) {
+					CHECK_PTR_VAL(((yyval.rblk) = gen_llc_s(cstate)));
+				  } else if (pcap_strcasecmp((yyvsp[0].s), "u") == 0) {
+					CHECK_PTR_VAL(((yyval.rblk) = gen_llc_u(cstate)));
+				  } else {
 					int subtype;
 
 					subtype = str2tok((yyvsp[0].s), llc_s_subtypes);
-					if (subtype != -1)
-						(yyval.rblk) = gen_llc_s_subtype(cstate, subtype);
-					else {
+					if (subtype != -1) {
+						CHECK_PTR_VAL(((yyval.rblk) = gen_llc_s_subtype(cstate, subtype)));
+					} else {
 						subtype = str2tok((yyvsp[0].s), llc_u_subtypes);
-						if (subtype == -1)
-					  		bpf_error(cstate, "unknown LLC type name \"%s\"", (yyvsp[0].s));
-						(yyval.rblk) = gen_llc_u_subtype(cstate, subtype);
+						if (subtype == -1) {
+					  		bpf_set_error(cstate, "unknown LLC type name \"%s\"", (yyvsp[0].s));
+					  		YYABORT;
+					  	}
+						CHECK_PTR_VAL(((yyval.rblk) = gen_llc_u_subtype(cstate, subtype)));
 					}
 				  }
 				}
-#line 2987 "grammar.c" /* yacc.c:1646  */
+#line 3097 "grammar.c"
     break;
 
   case 144:
-#line 652 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_llc_s_subtype(cstate, LLC_RNR); }
-#line 2993 "grammar.c" /* yacc.c:1646  */
+#line 665 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.rblk) = gen_llc_s_subtype(cstate, LLC_RNR))); }
+#line 3103 "grammar.c"
     break;
 
   case 146:
-#line 656 "grammar.y" /* yacc.c:1646  */
-    { if (pcap_strcasecmp((yyvsp[0].s), "nods") == 0)
+#line 669 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s));
+				  if (pcap_strcasecmp((yyvsp[0].s), "nods") == 0)
 					(yyval.i) = IEEE80211_FC1_DIR_NODS;
 				  else if (pcap_strcasecmp((yyvsp[0].s), "tods") == 0)
 					(yyval.i) = IEEE80211_FC1_DIR_TODS;
@@ -3002,416 +3113,418 @@
 					(yyval.i) = IEEE80211_FC1_DIR_FROMDS;
 				  else if (pcap_strcasecmp((yyvsp[0].s), "dstods") == 0)
 					(yyval.i) = IEEE80211_FC1_DIR_DSTODS;
-				  else
-					bpf_error(cstate, "unknown 802.11 direction");
+				  else {
+					bpf_set_error(cstate, "unknown 802.11 direction");
+					YYABORT;
+				  }
 				}
-#line 3009 "grammar.c" /* yacc.c:1646  */
+#line 3122 "grammar.c"
     break;
 
   case 147:
-#line 669 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = (yyvsp[0].i); }
-#line 3015 "grammar.c" /* yacc.c:1646  */
+#line 685 "grammar.y"
+                                { (yyval.i) = (yyvsp[0].i); }
+#line 3128 "grammar.c"
     break;
 
   case 148:
-#line 670 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = pfreason_to_num(cstate, (yyvsp[0].s)); }
-#line 3021 "grammar.c" /* yacc.c:1646  */
+#line 686 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_INT_VAL(((yyval.i) = pfreason_to_num(cstate, (yyvsp[0].s)))); }
+#line 3134 "grammar.c"
     break;
 
   case 149:
-#line 673 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = pfaction_to_num(cstate, (yyvsp[0].s)); }
-#line 3027 "grammar.c" /* yacc.c:1646  */
+#line 689 "grammar.y"
+                                { CHECK_PTR_VAL((yyvsp[0].s)); CHECK_INT_VAL(((yyval.i) = pfaction_to_num(cstate, (yyvsp[0].s)))); }
+#line 3140 "grammar.c"
     break;
 
   case 150:
-#line 676 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JGT; }
-#line 3033 "grammar.c" /* yacc.c:1646  */
+#line 692 "grammar.y"
+                                { (yyval.i) = BPF_JGT; }
+#line 3146 "grammar.c"
     break;
 
   case 151:
-#line 677 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JGE; }
-#line 3039 "grammar.c" /* yacc.c:1646  */
+#line 693 "grammar.y"
+                                { (yyval.i) = BPF_JGE; }
+#line 3152 "grammar.c"
     break;
 
   case 152:
-#line 678 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JEQ; }
-#line 3045 "grammar.c" /* yacc.c:1646  */
+#line 694 "grammar.y"
+                                { (yyval.i) = BPF_JEQ; }
+#line 3158 "grammar.c"
     break;
 
   case 153:
-#line 680 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JGT; }
-#line 3051 "grammar.c" /* yacc.c:1646  */
+#line 696 "grammar.y"
+                                { (yyval.i) = BPF_JGT; }
+#line 3164 "grammar.c"
     break;
 
   case 154:
-#line 681 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JGE; }
-#line 3057 "grammar.c" /* yacc.c:1646  */
+#line 697 "grammar.y"
+                                { (yyval.i) = BPF_JGE; }
+#line 3170 "grammar.c"
     break;
 
   case 155:
-#line 682 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = BPF_JEQ; }
-#line 3063 "grammar.c" /* yacc.c:1646  */
+#line 698 "grammar.y"
+                                { (yyval.i) = BPF_JEQ; }
+#line 3176 "grammar.c"
     break;
 
   case 156:
-#line 684 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_loadi(cstate, (yyvsp[0].i)); }
-#line 3069 "grammar.c" /* yacc.c:1646  */
+#line 700 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.a) = gen_loadi(cstate, (yyvsp[0].i)))); }
+#line 3182 "grammar.c"
     break;
 
   case 158:
-#line 687 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_load(cstate, (yyvsp[-3].i), (yyvsp[-1].a), 1); }
-#line 3075 "grammar.c" /* yacc.c:1646  */
+#line 703 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_load(cstate, (yyvsp[-3].i), (yyvsp[-1].a), 1))); }
+#line 3188 "grammar.c"
     break;
 
   case 159:
-#line 688 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_load(cstate, (yyvsp[-5].i), (yyvsp[-3].a), (yyvsp[-1].i)); }
-#line 3081 "grammar.c" /* yacc.c:1646  */
+#line 704 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_load(cstate, (yyvsp[-5].i), (yyvsp[-3].a), (yyvsp[-1].i)))); }
+#line 3194 "grammar.c"
     break;
 
   case 160:
-#line 689 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_ADD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3087 "grammar.c" /* yacc.c:1646  */
+#line 705 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_ADD, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3200 "grammar.c"
     break;
 
   case 161:
-#line 690 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_SUB, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3093 "grammar.c" /* yacc.c:1646  */
+#line 706 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_SUB, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3206 "grammar.c"
     break;
 
   case 162:
-#line 691 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_MUL, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3099 "grammar.c" /* yacc.c:1646  */
+#line 707 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_MUL, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3212 "grammar.c"
     break;
 
   case 163:
-#line 692 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_DIV, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3105 "grammar.c" /* yacc.c:1646  */
+#line 708 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_DIV, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3218 "grammar.c"
     break;
 
   case 164:
-#line 693 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_MOD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3111 "grammar.c" /* yacc.c:1646  */
+#line 709 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_MOD, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3224 "grammar.c"
     break;
 
   case 165:
-#line 694 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_AND, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3117 "grammar.c" /* yacc.c:1646  */
+#line 710 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_AND, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3230 "grammar.c"
     break;
 
   case 166:
-#line 695 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_OR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3123 "grammar.c" /* yacc.c:1646  */
+#line 711 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_OR, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3236 "grammar.c"
     break;
 
   case 167:
-#line 696 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_XOR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3129 "grammar.c" /* yacc.c:1646  */
+#line 712 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_XOR, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3242 "grammar.c"
     break;
 
   case 168:
-#line 697 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_LSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3135 "grammar.c" /* yacc.c:1646  */
+#line 713 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_LSH, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3248 "grammar.c"
     break;
 
   case 169:
-#line 698 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(cstate, BPF_RSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3141 "grammar.c" /* yacc.c:1646  */
+#line 714 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_arth(cstate, BPF_RSH, (yyvsp[-2].a), (yyvsp[0].a)))); }
+#line 3254 "grammar.c"
     break;
 
   case 170:
-#line 699 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_neg(cstate, (yyvsp[0].a)); }
-#line 3147 "grammar.c" /* yacc.c:1646  */
+#line 715 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_neg(cstate, (yyvsp[0].a)))); }
+#line 3260 "grammar.c"
     break;
 
   case 171:
-#line 700 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = (yyvsp[-1].a); }
-#line 3153 "grammar.c" /* yacc.c:1646  */
+#line 716 "grammar.y"
+                                        { (yyval.a) = (yyvsp[-1].a); }
+#line 3266 "grammar.c"
     break;
 
   case 172:
-#line 701 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_loadlen(cstate); }
-#line 3159 "grammar.c" /* yacc.c:1646  */
+#line 717 "grammar.y"
+                                        { CHECK_PTR_VAL(((yyval.a) = gen_loadlen(cstate))); }
+#line 3272 "grammar.c"
     break;
 
   case 173:
-#line 703 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = '&'; }
-#line 3165 "grammar.c" /* yacc.c:1646  */
+#line 719 "grammar.y"
+                                { (yyval.i) = '&'; }
+#line 3278 "grammar.c"
     break;
 
   case 174:
-#line 704 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = '|'; }
-#line 3171 "grammar.c" /* yacc.c:1646  */
+#line 720 "grammar.y"
+                                { (yyval.i) = '|'; }
+#line 3284 "grammar.c"
     break;
 
   case 175:
-#line 705 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = '<'; }
-#line 3177 "grammar.c" /* yacc.c:1646  */
+#line 721 "grammar.y"
+                                { (yyval.i) = '<'; }
+#line 3290 "grammar.c"
     break;
 
   case 176:
-#line 706 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = '>'; }
-#line 3183 "grammar.c" /* yacc.c:1646  */
+#line 722 "grammar.y"
+                                { (yyval.i) = '>'; }
+#line 3296 "grammar.c"
     break;
 
   case 177:
-#line 707 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = '='; }
-#line 3189 "grammar.c" /* yacc.c:1646  */
+#line 723 "grammar.y"
+                                { (yyval.i) = '='; }
+#line 3302 "grammar.c"
     break;
 
   case 179:
-#line 710 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = (yyvsp[-1].i); }
-#line 3195 "grammar.c" /* yacc.c:1646  */
+#line 726 "grammar.y"
+                                { (yyval.i) = (yyvsp[-1].i); }
+#line 3308 "grammar.c"
     break;
 
   case 180:
-#line 712 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_LANE; }
-#line 3201 "grammar.c" /* yacc.c:1646  */
+#line 728 "grammar.y"
+                                { (yyval.i) = A_LANE; }
+#line 3314 "grammar.c"
     break;
 
   case 181:
-#line 713 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_METAC;	}
-#line 3207 "grammar.c" /* yacc.c:1646  */
+#line 729 "grammar.y"
+                                { (yyval.i) = A_METAC;	}
+#line 3320 "grammar.c"
     break;
 
   case 182:
-#line 714 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_BCC; }
-#line 3213 "grammar.c" /* yacc.c:1646  */
+#line 730 "grammar.y"
+                                { (yyval.i) = A_BCC; }
+#line 3326 "grammar.c"
     break;
 
   case 183:
-#line 715 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_OAMF4EC; }
-#line 3219 "grammar.c" /* yacc.c:1646  */
+#line 731 "grammar.y"
+                                { (yyval.i) = A_OAMF4EC; }
+#line 3332 "grammar.c"
     break;
 
   case 184:
-#line 716 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_OAMF4SC; }
-#line 3225 "grammar.c" /* yacc.c:1646  */
+#line 732 "grammar.y"
+                                { (yyval.i) = A_OAMF4SC; }
+#line 3338 "grammar.c"
     break;
 
   case 185:
-#line 717 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_SC; }
-#line 3231 "grammar.c" /* yacc.c:1646  */
+#line 733 "grammar.y"
+                                { (yyval.i) = A_SC; }
+#line 3344 "grammar.c"
     break;
 
   case 186:
-#line 718 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_ILMIC; }
-#line 3237 "grammar.c" /* yacc.c:1646  */
+#line 734 "grammar.y"
+                                { (yyval.i) = A_ILMIC; }
+#line 3350 "grammar.c"
     break;
 
   case 187:
-#line 720 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_OAM; }
-#line 3243 "grammar.c" /* yacc.c:1646  */
+#line 736 "grammar.y"
+                                { (yyval.i) = A_OAM; }
+#line 3356 "grammar.c"
     break;
 
   case 188:
-#line 721 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_OAMF4; }
-#line 3249 "grammar.c" /* yacc.c:1646  */
+#line 737 "grammar.y"
+                                { (yyval.i) = A_OAMF4; }
+#line 3362 "grammar.c"
     break;
 
   case 189:
-#line 722 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_CONNECTMSG; }
-#line 3255 "grammar.c" /* yacc.c:1646  */
+#line 738 "grammar.y"
+                                { (yyval.i) = A_CONNECTMSG; }
+#line 3368 "grammar.c"
     break;
 
   case 190:
-#line 723 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = A_METACONNECT; }
-#line 3261 "grammar.c" /* yacc.c:1646  */
+#line 739 "grammar.y"
+                                { (yyval.i) = A_METACONNECT; }
+#line 3374 "grammar.c"
     break;
 
   case 191:
-#line 726 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).atmfieldtype = A_VPI; }
-#line 3267 "grammar.c" /* yacc.c:1646  */
+#line 742 "grammar.y"
+                                { (yyval.blk).atmfieldtype = A_VPI; }
+#line 3380 "grammar.c"
     break;
 
   case 192:
-#line 727 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).atmfieldtype = A_VCI; }
-#line 3273 "grammar.c" /* yacc.c:1646  */
+#line 743 "grammar.y"
+                                { (yyval.blk).atmfieldtype = A_VCI; }
+#line 3386 "grammar.c"
     break;
 
   case 194:
-#line 730 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 0); }
-#line 3279 "grammar.c" /* yacc.c:1646  */
+#line 746 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 0))); }
+#line 3392 "grammar.c"
     break;
 
   case 195:
-#line 731 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 1); }
-#line 3285 "grammar.c" /* yacc.c:1646  */
+#line 747 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 1))); }
+#line 3398 "grammar.c"
     break;
 
   case 196:
-#line 732 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3291 "grammar.c" /* yacc.c:1646  */
+#line 748 "grammar.y"
+                                 { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
+#line 3404 "grammar.c"
     break;
 
   case 197:
-#line 734 "grammar.y" /* yacc.c:1646  */
-    {
+#line 750 "grammar.y"
+                   {
 	(yyval.blk).atmfieldtype = (yyvsp[-1].blk).atmfieldtype;
 	if ((yyval.blk).atmfieldtype == A_VPI ||
 	    (yyval.blk).atmfieldtype == A_VCI)
-		(yyval.blk).b = gen_atmfield_code(cstate, (yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[0].i), BPF_JEQ, 0);
+		CHECK_PTR_VAL(((yyval.blk).b = gen_atmfield_code(cstate, (yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[0].i), BPF_JEQ, 0)));
 	}
-#line 3302 "grammar.c" /* yacc.c:1646  */
+#line 3415 "grammar.c"
     break;
 
   case 199:
-#line 742 "grammar.y" /* yacc.c:1646  */
-    { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3308 "grammar.c" /* yacc.c:1646  */
+#line 758 "grammar.y"
+                                        { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 3421 "grammar.c"
     break;
 
   case 200:
-#line 745 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = M_FISU; }
-#line 3314 "grammar.c" /* yacc.c:1646  */
+#line 761 "grammar.y"
+                                { (yyval.i) = M_FISU; }
+#line 3427 "grammar.c"
     break;
 
   case 201:
-#line 746 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = M_LSSU; }
-#line 3320 "grammar.c" /* yacc.c:1646  */
+#line 762 "grammar.y"
+                                { (yyval.i) = M_LSSU; }
+#line 3433 "grammar.c"
     break;
 
   case 202:
-#line 747 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = M_MSU; }
-#line 3326 "grammar.c" /* yacc.c:1646  */
+#line 763 "grammar.y"
+                                { (yyval.i) = M_MSU; }
+#line 3439 "grammar.c"
     break;
 
   case 203:
-#line 748 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = MH_FISU; }
-#line 3332 "grammar.c" /* yacc.c:1646  */
+#line 764 "grammar.y"
+                                { (yyval.i) = MH_FISU; }
+#line 3445 "grammar.c"
     break;
 
   case 204:
-#line 749 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = MH_LSSU; }
-#line 3338 "grammar.c" /* yacc.c:1646  */
+#line 765 "grammar.y"
+                                { (yyval.i) = MH_LSSU; }
+#line 3451 "grammar.c"
     break;
 
   case 205:
-#line 750 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = MH_MSU; }
-#line 3344 "grammar.c" /* yacc.c:1646  */
+#line 766 "grammar.y"
+                                { (yyval.i) = MH_MSU; }
+#line 3457 "grammar.c"
     break;
 
   case 206:
-#line 753 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = M_SIO; }
-#line 3350 "grammar.c" /* yacc.c:1646  */
+#line 769 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = M_SIO; }
+#line 3463 "grammar.c"
     break;
 
   case 207:
-#line 754 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = M_OPC; }
-#line 3356 "grammar.c" /* yacc.c:1646  */
+#line 770 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = M_OPC; }
+#line 3469 "grammar.c"
     break;
 
   case 208:
-#line 755 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = M_DPC; }
-#line 3362 "grammar.c" /* yacc.c:1646  */
+#line 771 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = M_DPC; }
+#line 3475 "grammar.c"
     break;
 
   case 209:
-#line 756 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = M_SLS; }
-#line 3368 "grammar.c" /* yacc.c:1646  */
+#line 772 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = M_SLS; }
+#line 3481 "grammar.c"
     break;
 
   case 210:
-#line 757 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = MH_SIO; }
-#line 3374 "grammar.c" /* yacc.c:1646  */
+#line 773 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = MH_SIO; }
+#line 3487 "grammar.c"
     break;
 
   case 211:
-#line 758 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = MH_OPC; }
-#line 3380 "grammar.c" /* yacc.c:1646  */
+#line 774 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = MH_OPC; }
+#line 3493 "grammar.c"
     break;
 
   case 212:
-#line 759 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = MH_DPC; }
-#line 3386 "grammar.c" /* yacc.c:1646  */
+#line 775 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = MH_DPC; }
+#line 3499 "grammar.c"
     break;
 
   case 213:
-#line 760 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).mtp3fieldtype = MH_SLS; }
-#line 3392 "grammar.c" /* yacc.c:1646  */
+#line 776 "grammar.y"
+                                { (yyval.blk).mtp3fieldtype = MH_SLS; }
+#line 3505 "grammar.c"
     break;
 
   case 215:
-#line 763 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 0); }
-#line 3398 "grammar.c" /* yacc.c:1646  */
+#line 779 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 0))); }
+#line 3511 "grammar.c"
     break;
 
   case 216:
-#line 764 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 1); }
-#line 3404 "grammar.c" /* yacc.c:1646  */
+#line 780 "grammar.y"
+                                { CHECK_PTR_VAL(((yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 1))); }
+#line 3517 "grammar.c"
     break;
 
   case 217:
-#line 765 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3410 "grammar.c" /* yacc.c:1646  */
+#line 781 "grammar.y"
+                                  { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
+#line 3523 "grammar.c"
     break;
 
   case 218:
-#line 767 "grammar.y" /* yacc.c:1646  */
-    {
+#line 783 "grammar.y"
+                    {
 	(yyval.blk).mtp3fieldtype = (yyvsp[-1].blk).mtp3fieldtype;
 	if ((yyval.blk).mtp3fieldtype == M_SIO ||
 	    (yyval.blk).mtp3fieldtype == M_OPC ||
@@ -3421,19 +3534,20 @@
 	    (yyval.blk).mtp3fieldtype == MH_OPC ||
 	    (yyval.blk).mtp3fieldtype == MH_DPC ||
 	    (yyval.blk).mtp3fieldtype == MH_SLS)
-		(yyval.blk).b = gen_mtp3field_code(cstate, (yyval.blk).mtp3fieldtype, (u_int) (yyvsp[0].i), BPF_JEQ, 0);
+		CHECK_PTR_VAL(((yyval.blk).b = gen_mtp3field_code(cstate, (yyval.blk).mtp3fieldtype, (u_int) (yyvsp[0].i), BPF_JEQ, 0)));
 	}
-#line 3427 "grammar.c" /* yacc.c:1646  */
+#line 3540 "grammar.c"
     break;
 
   case 220:
-#line 781 "grammar.y" /* yacc.c:1646  */
-    { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3433 "grammar.c" /* yacc.c:1646  */
+#line 797 "grammar.y"
+                                          { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
+#line 3546 "grammar.c"
     break;
 
 
-#line 3437 "grammar.c" /* yacc.c:1646  */
+#line 3550 "grammar.c"
+
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -3458,14 +3572,13 @@
   /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
+  {
+    const int yylhs = yyr1[yyn] - YYNTOKENS;
+    const int yyi = yypgoto[yylhs] + *yyssp;
+    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+               ? yytable[yyi]
+               : yydefgoto[yylhs]);
+  }
 
   goto yynewstate;
 
@@ -3497,7 +3610,7 @@
           {
             if (yymsg != yymsgbuf)
               YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            yymsg = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
             if (!yymsg)
               {
                 yymsg = yymsgbuf;
@@ -3548,12 +3661,10 @@
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
 yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
+  /* Pacify compilers when the user code never invokes YYERROR and the
+     label yyerrorlab therefore never appears in user code.  */
+  if (0)
+    YYERROR;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -3615,6 +3726,7 @@
   yyresult = 0;
   goto yyreturn;
 
+
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
@@ -3622,6 +3734,7 @@
   yyresult = 1;
   goto yyreturn;
 
+
 #if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
@@ -3632,6 +3745,10 @@
   /* Fall through.  */
 #endif
 
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result.  |
+`-----------------------------------------------------*/
 yyreturn:
   if (yychar != YYEMPTY)
     {
@@ -3648,7 +3765,7 @@
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp, yyscanner, cstate);
+                  yystos[+*yyssp], yyvsp, yyscanner, cstate);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -3661,5 +3778,5 @@
 #endif
   return yyresult;
 }
-#line 783 "grammar.y" /* yacc.c:1906  */
+#line 799 "grammar.y"
 
diff --git a/grammar.h b/grammar.h
index 286cc79..b4cfd19 100644
--- a/grammar.h
+++ b/grammar.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.5.1.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_PCAP_GRAMMAR_H_INCLUDED
 # define YY_PCAP_GRAMMAR_H_INCLUDED
 /* Debug traces.  */
@@ -161,9 +165,10 @@
     HOPC = 371,
     HDPC = 372,
     HSLS = 373,
-    OR = 374,
-    AND = 375,
-    UMINUS = 376
+    LEX_ERROR = 374,
+    OR = 375,
+    AND = 376,
+    UMINUS = 377
   };
 #endif
 /* Tokens.  */
@@ -283,20 +288,19 @@
 #define HOPC 371
 #define HDPC 372
 #define HSLS 373
-#define OR 374
-#define AND 375
-#define UMINUS 376
+#define LEX_ERROR 374
+#define OR 375
+#define AND 376
+#define UMINUS 377
 
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
 union YYSTYPE
 {
-#line 286 "grammar.y" /* yacc.c:1909  */
+#line 291 "grammar.y"
 
 	int i;
 	bpf_u_int32 h;
-	u_char *e;
 	char *s;
 	struct stmt *stmt;
 	struct arth *a;
@@ -308,9 +312,9 @@
 	} blk;
 	struct block *rblk;
 
-#line 312 "grammar.h" /* yacc.c:1909  */
-};
+#line 316 "grammar.h"
 
+};
 typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
diff --git a/grammar.y b/grammar.y.in
similarity index 61%
rename from grammar.y
rename to grammar.y.in
index be80e2b..fe56515 100644
--- a/grammar.y
+++ b/grammar.y.in
@@ -1,7 +1,7 @@
 /*
  * We want a reentrant parser.
  */
-%pure-parser
+@REENTRANT_PARSER@
 
 /*
  * We also want a reentrant scanner, so we have to pass the
@@ -19,6 +19,27 @@
 %lex-param   {void *yyscanner}
 
 /*
+ * According to bison documentation, shift/reduce conflicts are not an issue
+ * in most parsers as long as the number does not evolve over time:
+ * https://www.gnu.org/software/bison/manual/html_node/Expect-Decl.html
+ * So, following the advice use %expect to check the amount of shift/reduce
+ * warnings.
+ *
+ * This doesn't appear to work in Berkeley YACC - 1.9 20170709; it still
+ * warns of 38 shift/reduce conflicts.
+ *
+ * The Berkeley YACC documentation:
+ *
+ *    https://invisible-island.net/byacc/manpage/yacc.html
+ *
+ * claims that "Bison's support for "%expect" is broken in more than one
+ * release.", but doesn't give details.  Hopefully, that only means that
+ * you get warnings even if you have the expected number of shift/reduce
+ * conflicts, not that anything else fails.
+ */
+%expect 38
+
+/*
  * And we need to pass the compiler state to the scanner.
  */
 %parse-param { compiler_state_t *cstate }
@@ -210,19 +231,27 @@
 	int i;
 
 	for (i = 0; toks[i].s != NULL; i++) {
-		if (pcap_strcasecmp(toks[i].s, str) == 0)
+		if (pcap_strcasecmp(toks[i].s, str) == 0) {
+			/*
+			 * Just in case somebody is using this to
+			 * generate values of -1/0xFFFFFFFF.
+			 * That won't work, as it's indistinguishable
+			 * from an error.
+			 */
+			if (toks[i].v == -1)
+				abort();
 			return (toks[i].v);
+		}
 	}
 	return (-1);
 }
 
-static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+static const struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
-static PCAP_NORETURN_DEF void
+static void
 yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
 {
-	bpf_syntax_error(cstate, msg);
-	/* NOTREACHED */
+	bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
 #ifdef HAVE_NET_PFVAR_H
@@ -236,8 +265,8 @@
 		if (pcap_strcasecmp(reason, reasons[i]) == 0)
 			return (i);
 	}
-	bpf_error(cstate, "unknown PF reason");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
+	return (-1);
 }
 
 static int
@@ -260,33 +289,38 @@
 		return (PF_NORDR);
 #endif
 	else {
-		bpf_error(cstate, "unknown PF action");
-		/*NOTREACHED*/
+		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
+		return (-1);
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
-static PCAP_NORETURN_DEF int
+static int
 pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
 {
-	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+	return (-1);
 }
 
-static PCAP_NORETURN_DEF int
+static int
 pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
 {
-	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-	/*NOTREACHED*/
+	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+	return (-1);
 }
 #endif /* HAVE_NET_PFVAR_H */
 
+/*
+ * For calls that might return an "an error occurred" value.
+ */
+#define CHECK_INT_VAL(val)	if (val == -1) YYABORT
+#define CHECK_PTR_VAL(val)	if (val == NULL) YYABORT
+
 DIAG_OFF_BISON_BYACC
 %}
 
 %union {
 	int i;
 	bpf_u_int32 h;
-	u_char *e;
 	char *s;
 	struct stmt *stmt;
 	struct arth *a;
@@ -303,7 +337,8 @@
 %type	<blk>	head
 %type	<i>	pqual dqual aqual ndaqual
 %type	<a>	arth narth
-%type	<i>	byteop pname pnum relop irelop
+%type	<i>	byteop pname relop irelop
+%type	<h>	pnum
 %type	<blk>	and or paren not null prog
 %type	<rblk>	other pfvar p80211 pllc
 %type	<i>	atmtype atmmultitype
@@ -320,6 +355,7 @@
 %token  ATALK AARP DECNET LAT SCA MOPRC MOPDL
 %token  TK_BROADCAST TK_MULTICAST
 %token  NUM INBOUND OUTBOUND
+%token  IFINDEX
 %token  PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
 %token	TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
 %token  LINK
@@ -340,13 +376,12 @@
 %token	RADIO
 %token	FISU LSSU MSU HFISU HLSSU HMSU
 %token	SIO OPC DPC SLS HSIO HOPC HDPC HSLS
+%token	LEX_ERROR
 
-
-%type	<s> ID
-%type	<e> EID
-%type	<e> AID
+%type	<s> ID EID AID
 %type	<s> HID HID6
-%type	<i> NUM action reason type subtype type_subtype dir
+%type	<h> NUM
+%type	<i> action reason type subtype type_subtype dir
 
 %left OR AND
 %nonassoc  '!'
@@ -359,7 +394,7 @@
 %%
 prog:	  null expr
 {
-	finish_parse(cstate, $2.b);
+	CHECK_INT_VAL(finish_parse(cstate, $2.b));
 }
 	| null
 	;
@@ -376,64 +411,58 @@
 or:	  OR			{ $$ = $<blk>0; }
 	;
 id:	  nid
-	| pnum			{ $$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
-						   $$.q = $<blk>0.q); }
+	| pnum			{ CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, $1,
+						   $$.q = $<blk>0.q))); }
 	| paren pid ')'		{ $$ = $2; }
 	;
-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(cstate, $1, $3, 0,
-				    $$.q = $<blk>0.q); }
+nid:	  ID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q))); }
+	| HID '/' NUM		{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, NULL, $3,
+				    $$.q = $<blk>0.q))); }
+	| HID NETMASK HID	{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, $3, 0,
+				    $$.q = $<blk>0.q))); }
 	| HID			{
+				  CHECK_PTR_VAL($1);
 				  /* Decide how to parse HID based on proto */
 				  $$.q = $<blk>0.q;
-				  if ($$.q.addr == Q_PORT)
-				  	bpf_error(cstate, "'port' modifier applied to ip host");
-				  else if ($$.q.addr == Q_PORTRANGE)
-				  	bpf_error(cstate, "'portrange' modifier applied to ip host");
-				  else if ($$.q.addr == Q_PROTO)
-				  	bpf_error(cstate, "'proto' modifier applied to ip host");
-				  else if ($$.q.addr == Q_PROTOCHAIN)
-				  	bpf_error(cstate, "'protochain' modifier applied to ip host");
-				  $$.b = gen_ncode(cstate, $1, 0, $$.q);
+				  if ($$.q.addr == Q_PORT) {
+					bpf_set_error(cstate, "'port' modifier applied to ip host");
+					YYABORT;
+				  } else if ($$.q.addr == Q_PORTRANGE) {
+					bpf_set_error(cstate, "'portrange' modifier applied to ip host");
+					YYABORT;
+				  } else if ($$.q.addr == Q_PROTO) {
+					bpf_set_error(cstate, "'proto' modifier applied to ip host");
+					YYABORT;
+				  } else if ($$.q.addr == Q_PROTOCHAIN) {
+					bpf_set_error(cstate, "'protochain' modifier applied to ip host");
+					YYABORT;
+				  }
+				  CHECK_PTR_VAL(($$.b = gen_ncode(cstate, $1, 0, $$.q)));
 				}
 	| HID6 '/' NUM		{
+				  CHECK_PTR_VAL($1);
 #ifdef INET6
-				  $$.b = gen_mcode6(cstate, $1, NULL, $3,
-				    $$.q = $<blk>0.q);
+				  CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, NULL, $3,
+				    $$.q = $<blk>0.q)));
 #else
-				  bpf_error(cstate, "'ip6addr/prefixlen' not supported "
+				  bpf_set_error(cstate, "'ip6addr/prefixlen' not supported "
 					"in this configuration");
+				  YYABORT;
 #endif /*INET6*/
 				}
 	| HID6			{
+				  CHECK_PTR_VAL($1);
 #ifdef INET6
-				  $$.b = gen_mcode6(cstate, $1, 0, 128,
-				    $$.q = $<blk>0.q);
+				  CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, 0, 128,
+				    $$.q = $<blk>0.q)));
 #else
-				  bpf_error(cstate, "'ip6addr' not supported "
+				  bpf_set_error(cstate, "'ip6addr' not supported "
 					"in this configuration");
+				  YYABORT;
 #endif /*INET6*/
 				}
-	| EID			{
-				  $$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q);
-				  /*
-				   * $1 was allocated by "pcap_ether_aton()",
-				   * so we must free it now that we're done
-				   * with it.
-				   */
-				  free($1);
-				}
-	| AID			{
-				  $$.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
-				   * with it.
-				   */
-				  free($1);
-				}
+	| EID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q))); }
+	| AID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q))); }
 	| not id		{ gen_not($2.b); $$ = $2; }
 	;
 not:	  '!'			{ $$ = $<blk>0; }
@@ -444,8 +473,8 @@
 	| 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(cstate, NULL, (bpf_u_int32)$1,
-						   $$.q = $<blk>0.q); }
+qid:	  pnum			{ CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, $1,
+						   $$.q = $<blk>0.q))); }
 	| pid
 	;
 term:	  rterm
@@ -455,21 +484,28 @@
 	| pqual dqual		{ QSET($$.q, $1, $2, Q_DEFAULT); }
 	| pqual aqual		{ QSET($$.q, $1, Q_DEFAULT, $2); }
 	| pqual PROTO		{ QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
-	| pqual PROTOCHAIN	{ QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); }
+	| pqual PROTOCHAIN	{
+#ifdef NO_PROTOCHAIN
+				  bpf_set_error(cstate, "protochain not supported");
+				  YYABORT;
+#else
+				  QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN);
+#endif
+				}
 	| pqual ndaqual		{ QSET($$.q, $1, Q_DEFAULT, $2); }
 	;
 rterm:	  head id		{ $$ = $2; }
 	| paren expr ')'	{ $$.b = $2.b; $$.q = $1.q; }
-	| pname			{ $$.b = gen_proto_abbrev(cstate, $1); $$.q = qerr; }
-	| arth relop arth	{ $$.b = gen_relation(cstate, $2, $1, $3, 0);
+	| pname			{ CHECK_PTR_VAL(($$.b = gen_proto_abbrev(cstate, $1))); $$.q = qerr; }
+	| arth relop arth	{ CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 0)));
 				  $$.q = qerr; }
-	| arth irelop arth	{ $$.b = gen_relation(cstate, $2, $1, $3, 1);
+	| arth irelop arth	{ CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 1)));
 				  $$.q = qerr; }
 	| other			{ $$.b = $1; $$.q = qerr; }
-	| atmtype		{ $$.b = gen_atmtype_abbrev(cstate, $1); $$.q = qerr; }
-	| atmmultitype		{ $$.b = gen_atmmulti_abbrev(cstate, $1); $$.q = qerr; }
+	| atmtype		{ CHECK_PTR_VAL(($$.b = gen_atmtype_abbrev(cstate, $1))); $$.q = qerr; }
+	| atmmultitype		{ CHECK_PTR_VAL(($$.b = gen_atmmulti_abbrev(cstate, $1))); $$.q = qerr; }
 	| atmfield atmvalue	{ $$.b = $2.b; $$.q = qerr; }
-	| mtp2type		{ $$.b = gen_mtp2type_abbrev(cstate, $1); $$.q = qerr; }
+	| mtp2type		{ CHECK_PTR_VAL(($$.b = gen_mtp2type_abbrev(cstate, $1))); $$.q = qerr; }
 	| mtp3field mtp3value	{ $$.b = $2.b; $$.q = qerr; }
 	;
 /* protocol level qualifiers */
@@ -511,7 +547,7 @@
 	| IGRP			{ $$ = Q_IGRP; }
 	| PIM			{ $$ = Q_PIM; }
 	| VRRP			{ $$ = Q_VRRP; }
-	| CARP 			{ $$ = Q_CARP; }
+	| CARP			{ $$ = Q_CARP; }
 	| ATALK			{ $$ = Q_ATALK; }
 	| AARP			{ $$ = Q_AARP; }
 	| DECNET		{ $$ = Q_DECNET; }
@@ -539,84 +575,102 @@
 	| NETBEUI		{ $$ = Q_NETBEUI; }
 	| RADIO			{ $$ = Q_RADIO; }
 	;
-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); }
+other:	  pqual TK_BROADCAST	{ CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
+	| pqual TK_MULTICAST	{ CHECK_PTR_VAL(($$ = gen_multicast(cstate, $1))); }
+	| LESS NUM		{ CHECK_PTR_VAL(($$ = gen_less(cstate, $2))); }
+	| GREATER NUM		{ CHECK_PTR_VAL(($$ = gen_greater(cstate, $2))); }
+	| CBYTE NUM byteop NUM	{ CHECK_PTR_VAL(($$ = gen_byteop(cstate, $3, $2, $4))); }
+	| INBOUND		{ CHECK_PTR_VAL(($$ = gen_inbound(cstate, 0))); }
+	| OUTBOUND		{ CHECK_PTR_VAL(($$ = gen_inbound(cstate, 1))); }
+	| IFINDEX NUM		{ CHECK_PTR_VAL(($$ = gen_ifindex(cstate, $2))); }
+	| VLAN pnum		{ CHECK_PTR_VAL(($$ = gen_vlan(cstate, $2, 1))); }
+	| VLAN			{ CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
+	| MPLS pnum		{ CHECK_PTR_VAL(($$ = gen_mpls(cstate, $2, 1))); }
+	| MPLS			{ CHECK_PTR_VAL(($$ = gen_mpls(cstate, 0, 0))); }
+	| PPPOED		{ CHECK_PTR_VAL(($$ = gen_pppoed(cstate))); }
+	| PPPOES pnum		{ CHECK_PTR_VAL(($$ = gen_pppoes(cstate, $2, 1))); }
+	| PPPOES		{ CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }
+	| GENEVE pnum		{ CHECK_PTR_VAL(($$ = gen_geneve(cstate, $2, 1))); }
+	| GENEVE		{ CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); }
 	| pfvar			{ $$ = $1; }
 	| pqual p80211		{ $$ = $2; }
 	| pllc			{ $$ = $1; }
 	;
 
-pfvar:	  PF_IFNAME ID		{ $$ = gen_pf_ifname(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); }
+pfvar:	  PF_IFNAME ID		{ CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); }
+	| PF_RSET ID		{ CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); }
+	| PF_RNR NUM		{ CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); }
+	| PF_SRNR NUM		{ CHECK_PTR_VAL(($$ = gen_pf_srnr(cstate, $2))); }
+	| PF_REASON reason	{ CHECK_PTR_VAL(($$ = gen_pf_reason(cstate, $2))); }
+	| PF_ACTION action	{ CHECK_PTR_VAL(($$ = gen_pf_action(cstate, $2))); }
 	;
 
 p80211:   TYPE type SUBTYPE subtype
-				{ $$ = gen_p80211_type(cstate, $2 | $4,
+				{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2 | $4,
 					IEEE80211_FC0_TYPE_MASK |
-					IEEE80211_FC0_SUBTYPE_MASK);
+					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
-	| TYPE type		{ $$ = gen_p80211_type(cstate, $2,
-					IEEE80211_FC0_TYPE_MASK);
+	| TYPE type		{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
+					IEEE80211_FC0_TYPE_MASK)));
 				}
-	| SUBTYPE type_subtype	{ $$ = gen_p80211_type(cstate, $2,
+	| SUBTYPE type_subtype	{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
 					IEEE80211_FC0_TYPE_MASK |
-					IEEE80211_FC0_SUBTYPE_MASK);
+					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
-	| DIR dir		{ $$ = gen_p80211_fcdir(cstate, $2); }
+	| DIR dir		{ CHECK_PTR_VAL(($$ = gen_p80211_fcdir(cstate, $2))); }
 	;
 
-type:	  NUM
-	| ID			{ $$ = str2tok($1, ieee80211_types);
-				  if ($$ == -1)
-				  	bpf_error(cstate, "unknown 802.11 type name");
+type:	  NUM			{ if (($1 & (~IEEE80211_FC0_TYPE_MASK)) != 0) {
+					bpf_set_error(cstate, "invalid 802.11 type value 0x%02x", $1);
+					YYABORT;
+				  }
+				  $$ = (int)$1;
+				}
+	| ID			{ CHECK_PTR_VAL($1);
+				  $$ = str2tok($1, ieee80211_types);
+				  if ($$ == -1) {
+					bpf_set_error(cstate, "unknown 802.11 type name \"%s\"", $1);
+					YYABORT;
+				  }
 				}
 	;
 
-subtype:  NUM
+subtype:  NUM			{ if (($1 & (~IEEE80211_FC0_SUBTYPE_MASK)) != 0) {
+					bpf_set_error(cstate, "invalid 802.11 subtype value 0x%02x", $1);
+					YYABORT;
+				  }
+				  $$ = (int)$1;
+				}
 	| ID			{ const struct tok *types = NULL;
 				  int i;
+				  CHECK_PTR_VAL($1);
 				  for (i = 0;; i++) {
-				  	if (ieee80211_type_subtypes[i].tok == NULL) {
-				  		/* Ran out of types */
-						bpf_error(cstate, "unknown 802.11 type");
-						break;
+					if (ieee80211_type_subtypes[i].tok == NULL) {
+						/* Ran out of types */
+						bpf_set_error(cstate, "unknown 802.11 type");
+						YYABORT;
 					}
-					if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+					if (-1 == ieee80211_type_subtypes[i].type) {
 						types = ieee80211_type_subtypes[i].tok;
 						break;
 					}
 				  }
 
 				  $$ = str2tok($1, types);
-				  if ($$ == -1)
-					bpf_error(cstate, "unknown 802.11 subtype name");
+				  if ($$ == -1) {
+					bpf_set_error(cstate, "unknown 802.11 subtype name \"%s\"", $1);
+					YYABORT;
+				  }
 				}
 	;
 
 type_subtype:	ID		{ int i;
+				  CHECK_PTR_VAL($1);
 				  for (i = 0;; i++) {
-				  	if (ieee80211_type_subtypes[i].tok == NULL) {
-				  		/* Ran out of types */
-						bpf_error(cstate, "unknown 802.11 type name");
-						break;
+					if (ieee80211_type_subtypes[i].tok == NULL) {
+						/* Ran out of types */
+						bpf_set_error(cstate, "unknown 802.11 type name");
+						YYABORT;
 					}
 					$$ = str2tok($1, ieee80211_type_subtypes[i].tok);
 					if ($$ != -1) {
@@ -627,33 +681,37 @@
 				}
 		;
 
-pllc:	LLC			{ $$ = gen_llc(cstate); }
-	| LLC ID		{ if (pcap_strcasecmp($2, "i") == 0)
-					$$ = gen_llc_i(cstate);
-				  else if (pcap_strcasecmp($2, "s") == 0)
-					$$ = gen_llc_s(cstate);
-				  else if (pcap_strcasecmp($2, "u") == 0)
-					$$ = gen_llc_u(cstate);
-				  else {
+pllc:	LLC			{ CHECK_PTR_VAL(($$ = gen_llc(cstate))); }
+	| LLC ID		{ CHECK_PTR_VAL($2);
+				  if (pcap_strcasecmp($2, "i") == 0) {
+					CHECK_PTR_VAL(($$ = gen_llc_i(cstate)));
+				  } else if (pcap_strcasecmp($2, "s") == 0) {
+					CHECK_PTR_VAL(($$ = gen_llc_s(cstate)));
+				  } else if (pcap_strcasecmp($2, "u") == 0) {
+					CHECK_PTR_VAL(($$ = gen_llc_u(cstate)));
+				  } else {
 					int subtype;
 
 					subtype = str2tok($2, llc_s_subtypes);
-					if (subtype != -1)
-						$$ = gen_llc_s_subtype(cstate, subtype);
-					else {
+					if (subtype != -1) {
+						CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, subtype)));
+					} else {
 						subtype = str2tok($2, llc_u_subtypes);
-						if (subtype == -1)
-					  		bpf_error(cstate, "unknown LLC type name \"%s\"", $2);
-						$$ = gen_llc_u_subtype(cstate, subtype);
+						if (subtype == -1) {
+							bpf_set_error(cstate, "unknown LLC type name \"%s\"", $2);
+							YYABORT;
+						}
+						CHECK_PTR_VAL(($$ = gen_llc_u_subtype(cstate, subtype)));
 					}
 				  }
 				}
 				/* sigh, "rnr" is already a keyword for PF */
-	| LLC PF_RNR		{ $$ = gen_llc_s_subtype(cstate, LLC_RNR); }
+	| LLC PF_RNR		{ CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, LLC_RNR))); }
 	;
 
-dir:	  NUM
-	| ID			{ if (pcap_strcasecmp($1, "nods") == 0)
+dir:	  NUM			{ $$ = (int)$1; }
+	| ID			{ CHECK_PTR_VAL($1);
+				  if (pcap_strcasecmp($1, "nods") == 0)
 					$$ = IEEE80211_FC1_DIR_NODS;
 				  else if (pcap_strcasecmp($1, "tods") == 0)
 					$$ = IEEE80211_FC1_DIR_TODS;
@@ -661,16 +719,18 @@
 					$$ = IEEE80211_FC1_DIR_FROMDS;
 				  else if (pcap_strcasecmp($1, "dstods") == 0)
 					$$ = IEEE80211_FC1_DIR_DSTODS;
-				  else
-					bpf_error(cstate, "unknown 802.11 direction");
+				  else {
+					bpf_set_error(cstate, "unknown 802.11 direction");
+					YYABORT;
+				  }
 				}
 	;
 
 reason:	  NUM			{ $$ = $1; }
-	| ID			{ $$ = pfreason_to_num(cstate, $1); }
+	| ID			{ CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfreason_to_num(cstate, $1))); }
 	;
 
-action:	  ID			{ $$ = pfaction_to_num(cstate, $1); }
+action:	  ID			{ CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfaction_to_num(cstate, $1))); }
 	;
 
 relop:	  '>'			{ $$ = BPF_JGT; }
@@ -681,24 +741,24 @@
 	| '<'			{ $$ = BPF_JGE; }
 	| NEQ			{ $$ = BPF_JEQ; }
 	;
-arth:	  pnum			{ $$ = gen_loadi(cstate, $1); }
+arth:	  pnum			{ CHECK_PTR_VAL(($$ = gen_loadi(cstate, $1))); }
 	| narth
 	;
-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); }
+narth:	  pname '[' arth ']'		{ CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, 1))); }
+	| pname '[' arth ':' NUM ']'	{ CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, $5))); }
+	| arth '+' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_ADD, $1, $3))); }
+	| arth '-' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_SUB, $1, $3))); }
+	| arth '*' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MUL, $1, $3))); }
+	| arth '/' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_DIV, $1, $3))); }
+	| arth '%' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MOD, $1, $3))); }
+	| arth '&' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_AND, $1, $3))); }
+	| arth '|' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_OR, $1, $3))); }
+	| arth '^' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_XOR, $1, $3))); }
+	| arth LSH arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_LSH, $1, $3))); }
+	| arth RSH arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_RSH, $1, $3))); }
+	| '-' arth %prec UMINUS		{ CHECK_PTR_VAL(($$ = gen_neg(cstate, $2))); }
 	| paren narth ')'		{ $$ = $2; }
-	| LEN				{ $$ = gen_loadlen(cstate); }
+	| LEN				{ CHECK_PTR_VAL(($$ = gen_loadlen(cstate))); }
 	;
 byteop:	  '&'			{ $$ = '&'; }
 	| '|'			{ $$ = '|'; }
@@ -727,15 +787,15 @@
 	| VCI			{ $$.atmfieldtype = A_VCI; }
 	;
 atmvalue: atmfieldvalue
-	| 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); }
+	| relop NUM		{ CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, $2, $1, 0))); }
+	| irelop NUM		{ CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, $2, $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(cstate, $$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
+		CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $$.atmfieldtype, $1, BPF_JEQ, 0)));
 	}
 	;
 atmlistvalue: atmfieldvalue
@@ -760,8 +820,8 @@
 	| HSLS                  { $$.mtp3fieldtype = MH_SLS; }
 	;
 mtp3value: mtp3fieldvalue
-	| 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); }
+	| relop NUM		{ CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, $2, $1, 0))); }
+	| irelop NUM		{ CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, $2, $1, 1))); }
 	| paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
 	;
 mtp3fieldvalue: NUM {
@@ -774,7 +834,7 @@
 	    $$.mtp3fieldtype == MH_OPC ||
 	    $$.mtp3fieldtype == MH_DPC ||
 	    $$.mtp3fieldtype == MH_SLS)
-		$$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+		CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, $1, BPF_JEQ, 0)));
 	}
 	;
 mtp3listvalue: mtp3fieldvalue
diff --git a/lbl/os-osf4.h b/lbl/os-osf4.h
index 055eb80..f461eea 100644
--- a/lbl/os-osf4.h
+++ b/lbl/os-osf4.h
@@ -20,7 +20,7 @@
  */
 
 /* Prototypes missing in Digital UNIX 4.x */
-int	pcap_snprintf(char *, size_t, const char *, ...);
-int	pcap_vsnprintf(char *, size_t, const char *, va_list);
+int	snprintf(char *, size_t, const char *, ...);
+int	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 5422f18..52ab175 100644
--- a/lbl/os-osf5.h
+++ b/lbl/os-osf5.h
@@ -21,10 +21,10 @@
 
 /*
  * Prototypes missing in Tru64 UNIX 5.x
- * XXX - "pcap_snprintf()" and "pcap_vsnprintf()" aren't missing, but you have to
+ * XXX - "snprintf()" and "vsnprintf()" aren't missing, but you have to
  * #define the right value to get them defined by <stdio.h>.
  */
-int	pcap_snprintf(char *, size_t, const char *, ...);
-int	pcap_vsnprintf(char *, size_t, const char *, va_list);
+int	snprintf(char *, size_t, const char *, ...);
+int	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 a555f5e..22948b4 100644
--- a/lbl/os-solaris2.h
+++ b/lbl/os-solaris2.h
@@ -21,4 +21,4 @@
 
 /* Prototypes missing in SunOS 5 */
 char    *strerror(int);
-int	pcap_snprintf(char *, size_t, const char *, ...);
+int	snprintf(char *, size_t, const char *, ...);
diff --git a/lbl/os-sunos4.h b/lbl/os-sunos4.h
index 6353fb0..ab032ef 100644
--- a/lbl/os-sunos4.h
+++ b/lbl/os-sunos4.h
@@ -155,7 +155,7 @@
 struct	sigvec;
 #endif
 int	sigvec(int, struct sigvec *, struct sigvec*);
-int	pcap_snprintf(char *, size_t, const char *, ...);
+int	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/missing/asprintf.c b/missing/asprintf.c
new file mode 100644
index 0000000..3aa55ed
--- /dev/null
+++ b/missing/asprintf.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * vasprintf() and asprintf() for platforms with a C99-compliant
+ * snprintf() - so that, if you format into a 1-byte buffer, it
+ * will return how many characters it would have produced had
+ * it been given an infinite-sized buffer.
+ */
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+	char buf;
+	int len;
+	size_t str_size;
+	char *str;
+	int ret;
+
+	/*
+	 * XXX - the C99 standard says, in section 7.19.6.5 "Thes
+	 * nprintf function":
+	 *
+	 *    The snprintf function is equivalent to fprintf, except that
+	 *    the output is written into an array (specified by argument s)
+	 *    rather than to a stream.  If n is zero, nothing is written,
+	 *    and s may be a null pointer.  Otherwise, output characters
+	 *    beyond the n-1st are discarded rather than being written
+	 *    to the array, and a null character is written at the end
+	 *    of the characters actually written into the array.
+	 *
+	 *        ...
+	 *
+	 *    The snprintf function returns the number of characters that
+	 *    would have been written had n been sufficiently large, not
+	 *    counting the terminating null character, or a negative value
+	 *    if an encoding error occurred. Thus, the null-terminated
+	 *    output has been completely written if and only if the returned
+	 *    value is nonnegative and less than n.
+	 *
+	 * That doesn't make it entirely clear whether, if a null buffer
+	 * pointer and a zero count are passed, it will return the number
+	 * of characters that would have been written had a buffer been
+	 * passed.
+	 *
+	 * And, even if C99 *does*, in fact, say it has to work, it
+	 * doesn't work in Solaris 8, for example - it returns -1 for
+	 * NULL/0, but returns the correct character count for a 1-byte
+	 * buffer.
+	 *
+	 * So we pass a one-character pointer in order to find out how
+	 * many characters this format and those arguments will need
+	 * without actually generating any more of those characters
+	 * than we need.
+	 *
+	 * (The fact that it might happen to work with GNU libc or with
+	 * various BSD libcs is completely uninteresting, as those tend
+	 * to have asprintf() already and thus don't even *need* this
+	 * code; this is for use in those UN*Xes that *don't* have
+	 * asprintf().)
+	 */
+	len = vsnprintf(&buf, sizeof buf, format, args);
+	if (len == -1) {
+		*strp = NULL;
+		return (-1);
+	}
+	str_size = len + 1;
+	str = malloc(str_size);
+	if (str == NULL) {
+		*strp = NULL;
+		return (-1);
+	}
+	ret = vsnprintf(str, str_size, format, args);
+	if (ret == -1) {
+		free(str);
+		*strp = NULL;
+		return (-1);
+	}
+	*strp = str;
+	/*
+	 * vsnprintf() shouldn't truncate the string, as we have
+	 * allocated a buffer large enough to hold the string, so its
+	 * return value should be the number of characters written.
+	 */
+	return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, format);
+	ret = pcap_vasprintf(strp, format, args);
+	va_end(args);
+	return (ret);
+}
+
diff --git a/missing/getopt.c b/missing/getopt.c
index 7c897c6..c535776 100644
--- a/missing/getopt.c
+++ b/missing/getopt.c
@@ -80,9 +80,18 @@
 			place = EMSG;
 			return (-1);
 		}
-	}					/* option letter okay? */
-	if ((optopt = (int)*place++) == (int)':' ||
-	    !(oli = strchr(ostr, optopt))) {
+	}
+	optopt = (int)*place++;
+	if (optopt == (int)':') {		/* option letter okay? */
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname, optopt);
+		return (BADCH);
+	}
+	oli = strchr(ostr, optopt);
+	if (!oli) {
 		/*
 		 * if the user didn't specify '-' as an option,
 		 * assume it means -1.
@@ -114,7 +123,7 @@
 				    __progname, optopt);
 			return (BADCH);
 		}
-	 	else				/* white space */
+		else				/* white space */
 			optarg = nargv[optind];
 		place = EMSG;
 		++optind;
diff --git a/missing/snprintf.c b/missing/snprintf.c
deleted file mode 100644
index 99f0bdf..0000000
--- a/missing/snprintf.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (c) 1995-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. 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-
-#include <pcap-int.h>
-
-enum format_flags {
-    minus_flag     =  1,
-    plus_flag      =  2,
-    space_flag     =  4,
-    alternate_flag =  8,
-    zero_flag      = 16
-};
-
-/*
- * Common state
- */
-
-struct state {
-  unsigned char *str;
-  unsigned char *s;
-  unsigned char *theend;
-  size_t sz;
-  size_t max_sz;
-  int (*append_char)(struct state *, unsigned char);
-  int (*reserve)(struct state *, size_t);
-  /* XXX - methods */
-};
-
-#ifndef HAVE_VSNPRINTF
-static int
-sn_reserve (struct state *state, size_t n)
-{
-  return state->s + n > state->theend;
-}
-
-static int
-sn_append_char (struct state *state, unsigned char c)
-{
-  if (sn_reserve (state, 1)) {
-    return 1;
-  } else {
-    *state->s++ = c;
-    return 0;
-  }
-}
-#endif
-
-#if 0
-static int
-as_reserve (struct state *state, size_t n)
-{
-  if (state->s + n > state->theend) {
-    int off = state->s - state->str;
-    unsigned char *tmp;
-
-    if (state->max_sz && state->sz >= state->max_sz)
-      return 1;
-
-    state->sz = max(state->sz * 2, state->sz + n);
-    if (state->max_sz)
-      state->sz = min(state->sz, state->max_sz);
-    tmp = realloc (state->str, state->sz);
-    if (tmp == NULL)
-      return 1;
-    state->str = tmp;
-    state->s = state->str + off;
-    state->theend = state->str + state->sz - 1;
-  }
-  return 0;
-}
-
-static int
-as_append_char (struct state *state, unsigned char c)
-{
-  if(as_reserve (state, 1))
-    return 1;
-  else {
-    *state->s++ = c;
-    return 0;
-  }
-}
-#endif
-
-static int
-append_number(struct state *state,
-	      unsigned long num, unsigned base, char *rep,
-	      int width, int prec, int flags, int minusp)
-{
-  int len = 0;
-  int i;
-
-  /* given precision, ignore zero flag */
-  if(prec != -1)
-    flags &= ~zero_flag;
-  else
-    prec = 1;
-  /* zero value with zero precision -> "" */
-  if(prec == 0 && num == 0)
-    return 0;
-  do{
-    if((*state->append_char)(state, rep[num % base]))
-      return 1;
-    len++;
-    num /= base;
-  }while(num);
-  prec -= len;
-  /* pad with prec zeros */
-  while(prec-- > 0){
-    if((*state->append_char)(state, '0'))
-      return 1;
-    len++;
-  }
-  /* add length of alternate prefix (added later) to len */
-  if(flags & alternate_flag && (base == 16 || base == 8))
-    len += base / 8;
-  /* pad with zeros */
-  if(flags & zero_flag){
-    width -= len;
-    if(minusp || (flags & space_flag) || (flags & plus_flag))
-      width--;
-    while(width-- > 0){
-      if((*state->append_char)(state, '0'))
-	return 1;
-      len++;
-    }
-  }
-  /* add alternate prefix */
-  if(flags & alternate_flag && (base == 16 || base == 8)){
-    if(base == 16)
-      if((*state->append_char)(state, rep[10] + 23)) /* XXX */
-	return 1;
-    if((*state->append_char)(state, '0'))
-      return 1;
-  }
-  /* add sign */
-  if(minusp){
-    if((*state->append_char)(state, '-'))
-      return 1;
-    len++;
-  } else if(flags & plus_flag) {
-    if((*state->append_char)(state, '+'))
-      return 1;
-    len++;
-  } else if(flags & space_flag) {
-    if((*state->append_char)(state, ' '))
-      return 1;
-    len++;
-  }
-  if(flags & minus_flag)
-    /* swap before padding with spaces */
-    for(i = 0; i < len / 2; i++){
-      char c = state->s[-i-1];
-      state->s[-i-1] = state->s[-len+i];
-      state->s[-len+i] = c;
-    }
-  width -= len;
-  while(width-- > 0){
-    if((*state->append_char)(state,  ' '))
-      return 1;
-    len++;
-  }
-  if(!(flags & minus_flag))
-    /* swap after padding with spaces */
-    for(i = 0; i < len / 2; i++){
-      char c = state->s[-i-1];
-      state->s[-i-1] = state->s[-len+i];
-      state->s[-len+i] = c;
-    }
-
-  return 0;
-}
-
-static int
-append_string (struct state *state,
-	       unsigned char *arg,
-	       int width,
-	       int prec,
-	       int flags)
-{
-  if(prec != -1)
-    width -= prec;
-  else
-    width -= strlen((char *)arg);
-  if(!(flags & minus_flag))
-    while(width-- > 0)
-      if((*state->append_char) (state, ' '))
-	return 1;
-  if (prec != -1) {
-    while (*arg && prec--)
-      if ((*state->append_char) (state, *arg++))
-	return 1;
-  } else {
-    while (*arg)
-      if ((*state->append_char) (state, *arg++))
-	return 1;
-  }
-  if(flags & minus_flag)
-    while(width-- > 0)
-      if((*state->append_char) (state, ' '))
-	return 1;
-  return 0;
-}
-
-static int
-append_char(struct state *state,
-	    unsigned char arg,
-	    int width,
-	    int flags)
-{
-  while(!(flags & minus_flag) && --width > 0)
-    if((*state->append_char) (state, ' '))
-      return 1;
-
-  if((*state->append_char) (state, arg))
-    return 1;
-  while((flags & minus_flag) && --width > 0)
-    if((*state->append_char) (state, ' '))
-      return 1;
-
-  return 0;
-}
-
-/*
- * This can't be made into a function...
- */
-
-#define PARSE_INT_FORMAT(res, arg, unsig) \
-if (long_flag) \
-     res = (unsig long)va_arg(arg, unsig long); \
-else if (short_flag) \
-     res = (unsig short)va_arg(arg, unsig int); \
-else \
-     res = (unsig int)va_arg(arg, unsig int)
-
-/*
- * zyxprintf - return 0 or -1
- */
-
-static int
-xyzprintf (struct state *state, const char *char_format, va_list ap)
-{
-  const unsigned char *format = (const unsigned char *)char_format;
-  unsigned char c;
-
-  while((c = *format++)) {
-    if (c == '%') {
-      int flags      = 0;
-      int width      = 0;
-      int prec       = -1;
-      int long_flag  = 0;
-      int short_flag = 0;
-
-      /* flags */
-      while((c = *format++)){
-	if(c == '-')
-	  flags |= minus_flag;
-	else if(c == '+')
-	  flags |= plus_flag;
-	else if(c == ' ')
-	  flags |= space_flag;
-	else if(c == '#')
-	  flags |= alternate_flag;
-	else if(c == '0')
-	  flags |= zero_flag;
-	else
-	  break;
-      }
-
-      if((flags & space_flag) && (flags & plus_flag))
-	flags ^= space_flag;
-
-      if((flags & minus_flag) && (flags & zero_flag))
-	flags ^= zero_flag;
-
-      /* width */
-      if (isdigit(c))
-	do {
-	  width = width * 10 + c - '0';
-	  c = *format++;
-	} while(isdigit(c));
-      else if(c == '*') {
-	width = va_arg(ap, int);
-	c = *format++;
-      }
-
-      /* precision */
-      if (c == '.') {
-	prec = 0;
-	c = *format++;
-	if (isdigit(c))
-	  do {
-	    prec = prec * 10 + c - '0';
-	    c = *format++;
-	  } while(isdigit(c));
-	else if (c == '*') {
-	  prec = va_arg(ap, int);
-	  c = *format++;
-	}
-      }
-
-      /* size */
-
-      if (c == 'h') {
-	short_flag = 1;
-	c = *format++;
-      } else if (c == 'l') {
-	long_flag = 1;
-	c = *format++;
-      }
-
-      switch (c) {
-      case 'c' :
-	if(append_char(state, va_arg(ap, int), width, flags))
-	  return -1;
-	break;
-      case 's' :
-	if (append_string(state,
-			  va_arg(ap, unsigned char*),
-			  width,
-			  prec,
-			  flags))
-	  return -1;
-	break;
-      case 'd' :
-      case 'i' : {
-	long arg;
-	unsigned long num;
-	int minusp = 0;
-
-	PARSE_INT_FORMAT(arg, ap, signed);
-
-	if (arg < 0) {
-	  minusp = 1;
-	  num = -arg;
-	} else
-	  num = arg;
-
-	if (append_number (state, num, 10, "0123456789",
-			   width, prec, flags, minusp))
-	  return -1;
-	break;
-      }
-      case 'u' : {
-	unsigned long arg;
-
-	PARSE_INT_FORMAT(arg, ap, unsigned);
-
-	if (append_number (state, arg, 10, "0123456789",
-			   width, prec, flags, 0))
-	  return -1;
-	break;
-      }
-      case 'o' : {
-	unsigned long arg;
-
-	PARSE_INT_FORMAT(arg, ap, unsigned);
-
-	if (append_number (state, arg, 010, "01234567",
-			   width, prec, flags, 0))
-	  return -1;
-	break;
-      }
-      case 'x' : {
-	unsigned long arg;
-
-	PARSE_INT_FORMAT(arg, ap, unsigned);
-
-	if (append_number (state, arg, 0x10, "0123456789abcdef",
-			   width, prec, flags, 0))
-	  return -1;
-	break;
-      }
-      case 'X' :{
-	unsigned long arg;
-
-	PARSE_INT_FORMAT(arg, ap, unsigned);
-
-	if (append_number (state, arg, 0x10, "0123456789ABCDEF",
-			   width, prec, flags, 0))
-	  return -1;
-	break;
-      }
-      case 'p' : {
-	unsigned long arg = (unsigned long)va_arg(ap, void*);
-
-	if (append_number (state, arg, 0x10, "0123456789ABCDEF",
-			   width, prec, flags, 0))
-	  return -1;
-	break;
-      }
-      case 'n' : {
-	int *arg = va_arg(ap, int*);
-	*arg = state->s - state->str;
-	break;
-      }
-      case '\0' :
-	  --format;
-	  /* FALLTHROUGH */
-      case '%' :
-	if ((*state->append_char)(state, c))
-	  return -1;
-	break;
-      default :
-	if (   (*state->append_char)(state, '%')
-	    || (*state->append_char)(state, c))
-	  return -1;
-	break;
-      }
-    } else
-      if ((*state->append_char) (state, c))
-	return -1;
-  }
-  return 0;
-}
-
-#ifndef HAVE_SNPRINTF
-int
-pcap_snprintf (char *str, size_t sz, const char *format, ...)
-{
-  va_list args;
-  int ret;
-
-  va_start(args, format);
-  ret = pcap_vsnprintf (str, sz, format, args);
-
-#ifdef PARANOIA
-  {
-    int ret2;
-    char *tmp;
-
-    tmp = malloc (sz);
-    if (tmp == NULL)
-      abort ();
-
-    ret2 = pcap_vsprintf (tmp, format, args);
-    if (ret != ret2 || strcmp(str, tmp))
-      abort ();
-    free (tmp);
-  }
-#endif
-
-  va_end(args);
-  return ret;
-}
-#endif
-
-#if 0
-#ifndef HAVE_ASPRINTF
-int
-asprintf (char **ret, const char *format, ...)
-{
-  va_list args;
-  int val;
-
-  va_start(args, format);
-  val = vasprintf (ret, format, args);
-
-#ifdef PARANOIA
-  {
-    int ret2;
-    char *tmp;
-    tmp = malloc (val + 1);
-    if (tmp == NULL)
-      abort ();
-
-    ret2 = vsprintf (tmp, format, args);
-    if (val != ret2 || strcmp(*ret, tmp))
-      abort ();
-    free (tmp);
-  }
-#endif
-
-  va_end(args);
-  return val;
-}
-#endif
-
-#ifndef HAVE_ASNPRINTF
-int
-pcap_asnprintf (char **ret, size_t max_sz, const char *format, ...)
-{
-  va_list args;
-  int val;
-
-  va_start(args, format);
-  val = pcap_vasnprintf (ret, max_sz, format, args);
-
-#ifdef PARANOIA
-  {
-    int ret2;
-    char *tmp;
-    tmp = malloc (val + 1);
-    if (tmp == NULL)
-      abort ();
-
-    ret2 = pcap_vsprintf (tmp, format, args);
-    if (val != ret2 || strcmp(*ret, tmp))
-      abort ();
-    free (tmp);
-  }
-#endif
-
-  va_end(args);
-  return val;
-}
-#endif
-
-#ifndef HAVE_VASPRINTF
-int
-pcap_vasprintf (char **ret, const char *format, va_list args)
-{
-  return pcap_vasnprintf (ret, 0, format, args);
-}
-#endif
-
-
-#ifndef HAVE_VASNPRINTF
-int
-pcap_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
-{
-  int st;
-  size_t len;
-  struct state state;
-
-  state.max_sz = max_sz;
-  state.sz     = 1;
-  state.str    = malloc(state.sz);
-  if (state.str == NULL) {
-    *ret = NULL;
-    return -1;
-  }
-  state.s = state.str;
-  state.theend = state.s + state.sz - 1;
-  state.append_char = as_append_char;
-  state.reserve     = as_reserve;
-
-  st = xyzprintf (&state, format, args);
-  if (st) {
-    free (state.str);
-    *ret = NULL;
-    return -1;
-  } else {
-    char *tmp;
-
-    *state.s = '\0';
-    len = state.s - state.str;
-    tmp = realloc (state.str, len+1);
-    if (tmp == NULL) {
-      free (state.str);
-      *ret = NULL;
-      return -1;
-    }
-    *ret = tmp;
-    return len;
-  }
-}
-#endif
-#endif
-
-#ifndef HAVE_VSNPRINTF
-int
-pcap_vsnprintf (char *str, size_t sz, const char *format, va_list args)
-{
-  struct state state;
-  int ret;
-  unsigned char *ustr = (unsigned char *)str;
-
-  state.max_sz = 0;
-  state.sz     = sz;
-  state.str    = ustr;
-  state.s      = ustr;
-  state.theend = ustr + sz - 1;
-  state.append_char = sn_append_char;
-  state.reserve     = sn_reserve;
-
-  ret = xyzprintf (&state, format, args);
-  *state.s = '\0';
-  if (ret)
-    return sz;
-  else
-    return state.s - state.str;
-}
-#endif
-
diff --git a/missing/strlcat.c b/missing/strlcat.c
new file mode 100644
index 0000000..bb78a3d
--- /dev/null
+++ b/missing/strlcat.c
@@ -0,0 +1,61 @@
+/*	$OpenBSD: pcap_strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left).  At most dsize-1 characters
+ * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcat(char * restrict dst, const char * restrict src, size_t dsize)
+{
+	const char *odst = dst;
+	const char *osrc = src;
+	size_t n = dsize;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end. */
+	while (n-- != 0 && *dst != '\0')
+		dst++;
+	dlen = dst - odst;
+	n = dsize - dlen;
+
+	if (n-- == 0)
+		return(dlen + strlen(src));
+	while (*src != '\0') {
+		if (n != 0) {
+			*dst++ = *src;
+			n--;
+		}
+		src++;
+	}
+	*dst = '\0';
+
+	return(dlen + (src - osrc));	/* count does not include NUL */
+}
diff --git a/missing/strlcpy.c b/missing/strlcpy.c
new file mode 100644
index 0000000..c552e0d
--- /dev/null
+++ b/missing/strlcpy.c
@@ -0,0 +1,56 @@
+/*	$OpenBSD: pcap_strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Copy string src to buffer dst of size dsize.  At most dsize-1
+ * chars will be copied.  Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dsize)
+{
+	const char *osrc = src;
+	size_t nleft = dsize;
+
+	/* Copy as many bytes as will fit. */
+	if (nleft != 0) {
+		while (--nleft != 0) {
+			if ((*dst++ = *src++) == '\0')
+				break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src. */
+	if (nleft == 0) {
+		if (dsize != 0)
+			*dst = '\0';		/* NUL-terminate dst */
+		while (*src++)
+			;
+	}
+
+	return(src - osrc - 1);	/* count does not include NUL */
+}
diff --git a/missing/win_asprintf.c b/missing/win_asprintf.c
new file mode 100644
index 0000000..e4bd13c
--- /dev/null
+++ b/missing/win_asprintf.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+	int len;
+	size_t str_size;
+	char *str;
+	int ret;
+
+	len = _vscprintf(format, args);
+	if (len == -1) {
+		*strp = NULL;
+		return (-1);
+	}
+	str_size = len + 1;
+	str = malloc(str_size);
+	if (str == NULL) {
+		*strp = NULL;
+		return (-1);
+	}
+	ret = vsnprintf(str, str_size, format, args);
+	if (ret == -1) {
+		free(str);
+		*strp = NULL;
+		return (-1);
+	}
+	*strp = str;
+	/*
+	 * vsnprintf() shouldn't truncate the string, as we have
+	 * allocated a buffer large enough to hold the string, so its
+	 * return value should be the number of characters printed.
+	 */
+	return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, format);
+	ret = pcap_vasprintf(strp, format, args);
+	va_end(args);
+	return (ret);
+}
diff --git a/missing/win_snprintf.c b/missing/win_snprintf.c
deleted file mode 100644
index 65a8ea1..0000000
--- a/missing/win_snprintf.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#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/mkdep b/mkdep
index 1486b18..6e8dbd6 100755
--- a/mkdep
+++ b/mkdep
@@ -16,7 +16,10 @@
 MAKE=Makefile			# default makefile name is "Makefile"
 CC=cc				# default C compiler is "cc"
 DEPENDENCY_CFLAG=-M		# default dependency-generation flag is -M
+SOURCE_DIRECTORY=.		# default source directory is the current directory
 
+# No command-line flags seen yet.
+flags=""
 while :
 	do case "$1" in
 		# -c allows you to specify the C compiler
@@ -39,13 +42,29 @@
 		-p)
 			SED='s;\.o;;'
 			shift ;;
+
+		# -s allows you to specify the source directory
+		-s)
+			SOURCE_DIRECTORY=$2
+			shift; shift ;;
+
+		# -include takes an argument
+		-include)
+			flags="$flags $1 $2"
+			shift; shift ;;
+
+		# other command-line flag
+		-*)
+			flags="$flags $1"
+			shift ;;
+
 		*)
 			break ;;
 	esac
 done
 
 if [ $# = 0 ] ; then
-	echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [flags] file ...'
+	echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [-s source-directory] [flags] file ...'
 	exit 1
 fi
 
@@ -76,8 +95,17 @@
 # egrep '^#include[ 	]*".*"' /dev/null $* |
 # sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
 
+#
+# Construct a list of source files with paths relative to the source directory.
+#
+sources=""
+for srcfile in $*
+do
+	sources="$sources $SOURCE_DIRECTORY/$srcfile"
+done
+
 # XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
-$CC $DEPENDENCY_CFLAG $* |
+$CC $DEPENDENCY_CFLAG $flags $sources |
 sed "
 	s; \./; ;g
 	$SED" |
diff --git a/msdos/readme.dos b/msdos/readme.dos
index b95483f..ec056dd 100644
--- a/msdos/readme.dos
+++ b/msdos/readme.dos
@@ -24,7 +24,7 @@
   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.watt-32.net/pcap/libpcap.zip
+     https://www.watt-32.net/pcap/libpcap.zip
 
   and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
 
@@ -51,12 +51,12 @@
    receive network data. It's mostly used to access the 'hosts'
    file and other <netdb.h> features. Get 'watt32s*.zip' at:
 
-     http://www.watt-32.net
+     https://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.watt-32.net/misc/exc_dx07.zip
+     https://www.watt-32.net/misc/exc_dx07.zip
 
 3. Flex & Bison is used to generate parser for the filter handler
    pcap_compile:
@@ -65,7 +65,7 @@
 
 4. NASM assembler v 0.98 or later is required when building djgpp and
    Watcom targets:
-     http://www.nasm.us/
+     https://www.nasm.us/
 
 5. sed (Stream Editor) is required for doing `make depend'.
    It's available at:
diff --git a/nametoaddr.c b/nametoaddr.c
index 194ff45..c944ad3 100644
--- a/nametoaddr.c
+++ b/nametoaddr.c
@@ -127,7 +127,6 @@
   #include <netdb.h>
 #endif /* _WIN32 */
 
-#include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
@@ -135,6 +134,8 @@
 
 #include "pcap-int.h"
 
+#include "diag-control.h"
+
 #include "gencode.h"
 #include <pcap/namedb.h>
 #include "nametoaddr.h"
@@ -162,7 +163,23 @@
 	bpf_u_int32 **p;
 	struct hostent *hp;
 
+	/*
+	 * gethostbyname() is deprecated on Windows, perhaps because
+	 * it's not thread-safe, or because it doesn't support IPv6,
+	 * or both.
+	 *
+	 * We deprecate pcap_nametoaddr() on all platforms because
+	 * it's not thread-safe; we supply it for backwards compatibility,
+	 * so suppress the deprecation warning.  We could, I guess,
+	 * use getaddrinfo() and construct the array ourselves, but
+	 * that's probably not worth the effort, as that wouldn't make
+	 * this thread-safe - we can't change the API to require that
+	 * our caller free the address array, so we still have to reuse
+	 * a local array.
+	 */
+DIAG_OFF_DEPRECATION
 	if ((hp = gethostbyname(name)) != NULL) {
+DIAG_ON_DEPRECATION
 #ifndef h_addr
 		hlist[0] = (bpf_u_int32 *)hp->h_addr;
 		NTOHL(hp->h_addr);
@@ -200,10 +217,10 @@
  *  XXX - not guaranteed to be thread-safe!  See below for platforms
  *  on which it is thread-safe and on which it isn't.
  */
+#if defined(_WIN32) || defined(__CYGWIN__)
 bpf_u_int32
-pcap_nametonetaddr(const char *name)
+pcap_nametonetaddr(const char *name _U_)
 {
-#ifdef _WIN32
 	/*
 	 * There's no "getnetbyname()" on Windows.
 	 *
@@ -217,7 +234,11 @@
 	 * of *UN*X* machines.)
 	 */
 	return 0;
-#else
+}
+#else /* _WIN32 */
+bpf_u_int32
+pcap_nametonetaddr(const char *name)
+{
 	/*
 	 * UN*X.
 	 */
@@ -231,7 +252,22 @@
 	int h_errnoval;
 	int err;
 
-	err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
+	/*
+	 * Apparently, the man page at
+	 *
+	 *    http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html
+	 *
+	 * lies when it says
+	 *
+	 *    If the function call successfully obtains a network record,
+	 *    then *result is set pointing to result_buf; otherwise, *result
+	 *    is set to NULL.
+	 *
+	 * and, in fact, at least in some versions of GNU libc, it does
+	 * *not* always get set if getnetbyname_r() succeeds.
+	 */
+	np = NULL;
+ 	err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
 	    &h_errnoval);
 	if (err != 0) {
 		/*
@@ -276,8 +312,8 @@
 		return np->n_net;
 	else
 		return 0;
-#endif /* _WIN32 */
 }
+#endif /* _WIN32 */
 
 /*
  * Convert a port name to its port and protocol numbers.
@@ -554,28 +590,20 @@
  */
 PCAP_API struct eproto eproto_db[];
 PCAP_API_DEF struct eproto eproto_db[] = {
-	{ "pup", ETHERTYPE_PUP },
-	{ "xns", ETHERTYPE_NS },
+	{ "aarp", ETHERTYPE_AARP },
+	{ "arp", ETHERTYPE_ARP },
+	{ "atalk", ETHERTYPE_ATALK },
+	{ "decnet", ETHERTYPE_DN },
 	{ "ip", ETHERTYPE_IP },
 #ifdef INET6
 	{ "ip6", ETHERTYPE_IPV6 },
 #endif
-	{ "arp", ETHERTYPE_ARP },
-	{ "rarp", ETHERTYPE_REVARP },
-	{ "sprite", ETHERTYPE_SPRITE },
+	{ "lat", ETHERTYPE_LAT },
+	{ "loopback", ETHERTYPE_LOOPBACK },
 	{ "mopdl", ETHERTYPE_MOPDL },
 	{ "moprc", ETHERTYPE_MOPRC },
-	{ "decnet", ETHERTYPE_DN },
-	{ "lat", ETHERTYPE_LAT },
+	{ "rarp", ETHERTYPE_REVARP },
 	{ "sca", ETHERTYPE_SCA },
-	{ "lanbridge", ETHERTYPE_LANBRIDGE },
-	{ "vexp", ETHERTYPE_VEXP },
-	{ "vprod", ETHERTYPE_VPROD },
-	{ "atalk", ETHERTYPE_ATALK },
-	{ "atalkarp", ETHERTYPE_AARP },
-	{ "loopback", ETHERTYPE_LOOPBACK },
-	{ "decdts", ETHERTYPE_DECDTS },
-	{ "decdns", ETHERTYPE_DECDNS },
 	{ (char *)0, 0 }
 };
 
@@ -620,9 +648,9 @@
 static inline u_char
 xdtoi(u_char c)
 {
-	if (isdigit(c))
+	if (c >= '0' && c <= '9')
 		return (u_char)(c - '0');
-	else if (islower(c))
+	else if (c >= 'a' && c <= 'f')
 		return (u_char)(c - 'a' + 10);
 	else
 		return (u_char)(c - 'A' + 10);
@@ -638,8 +666,15 @@
 	len = 0;
 	for (;;) {
 		n = 0;
-		while (*s && *s != '.')
+		while (*s && *s != '.') {
+			if (n > 25) {
+				/* The result will be > 255 */
+				return -1;
+			}
 			n = n * 10 + *s++ - '0';
+		}
+		if (n > 255)
+			return -1;
 		*addr <<= 8;
 		*addr |= n & 0xff;
 		len += 8;
@@ -694,7 +729,7 @@
 		if (*s == ':' || *s == '.' || *s == '-')
 			s += 1;
 		d = xdtoi(*s++);
-		if (isxdigit((unsigned char)*s)) {
+		if (PCAP_ISXDIGIT(*s)) {
 			d <<= 4;
 			d |= xdtoi(*s++);
 		}
diff --git a/optimize.c b/optimize.c
index 7c6424b..610a030 100644
--- a/optimize.c
+++ b/optimize.c
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
+#include <setjmp.h>
 #include <string.h>
 
 #include <errno.h>
@@ -102,7 +103,7 @@
  * Takes a 32-bit integer as an argument.
  *
  * If handed a non-zero value, returns the index of the lowest set bit,
- * counting upwards fro zero.
+ * counting upwards from zero.
  *
  * If handed zero, the results are platform- and compiler-dependent.
  * Keep it out of the light, don't give it any water, don't feed it
@@ -114,7 +115,7 @@
   /*
    * GCC 3.4 and later; we have __builtin_ctz().
    */
-  #define lowest_set_bit(mask) __builtin_ctz(mask)
+  #define lowest_set_bit(mask) ((u_int)__builtin_ctz(mask))
 #elif defined(_MSC_VER)
   /*
    * Visual Studio; we support only 2005 and later, so use
@@ -126,7 +127,7 @@
 #pragma intrinsic(_BitScanForward)
 #endif
 
-static __forceinline int
+static __forceinline u_int
 lowest_set_bit(int mask)
 {
 	unsigned long bit;
@@ -136,15 +137,15 @@
 	 * (It's currently not, in MSVC, even on 64-bit platforms, but....)
 	 */
 	if (_BitScanForward(&bit, (unsigned int)mask) == 0)
-		return -1;	/* mask is zero */
-	return (int)bit;
+		abort();	/* mask is zero */
+	return (u_int)bit;
 }
 #elif defined(MSDOS) && defined(__DJGPP__)
   /*
    * MS-DOS with DJGPP, which declares ffs() in <string.h>, which
    * we've already included.
    */
-  #define lowest_set_bit(mask)	(ffs((mask)) - 1)
+  #define lowest_set_bit(mask)	((u_int)(ffs((mask)) - 1))
 #elif (defined(MSDOS) && defined(__WATCOMC__)) || defined(STRINGS_H_DECLARES_FFS)
   /*
    * MS-DOS with Watcom C, which has <strings.h> and declares ffs() there,
@@ -152,18 +153,18 @@
    * of the Single UNIX Specification).
    */
   #include <strings.h>
-  #define lowest_set_bit(mask)	(ffs((mask)) - 1)
+  #define lowest_set_bit(mask)	(u_int)((ffs((mask)) - 1))
 #else
 /*
  * None of the above.
  * Use a perfect-hash-function-based function.
  */
-static int
+static u_int
 lowest_set_bit(int mask)
 {
 	unsigned int v = (unsigned int)mask;
 
-	static const int MultiplyDeBruijnBitPosition[32] = {
+	static const u_int MultiplyDeBruijnBitPosition[32] = {
 		0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
 		31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
 	};
@@ -212,38 +213,61 @@
  */
 struct valnode {
 	int code;
-	int v0, v1;
-	int val;
+	bpf_u_int32 v0, v1;
+	int val;		/* the value number */
 	struct valnode *next;
 };
 
 /* Integer constants mapped with the load immediate opcode. */
-#define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0L)
+#define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0U)
 
 struct vmapinfo {
 	int is_const;
-	bpf_int32 const_val;
+	bpf_u_int32 const_val;
 };
 
 typedef struct {
 	/*
+	 * Place to longjmp to on an error.
+	 */
+	jmp_buf top_ctx;
+
+	/*
+	 * The buffer into which to put error message.
+	 */
+	char *errbuf;
+
+	/*
 	 * A flag to indicate that further optimization is needed.
 	 * Iterative passes are continued until a given pass yields no
-	 * branch movement.
+	 * code simplification or branch movement.
 	 */
 	int done;
 
-	int n_blocks;
+	/*
+	 * XXX - detect loops that do nothing but repeated AND/OR pullups
+	 * and edge moves.
+	 * If 100 passes in a row do nothing but that, treat that as a
+	 * sign that we're in a loop that just shuffles in a cycle in
+	 * which each pass just shuffles the code and we eventually
+	 * get back to the original configuration.
+	 *
+	 * XXX - we need a non-heuristic way of detecting, or preventing,
+	 * such a cycle.
+	 */
+	int non_branch_movement_performed;
+
+	u_int n_blocks;		/* number of blocks in the CFG; guaranteed to be > 0, as it's a RET instruction at a minimum */
 	struct block **blocks;
-	int n_edges;
+	u_int n_edges;		/* twice n_blocks, so guaranteed to be > 0 */
 	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;
+	u_int nodewords;	/* number of 32-bit words for a bit vector of "number of nodes" bits; guaranteed to be > 0 */
+	u_int edgewords;	/* number of 32-bit words for a bit vector of "number of edges" bits; guaranteed to be > 0 */
 	struct block **levels;
 	bpf_u_int32 *space;
 
@@ -252,48 +276,51 @@
  * True if a is in uset {p}
  */
 #define SET_MEMBER(p, a) \
-((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+((p)[(unsigned)(a) / BITS_PER_WORD] & ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD)))
 
 /*
  * Add 'a' to uset p.
  */
 #define SET_INSERT(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] |= ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * Delete 'a' from uset p.
  */
 #define SET_DELETE(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * a := a intersect b
+ * n must be guaranteed to be > 0
  */
 #define SET_INTERSECT(a, b, n)\
 {\
 	register bpf_u_int32 *_x = a, *_y = b;\
-	register int _n = n;\
-	while (--_n >= 0) *_x++ &= *_y++;\
+	register u_int _n = n;\
+	do *_x++ &= *_y++; while (--_n != 0);\
 }
 
 /*
  * a := a - b
+ * n must be guaranteed to be > 0
  */
 #define SET_SUBTRACT(a, b, n)\
 {\
 	register bpf_u_int32 *_x = a, *_y = b;\
-	register int _n = n;\
-	while (--_n >= 0) *_x++ &=~ *_y++;\
+	register u_int _n = n;\
+	do *_x++ &=~ *_y++; while (--_n != 0);\
 }
 
 /*
  * a := a union b
+ * n must be guaranteed to be > 0
  */
 #define SET_UNION(a, b, n)\
 {\
 	register bpf_u_int32 *_x = a, *_y = b;\
-	register int _n = n;\
-	while (--_n >= 0) *_x++ |= *_y++;\
+	register u_int _n = n;\
+	do *_x++ |= *_y++; while (--_n != 0);\
 }
 
 	uset all_dom_sets;
@@ -302,8 +329,8 @@
 
 #define MODULUS 213
 	struct valnode *hashtbl[MODULUS];
-	int curval;
-	int maxval;
+	bpf_u_int32 curval;
+	bpf_u_int32 maxval;
 
 	struct vmapinfo *vmap;
 	struct valnode *vnode_base;
@@ -312,6 +339,16 @@
 
 typedef struct {
 	/*
+	 * Place to longjmp to on an error.
+	 */
+	jmp_buf top_ctx;
+
+	/*
+	 * The buffer into which to put error message.
+	 */
+	char *errbuf;
+
+	/*
 	 * Some pointers used to convert the basic block form of the code,
 	 * into the array form that BPF requires.  'fstart' will point to
 	 * the malloc'd array while 'ftail' is used during the recursive
@@ -321,14 +358,16 @@
 	struct bpf_insn *ftail;
 } conv_state_t;
 
-static void opt_init(compiler_state_t *, opt_state_t *, struct icode *);
+static void opt_init(opt_state_t *, struct icode *);
 static void opt_cleanup(opt_state_t *);
+static void PCAP_NORETURN opt_error(opt_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
 
 static void intern_blocks(opt_state_t *, struct icode *);
 
 static void find_inedges(opt_state_t *, struct block *);
 #ifdef BDEBUG
-static void opt_dump(compiler_state_t *, struct icode *);
+static void opt_dump(opt_state_t *, struct icode *);
 #endif
 
 #ifndef MAX
@@ -378,7 +417,8 @@
 static void
 find_dom(opt_state_t *opt_state, struct block *root)
 {
-	int i;
+	u_int i;
+	int level;
 	struct block *b;
 	bpf_u_int32 *x;
 
@@ -386,16 +426,23 @@
 	 * Initialize sets to contain all nodes.
 	 */
 	x = opt_state->all_dom_sets;
+	/*
+	 * In opt_init(), we've made sure the product doesn't overflow.
+	 */
 	i = opt_state->n_blocks * opt_state->nodewords;
-	while (--i >= 0)
+	while (i != 0) {
+		--i;
 		*x++ = 0xFFFFFFFFU;
+	}
 	/* Root starts off empty. */
-	for (i = opt_state->nodewords; --i >= 0;)
+	for (i = opt_state->nodewords; i != 0;) {
+		--i;
 		root->dom[i] = 0;
+	}
 
 	/* root->level is the highest level no found. */
-	for (i = root->level; i >= 0; --i) {
-		for (b = opt_state->levels[i]; b; b = b->link) {
+	for (level = root->level; level >= 0; --level) {
+		for (b = opt_state->levels[level]; b; b = b->link) {
 			SET_INSERT(b->dom, b->id);
 			if (JT(b) == 0)
 				continue;
@@ -422,19 +469,25 @@
 static void
 find_edom(opt_state_t *opt_state, struct block *root)
 {
-	int i;
+	u_int i;
 	uset x;
+	int level;
 	struct block *b;
 
 	x = opt_state->all_edge_sets;
-	for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
+	/*
+	 * In opt_init(), we've made sure the product doesn't overflow.
+	 */
+	for (i = opt_state->n_edges * opt_state->edgewords; i != 0; ) {
+		--i;
 		x[i] = 0xFFFFFFFFU;
+	}
 
 	/* root->level is the highest level no found. */
 	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 = opt_state->levels[i]; b != 0; b = b->link) {
+	for (level = root->level; level >= 0; --level) {
+		for (b = opt_state->levels[level]; b != 0; b = b->link) {
 			propedom(opt_state, &b->et);
 			propedom(opt_state, &b->ef);
 		}
@@ -451,7 +504,7 @@
 static void
 find_closure(opt_state_t *opt_state, struct block *root)
 {
-	int i;
+	int level;
 	struct block *b;
 
 	/*
@@ -461,8 +514,8 @@
 	      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 = opt_state->levels[i]; b; b = b->link) {
+	for (level = root->level; level >= 0; --level) {
+		for (b = opt_state->levels[level]; b; b = b->link) {
 			SET_INSERT(b->closure, b->id);
 			if (JT(b) == 0)
 				continue;
@@ -473,8 +526,11 @@
 }
 
 /*
- * Return the register number that is used by s.  If A and X are both
- * used, return AX_ATOM.  If no register is used, return -1.
+ * Return the register number that is used by s.
+ *
+ * Returns ATOM_A if A is used, ATOM_X if X is used, AX_ATOM if both A and X
+ * are used, the scratch memory location's number if a scratch memory
+ * location is used (e.g., 0 for M[0]), or -1 if none of those are used.
  *
  * The implementation should probably change to an array access.
  */
@@ -494,8 +550,12 @@
 
 	case BPF_LD:
 	case BPF_LDX:
+		/*
+		 * As there are fewer than 2^31 memory locations,
+		 * s->k should be convertible to int without problems.
+		 */
 		return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
-			(BPF_MODE(c) == BPF_MEM) ? s->k : -1;
+			(BPF_MODE(c) == BPF_MEM) ? (int)s->k : -1;
 
 	case BPF_ST:
 		return A_ATOM;
@@ -653,21 +713,40 @@
 	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(opt_state_t *opt_state, int code, int v0, int v1)
+/*
+ * Because we really don't have an IR, this stuff is a little messy.
+ *
+ * This routine looks in the table of existing value number for a value
+ * with generated from an operation with the specified opcode and
+ * the specified values.  If it finds it, it returns its value number,
+ * otherwise it makes a new entry in the table and returns the
+ * value number of that entry.
+ */
+static bpf_u_int32
+F(opt_state_t *opt_state, int code, bpf_u_int32 v0, bpf_u_int32 v1)
 {
 	u_int hash;
-	int val;
+	bpf_u_int32 val;
 	struct valnode *p;
 
-	hash = (u_int)code ^ ((u_int)v0 << 4) ^ ((u_int)v1 << 8);
+	hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
 	hash %= MODULUS;
 
 	for (p = opt_state->hashtbl[hash]; p; p = p->next)
 		if (p->code == code && p->v0 == v0 && p->v1 == v1)
 			return p->val;
 
+	/*
+	 * Not found.  Allocate a new value, and assign it a new
+	 * value number.
+	 *
+	 * opt_state->curval starts out as 0, which means VAL_UNKNOWN; we
+	 * increment it before using it as the new value number, which
+	 * means we never assign VAL_UNKNOWN.
+	 *
+	 * XXX - unless we overflow, but we probably won't have 2^32-1
+	 * values; we treat 32 bits as effectively infinite.
+	 */
 	val = ++opt_state->curval;
 	if (BPF_MODE(code) == BPF_IMM &&
 	    (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
@@ -686,7 +765,7 @@
 }
 
 static inline void
-vstore(struct stmt *s, int *valp, int newval, int alter)
+vstore(struct stmt *s, bpf_u_int32 *valp, bpf_u_int32 newval, int alter)
 {
 	if (alter && newval != VAL_UNKNOWN && *valp == newval)
 		s->code = NOP;
@@ -699,8 +778,7 @@
  * (Unary operators are handled elsewhere.)
  */
 static void
-fold_op(compiler_state_t *cstate, opt_state_t *opt_state,
-    struct stmt *s, int v0, int v1)
+fold_op(opt_state_t *opt_state, struct stmt *s, bpf_u_int32 v0, bpf_u_int32 v1)
 {
 	bpf_u_int32 a, b;
 
@@ -722,13 +800,13 @@
 
 	case BPF_DIV:
 		if (b == 0)
-			bpf_error(cstate, "division by zero");
+			opt_error(opt_state, "division by zero");
 		a /= b;
 		break;
 
 	case BPF_MOD:
 		if (b == 0)
-			bpf_error(cstate, "modulus by zero");
+			opt_error(opt_state, "modulus by zero");
 		a %= b;
 		break;
 
@@ -745,11 +823,39 @@
 		break;
 
 	case BPF_LSH:
-		a <<= b;
+		/*
+		 * A left shift of more than the width of the type
+		 * is undefined in C; we'll just treat it as shifting
+		 * all the bits out.
+		 *
+		 * XXX - the BPF interpreter doesn't check for this,
+		 * so its behavior is dependent on the behavior of
+		 * the processor on which it's running.  There are
+		 * processors on which it shifts all the bits out
+		 * and processors on which it does no shift.
+		 */
+		if (b < 32)
+			a <<= b;
+		else
+			a = 0;
 		break;
 
 	case BPF_RSH:
-		a >>= b;
+		/*
+		 * A right shift of more than the width of the type
+		 * is undefined in C; we'll just treat it as shifting
+		 * all the bits out.
+		 *
+		 * XXX - the BPF interpreter doesn't check for this,
+		 * so its behavior is dependent on the behavior of
+		 * the processor on which it's running.  There are
+		 * processors on which it shifts all the bits out
+		 * and processors on which it does no shift.
+		 */
+		if (b < 32)
+			a >>= b;
+		else
+			a = 0;
 		break;
 
 	default:
@@ -757,6 +863,10 @@
 	}
 	s->k = a;
 	s->code = BPF_LD|BPF_IMM;
+	/*
+	 * XXX - optimizer loop detection.
+	 */
+	opt_state->non_branch_movement_performed = 1;
 	opt_state->done = 0;
 }
 
@@ -782,7 +892,7 @@
 {
 	struct slist *s;
 	struct slist *next, *last;
-	int val;
+	bpf_u_int32 val;
 
 	s = b->stmts;
 	if (s == 0)
@@ -813,6 +923,10 @@
 		if (s->s.code == BPF_ST &&
 		    next->s.code == (BPF_LDX|BPF_MEM) &&
 		    s->s.k == next->s.k) {
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 			next->s.code = BPF_MISC|BPF_TAX;
 		}
@@ -824,6 +938,10 @@
 		    next->s.code == (BPF_MISC|BPF_TAX)) {
 			s->s.code = BPF_LDX|BPF_IMM;
 			next->s.code = BPF_MISC|BPF_TXA;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 		/*
@@ -903,6 +1021,10 @@
 			s->s.code = NOP;
 			add->s.code = NOP;
 			tax->s.code = NOP;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 	}
@@ -915,10 +1037,10 @@
 	 */
 	if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
 	    !ATOMELEM(b->out_use, A_ATOM)) {
-	    	/*
-	    	 * We can optimize away certain subtractions of the
-	    	 * X register.
-	    	 */
+		/*
+		 * We can optimize away certain subtractions of the
+		 * X register.
+		 */
 		if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
 			val = b->val[X_ATOM];
 			if (opt_state->vmap[val].is_const) {
@@ -933,6 +1055,10 @@
 				 */
 				b->s.k += opt_state->vmap[val].const_val;
 				last->s.code = NOP;
+				/*
+				 * XXX - optimizer loop detection.
+				 */
+				opt_state->non_branch_movement_performed = 1;
 				opt_state->done = 0;
 			} else if (b->s.k == 0) {
 				/*
@@ -946,6 +1072,10 @@
 				 */
 				last->s.code = NOP;
 				b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
+				/*
+				 * XXX - optimizer loop detection.
+				 */
+				opt_state->non_branch_movement_performed = 1;
 				opt_state->done = 0;
 			}
 		}
@@ -958,6 +1088,10 @@
 		else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
 			last->s.code = NOP;
 			b->s.k += last->s.k;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 		/*
@@ -972,6 +1106,10 @@
 			b->s.k = last->s.k;
 			b->s.code = BPF_JMP|BPF_K|BPF_JSET;
 			last->s.code = NOP;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 			opt_not(b);
 		}
@@ -983,7 +1121,7 @@
 	if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
 		if (b->s.k == 0)
 			JT(b) = JF(b);
-		if ((u_int)b->s.k == 0xffffffffU)
+		if (b->s.k == 0xffffffffU)
 			JF(b) = JT(b);
 	}
 	/*
@@ -993,7 +1131,7 @@
 	 */
 	val = b->val[X_ATOM];
 	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
-		bpf_int32 v = opt_state->vmap[val].const_val;
+		bpf_u_int32 v = opt_state->vmap[val].const_val;
 		b->s.code &= ~BPF_X;
 		b->s.k = v;
 	}
@@ -1003,7 +1141,7 @@
 	 */
 	val = b->val[A_ATOM];
 	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
-		bpf_int32 v = opt_state->vmap[val].const_val;
+		bpf_u_int32 v = opt_state->vmap[val].const_val;
 		switch (BPF_OP(b->s.code)) {
 
 		case BPF_JEQ:
@@ -1011,11 +1149,11 @@
 			break;
 
 		case BPF_JGT:
-			v = (unsigned)v > (unsigned)b->s.k;
+			v = v > b->s.k;
 			break;
 
 		case BPF_JGE:
-			v = (unsigned)v >= (unsigned)b->s.k;
+			v = v >= b->s.k;
 			break;
 
 		case BPF_JSET:
@@ -1025,8 +1163,13 @@
 		default:
 			abort();
 		}
-		if (JF(b) != JT(b))
+		if (JF(b) != JT(b)) {
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
+		}
 		if (v)
 			JF(b) = JT(b);
 		else
@@ -1041,11 +1184,10 @@
  * evaluation and code transformations weren't folded together.
  */
 static void
-opt_stmt(compiler_state_t *cstate, opt_state_t *opt_state,
-    struct stmt *s, int val[], int alter)
+opt_stmt(opt_state_t *opt_state, struct stmt *s, bpf_u_int32 val[], int alter)
 {
 	int op;
-	int v;
+	bpf_u_int32 v;
 
 	switch (s->code) {
 
@@ -1064,6 +1206,10 @@
 			s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
 			s->k += opt_state->vmap[v].const_val;
 			v = F(opt_state, s->code, s->k, 0L);
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 		else
@@ -1094,7 +1240,23 @@
 	case BPF_ALU|BPF_NEG:
 		if (alter && opt_state->vmap[val[A_ATOM]].is_const) {
 			s->code = BPF_LD|BPF_IMM;
-			s->k = -opt_state->vmap[val[A_ATOM]].const_val;
+			/*
+			 * Do this negation as unsigned arithmetic; that's
+			 * what modern BPF engines do, and it guarantees
+			 * that all possible values can be negated.  (Yeah,
+			 * negating 0x80000000, the minimum signed 32-bit
+			 * two's-complement value, results in 0x80000000,
+			 * so it's still negative, but we *should* be doing
+			 * all unsigned arithmetic here, to match what
+			 * modern BPF engines do.)
+			 *
+			 * Express it as 0U - (unsigned value) so that we
+			 * don't get compiler warnings about negating an
+			 * unsigned value and don't get UBSan warnings
+			 * about the result of negating 0x80000000 being
+			 * undefined.
+			 */
+			s->k = 0U - opt_state->vmap[val[A_ATOM]].const_val;
 			val[A_ATOM] = K(s->k);
 		}
 		else
@@ -1114,9 +1276,17 @@
 		op = BPF_OP(s->code);
 		if (alter) {
 			if (s->k == 0) {
-				/* don't optimize away "sub #0"
+				/*
+				 * Optimize operations where the constant
+				 * is zero.
+				 *
+				 * Don't optimize away "sub #0"
 				 * as it may be needed later to
-				 * fixup the generated math code */
+				 * fixup the generated math code.
+				 *
+				 * Fail if we're dividing by zero or taking
+				 * a modulus by zero.
+				 */
 				if (op == BPF_ADD ||
 				    op == BPF_LSH || op == BPF_RSH ||
 				    op == BPF_OR || op == BPF_XOR) {
@@ -1128,9 +1298,15 @@
 					val[A_ATOM] = K(s->k);
 					break;
 				}
+				if (op == BPF_DIV)
+					opt_error(opt_state,
+					    "division by zero");
+				if (op == BPF_MOD)
+					opt_error(opt_state,
+					    "modulus by zero");
 			}
 			if (opt_state->vmap[val[A_ATOM]].is_const) {
-				fold_op(cstate, opt_state, s, val[A_ATOM], K(s->k));
+				fold_op(opt_state, s, val[A_ATOM], K(s->k));
 				val[A_ATOM] = K(s->k);
 				break;
 			}
@@ -1151,12 +1327,20 @@
 		op = BPF_OP(s->code);
 		if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
 			if (opt_state->vmap[val[A_ATOM]].is_const) {
-				fold_op(cstate, opt_state, s, val[A_ATOM], val[X_ATOM]);
+				fold_op(opt_state, s, val[A_ATOM], val[X_ATOM]);
 				val[A_ATOM] = K(s->k);
 			}
 			else {
 				s->code = BPF_ALU|BPF_K|op;
 				s->k = opt_state->vmap[val[X_ATOM]].const_val;
+				if ((op == BPF_LSH || op == BPF_RSH) &&
+				    s->k > 31)
+					opt_error(opt_state,
+					    "shift by more than 31 bits");
+				/*
+				 * XXX - optimizer loop detection.
+				 */
+				opt_state->non_branch_movement_performed = 1;
 				opt_state->done = 0;
 				val[A_ATOM] =
 					F(opt_state, s->code, val[A_ATOM], K(s->k));
@@ -1201,6 +1385,10 @@
 		if (alter && opt_state->vmap[v].is_const) {
 			s->code = BPF_LD|BPF_IMM;
 			s->k = opt_state->vmap[v].const_val;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 		vstore(s, &val[A_ATOM], v, alter);
@@ -1215,6 +1403,10 @@
 		if (alter && opt_state->vmap[v].is_const) {
 			s->code = BPF_LDX|BPF_IMM;
 			s->k = opt_state->vmap[v].const_val;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 		vstore(s, &val[X_ATOM], v, alter);
@@ -1247,6 +1439,10 @@
 	atom = atomdef(s);
 	if (atom >= 0) {
 		if (last[atom]) {
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 			last[atom]->code = NOP;
 		}
@@ -1270,18 +1466,21 @@
 	for (atom = 0; atom < N_ATOMS; ++atom)
 		if (last[atom] && !ATOMELEM(b->out_use, atom)) {
 			last[atom]->code = NOP;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 }
 
 static void
-opt_blk(compiler_state_t *cstate, opt_state_t *opt_state,
-    struct block *b, int do_stmts)
+opt_blk(opt_state_t *opt_state, struct block *b, int do_stmts)
 {
 	struct slist *s;
 	struct edge *p;
 	int i;
-	bpf_int32 aval, xval;
+	bpf_u_int32 aval, xval;
 
 #if 0
 	for (s = b->stmts; s && s->next; s = s->next)
@@ -1326,7 +1525,7 @@
 	aval = b->val[A_ATOM];
 	xval = b->val[X_ATOM];
 	for (s = b->stmts; s; s = s->next)
-		opt_stmt(cstate, opt_state, &s->s, b->val, do_stmts);
+		opt_stmt(opt_state, &s->s, b->val, do_stmts);
 
 	/*
 	 * This is a special case: if we don't use anything from this
@@ -1334,7 +1533,10 @@
 	 * value that is already there, or if this block is a return,
 	 * eliminate all the statements.
 	 *
-	 * XXX - what if it does a store?
+	 * XXX - what if it does a store?  Presumably that falls under
+	 * the heading of "if we don't use anything from this block",
+	 * i.e., if we use any memory location set to a different
+	 * value by this block, then we use something from this block.
 	 *
 	 * XXX - why does it matter whether we use anything from this
 	 * block?  If the accumulator or index register doesn't change
@@ -1358,6 +1560,10 @@
 	     BPF_CLASS(b->s.code) == BPF_RET)) {
 		if (b->stmts != 0) {
 			b->stmts = 0;
+			/*
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 		}
 	} else {
@@ -1396,19 +1602,41 @@
 	return 0;
 }
 
+/*
+ * Given a block that is the successor of an edge, and an edge that
+ * dominates that edge, return either a pointer to a child of that
+ * block (a block to which that block jumps) if that block is a
+ * candidate to replace the successor of the latter edge or NULL
+ * if neither of the children of the first block are candidates.
+ */
 static struct block *
 fold_edge(struct block *child, struct edge *ep)
 {
 	int sense;
-	int aval0, aval1, oval0, oval1;
+	bpf_u_int32 aval0, aval1, oval0, oval1;
 	int code = ep->code;
 
 	if (code < 0) {
+		/*
+		 * This edge is a "branch if false" edge.
+		 */
 		code = -code;
 		sense = 0;
-	} else
+	} else {
+		/*
+		 * This edge is a "branch if true" edge.
+		 */
 		sense = 1;
+	}
 
+	/*
+	 * If the opcode for the branch at the end of the block we
+	 * were handed isn't the same as the opcode for the branch
+	 * to which the edge we were handed corresponds, the tests
+	 * for those branches aren't testing the same conditions,
+	 * so the blocks to which the first block branches aren't
+	 * candidates to replace the successor of the edge.
+	 */
 	if (child->s.code != code)
 		return 0;
 
@@ -1417,13 +1645,21 @@
 	aval1 = ep->pred->val[A_ATOM];
 	oval1 = ep->pred->oval;
 
+	/*
+	 * If the A register value on exit from the successor block
+	 * isn't the same as the A register value on exit from the
+	 * predecessor of the edge, the blocks to which the first
+	 * block branches aren't candidates to replace the successor
+	 * of the edge.
+	 */
 	if (aval0 != aval1)
 		return 0;
 
 	if (oval0 == oval1)
 		/*
 		 * The operands of the branch instructions are
-		 * identical, so the result is true if a true
+		 * identical, so the branches are testing the
+		 * same condition, and the result is true if a true
 		 * branch was taken to get here, otherwise false.
 		 */
 		return sense ? JT(child) : JF(child);
@@ -1448,21 +1684,58 @@
 	return 0;
 }
 
+/*
+ * If we can make this edge go directly to a child of the edge's current
+ * successor, do so.
+ */
 static void
 opt_j(opt_state_t *opt_state, struct edge *ep)
 {
-	register int i, k;
+	register u_int i, k;
 	register struct block *target;
 
+	/*
+	 * Does this edge go to a block where, if the test
+	 * at the end of it succeeds, it goes to a block
+	 * that's a leaf node of the DAG, i.e. a return
+	 * statement?
+	 * If so, there's nothing to optimize.
+	 */
 	if (JT(ep->succ) == 0)
 		return;
 
+	/*
+	 * Does this edge go to a block that goes, in turn, to
+	 * the same block regardless of whether the test at the
+	 * end succeeds or fails?
+	 */
 	if (JT(ep->succ) == JF(ep->succ)) {
 		/*
 		 * Common branch targets can be eliminated, provided
 		 * there is no data dependency.
+		 *
+		 * Check whether any register used on exit from the
+		 * block to which the successor of this edge goes
+		 * has a value at that point that's different from
+		 * the value it has on exit from the predecessor of
+		 * this edge.  If not, the predecessor of this edge
+		 * can just go to the block to which the successor
+		 * of this edge goes, bypassing the successor of this
+		 * edge, as the successor of this edge isn't doing
+		 * any calculations whose results are different
+		 * from what the blocks before it did and isn't
+		 * doing any tests the results of which matter.
 		 */
-		if (!use_conflict(ep->pred, ep->succ->et.succ)) {
+		if (!use_conflict(ep->pred, JT(ep->succ))) {
+			/*
+			 * No, there isn't.
+			 * Make this edge go to the block to
+			 * which the successor of that edge
+			 * goes.
+			 *
+			 * XXX - optimizer loop detection.
+			 */
+			opt_state->non_branch_movement_performed = 1;
 			opt_state->done = 0;
 			ep->succ = JT(ep->succ);
 		}
@@ -1476,19 +1749,38 @@
 	 */
  top:
 	for (i = 0; i < opt_state->edgewords; ++i) {
+		/* i'th word in the bitset of dominators */
 		register bpf_u_int32 x = ep->edom[i];
 
 		while (x != 0) {
+			/* Find the next dominator in that word and mark it as found */
 			k = lowest_set_bit(x);
-			x &=~ (1 << k);
+			x &=~ ((bpf_u_int32)1 << k);
 			k += i * BITS_PER_WORD;
 
 			target = fold_edge(ep->succ, opt_state->edges[k]);
 			/*
+			 * We have a candidate to replace the successor
+			 * of ep.
+			 *
 			 * Check that there is no data dependency between
-			 * nodes that will be violated if we move the edge.
+			 * nodes that will be violated if we move the edge;
+			 * i.e., if any register used on exit from the
+			 * candidate has a value at that point different
+			 * from the value it has when we exit the
+			 * predecessor of that edge, there's a data
+			 * dependency that will be violated.
 			 */
 			if (target != 0 && !use_conflict(ep->pred, target)) {
+				/*
+				 * It's safe to replace the successor of
+				 * ep; do so, and note that we've made
+				 * at least one change.
+				 *
+				 * XXX - this is one of the operations that
+				 * happens when the optimizer gets into
+				 * one of those infinite loops.
+				 */
 				opt_state->done = 0;
 				ep->succ = target;
 				if (JT(target) != 0)
@@ -1502,11 +1794,30 @@
 	}
 }
 
-
+/*
+ * XXX - is this, and and_pullup(), what's described in section 6.1.2
+ * "Predicate Assertion Propagation" in the BPF+ paper?
+ *
+ * Note that this looks at block dominators, not edge dominators.
+ * Don't think so.
+ *
+ * "A or B" compiles into
+ *
+ *          A
+ *       t / \ f
+ *        /   B
+ *       / t / \ f
+ *      \   /
+ *       \ /
+ *        X
+ *
+ *
+ */
 static void
 or_pullup(opt_state_t *opt_state, struct block *b)
 {
-	int val, at_top;
+	bpf_u_int32 val;
+	int at_top;
 	struct block *pull;
 	struct block **diffp, **samep;
 	struct edge *ep;
@@ -1524,39 +1835,106 @@
 		if (val != ep->pred->val[A_ATOM])
 			return;
 
+	/*
+	 * For the first edge in the list of edges coming into this block,
+	 * see whether the predecessor of that edge comes here via a true
+	 * branch or a false branch.
+	 */
 	if (JT(b->in_edges->pred) == b)
-		diffp = &JT(b->in_edges->pred);
+		diffp = &JT(b->in_edges->pred);	/* jt */
 	else
-		diffp = &JF(b->in_edges->pred);
+		diffp = &JF(b->in_edges->pred);	/* jf */
 
+	/*
+	 * diffp is a pointer to a pointer to the block.
+	 *
+	 * Go down the false chain looking as far as you can,
+	 * making sure that each jump-compare is doing the
+	 * same as the original block.
+	 *
+	 * If you reach the bottom before you reach a
+	 * different jump-compare, just exit.  There's nothing
+	 * to do here.  XXX - no, this version is checking for
+	 * the value leaving the block; that's from the BPF+
+	 * pullup routine.
+	 */
 	at_top = 1;
 	for (;;) {
+		/*
+		 * Done if that's not going anywhere XXX
+		 */
 		if (*diffp == 0)
 			return;
 
+		/*
+		 * Done if that predecessor blah blah blah isn't
+		 * going the same place we're going XXX
+		 *
+		 * Does the true edge of this block point to the same
+		 * location as the true edge of b?
+		 */
 		if (JT(*diffp) != JT(b))
 			return;
 
+		/*
+		 * Done if this node isn't a dominator of that
+		 * node blah blah blah XXX
+		 *
+		 * Does b dominate diffp?
+		 */
 		if (!SET_MEMBER((*diffp)->dom, b->id))
 			return;
 
+		/*
+		 * Break out of the loop if that node's value of A
+		 * isn't the value of A above XXX
+		 */
 		if ((*diffp)->val[A_ATOM] != val)
 			break;
 
+		/*
+		 * Get the JF for that node XXX
+		 * Go down the false path.
+		 */
 		diffp = &JF(*diffp);
 		at_top = 0;
 	}
+
+	/*
+	 * Now that we've found a different jump-compare in a chain
+	 * below b, search further down until we find another
+	 * jump-compare that looks at the original value.  This
+	 * jump-compare should get pulled up.  XXX again we're
+	 * comparing values not jump-compares.
+	 */
 	samep = &JF(*diffp);
 	for (;;) {
+		/*
+		 * Done if that's not going anywhere XXX
+		 */
 		if (*samep == 0)
 			return;
 
+		/*
+		 * Done if that predecessor blah blah blah isn't
+		 * going the same place we're going XXX
+		 */
 		if (JT(*samep) != JT(b))
 			return;
 
+		/*
+		 * Done if this node isn't a dominator of that
+		 * node blah blah blah XXX
+		 *
+		 * Does b dominate samep?
+		 */
 		if (!SET_MEMBER((*samep)->dom, b->id))
 			return;
 
+		/*
+		 * Break out of the loop if that node's value of A
+		 * is the value of A above XXX
+		 */
 		if ((*samep)->val[A_ATOM] == val)
 			break;
 
@@ -1592,13 +1970,18 @@
 	else
 		*diffp = pull;
 
+	/*
+	 * XXX - this is one of the operations that happens when the
+	 * optimizer gets into one of those infinite loops.
+	 */
 	opt_state->done = 0;
 }
 
 static void
 and_pullup(opt_state_t *opt_state, struct block *b)
 {
-	int val, at_top;
+	bpf_u_int32 val;
+	int at_top;
 	struct block *pull;
 	struct block **diffp, **samep;
 	struct edge *ep;
@@ -1683,12 +2066,15 @@
 	else
 		*diffp = pull;
 
+	/*
+	 * XXX - this is one of the operations that happens when the
+	 * optimizer gets into one of those infinite loops.
+	 */
 	opt_state->done = 0;
 }
 
 static void
-opt_blks(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
-    int do_stmts)
+opt_blks(opt_state_t *opt_state, struct icode *ic, int do_stmts)
 {
 	int i, maxlevel;
 	struct block *p;
@@ -1699,15 +2085,28 @@
 	find_inedges(opt_state, ic->root);
 	for (i = maxlevel; i >= 0; --i)
 		for (p = opt_state->levels[i]; p; p = p->link)
-			opt_blk(cstate, opt_state, p, do_stmts);
+			opt_blk(opt_state, p, do_stmts);
 
 	if (do_stmts)
 		/*
 		 * No point trying to move branches; it can't possibly
 		 * make a difference at this point.
+		 *
+		 * XXX - this might be after we detect a loop where
+		 * we were just looping infinitely moving branches
+		 * in such a fashion that we went through two or more
+		 * versions of the machine code, eventually returning
+		 * to the first version.  (We're really not doing a
+		 * full loop detection, we're just testing for two
+		 * passes in a row where where we do nothing but
+		 * move branches.)
 		 */
 		return;
 
+	/*
+	 * Is this what the BPF+ paper describes in sections 6.1.1,
+	 * 6.1.2, and 6.1.3?
+	 */
 	for (i = 1; i <= maxlevel; ++i) {
 		for (p = opt_state->levels[i]; p; p = p->link) {
 			opt_j(opt_state, &p->et);
@@ -1734,7 +2133,8 @@
 static void
 find_inedges(opt_state_t *opt_state, struct block *root)
 {
-	int i;
+	u_int i;
+	int level;
 	struct block *b;
 
 	for (i = 0; i < opt_state->n_blocks; ++i)
@@ -1744,8 +2144,8 @@
 	 * 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 = opt_state->levels[i]; b != 0; b = b->link) {
+	for (level = root->level; level > 0; --level) {
+		for (b = opt_state->levels[level]; b != 0; b = b->link) {
 			link_inedge(&b->et, JT(b));
 			link_inedge(&b->ef, JF(b));
 		}
@@ -1777,59 +2177,120 @@
 }
 
 static void
-opt_loop(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
-    int do_stmts)
+opt_loop(opt_state_t *opt_state, struct icode *ic, int do_stmts)
 {
 
 #ifdef BDEBUG
 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("opt_loop(root, %d) begin\n", do_stmts);
-		opt_dump(cstate, ic);
+		opt_dump(opt_state, ic);
 	}
 #endif
-	do {
+
+	/*
+	 * XXX - optimizer loop detection.
+	 */
+	int loop_count = 0;
+	for (;;) {
 		opt_state->done = 1;
+		/*
+		 * XXX - optimizer loop detection.
+		 */
+		opt_state->non_branch_movement_performed = 0;
 		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);
+		opt_blks(opt_state, ic, do_stmts);
 #ifdef BDEBUG
 		if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 			printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
-			opt_dump(cstate, ic);
+			opt_dump(opt_state, ic);
 		}
 #endif
-	} while (!opt_state->done);
+
+		/*
+		 * Was anything done in this optimizer pass?
+		 */
+		if (opt_state->done) {
+			/*
+			 * No, so we've reached a fixed point.
+			 * We're done.
+			 */
+			break;
+		}
+
+		/*
+		 * XXX - was anything done other than branch movement
+		 * in this pass?
+		 */
+		if (opt_state->non_branch_movement_performed) {
+			/*
+			 * Yes.  Clear any loop-detection counter;
+			 * we're making some form of progress (assuming
+			 * we can't get into a cycle doing *other*
+			 * optimizations...).
+			 */
+			loop_count = 0;
+		} else {
+			/*
+			 * No - increment the counter, and quit if
+			 * it's up to 100.
+			 */
+			loop_count++;
+			if (loop_count >= 100) {
+				/*
+				 * We've done nothing but branch movement
+				 * for 100 passes; we're probably
+				 * in a cycle and will never reach a
+				 * fixed point.
+				 *
+				 * XXX - yes, we really need a non-
+				 * heuristic way of detecting a cycle.
+				 */
+				opt_state->done = 1;
+				break;
+			}
+		}
+	}
 }
 
 /*
  * Optimize the filter code in its dag representation.
+ * Return 0 on success, -1 on error.
  */
-void
-bpf_optimize(compiler_state_t *cstate, struct icode *ic)
+int
+bpf_optimize(struct icode *ic, char *errbuf)
 {
 	opt_state_t opt_state;
 
-	opt_init(cstate, &opt_state, ic);
-	opt_loop(cstate, &opt_state, ic, 0);
-	opt_loop(cstate, &opt_state, ic, 1);
+	memset(&opt_state, 0, sizeof(opt_state));
+	opt_state.errbuf = errbuf;
+	opt_state.non_branch_movement_performed = 0;
+	if (setjmp(opt_state.top_ctx)) {
+		opt_cleanup(&opt_state);
+		return -1;
+	}
+	opt_init(&opt_state, ic);
+	opt_loop(&opt_state, ic, 0);
+	opt_loop(&opt_state, ic, 1);
 	intern_blocks(&opt_state, ic);
 #ifdef BDEBUG
 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("after intern_blocks()\n");
-		opt_dump(cstate, ic);
+		opt_dump(&opt_state, ic);
 	}
 #endif
 	opt_root(&ic->root);
 #ifdef BDEBUG
 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("after opt_root()\n");
-		opt_dump(cstate, ic);
+		opt_dump(&opt_state, ic);
 	}
 #endif
 	opt_cleanup(&opt_state);
+	return 0;
 }
 
 static void
@@ -1893,7 +2354,7 @@
 intern_blocks(opt_state_t *opt_state, struct icode *ic)
 {
 	struct block *p;
-	int i, j;
+	u_int i, j;
 	int done1; /* don't shadow global */
  top:
 	done1 = 1;
@@ -1902,7 +2363,8 @@
 
 	mark_code(ic);
 
-	for (i = opt_state->n_blocks - 1; --i >= 0; ) {
+	for (i = opt_state->n_blocks - 1; i != 0; ) {
+		--i;
 		if (!isMarked(ic, opt_state->blocks[i]))
 			continue;
 		for (j = i + 1; j < opt_state->n_blocks; ++j) {
@@ -1944,6 +2406,24 @@
 }
 
 /*
+ * For optimizer errors.
+ */
+static void PCAP_NORETURN
+opt_error(opt_state_t *opt_state, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (opt_state->errbuf != NULL) {
+		va_start(ap, fmt);
+		(void)vsnprintf(opt_state->errbuf,
+		    PCAP_ERRBUF_SIZE, fmt, ap);
+		va_end(ap);
+	}
+	longjmp(opt_state->top_ctx, 1);
+	/* NOTREACHED */
+}
+
+/*
  * Return the number of stmts in 's'.
  */
 static u_int
@@ -1977,13 +2457,19 @@
 static void
 number_blks_r(opt_state_t *opt_state, struct icode *ic, struct block *p)
 {
-	int n;
+	u_int n;
 
 	if (p == 0 || isMarked(ic, p))
 		return;
 
 	Mark(ic, p);
 	n = opt_state->n_blocks++;
+	if (opt_state->n_blocks == 0) {
+		/*
+		 * Overflow.
+		 */
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
 	p->id = n;
 	opt_state->blocks[n] = p;
 
@@ -2027,10 +2513,12 @@
  * from the total number of blocks and/or statements.
  */
 static void
-opt_init(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic)
+opt_init(opt_state_t *opt_state, struct icode *ic)
 {
 	bpf_u_int32 *p;
 	int i, n, max_stmts;
+	u_int product;
+	size_t block_memsize, edge_memsize;
 
 	/*
 	 * First, count the blocks, so we can malloc an array to map
@@ -2040,31 +2528,96 @@
 	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");
+		opt_error(opt_state, "malloc");
 	unMarkAll(ic);
 	opt_state->n_blocks = 0;
 	number_blks_r(opt_state, ic, ic->root);
 
+	/*
+	 * This "should not happen".
+	 */
+	if (opt_state->n_blocks == 0)
+		opt_error(opt_state, "filter has no instructions; please report this as a libpcap issue");
+
 	opt_state->n_edges = 2 * opt_state->n_blocks;
+	if ((opt_state->n_edges / 2) != opt_state->n_blocks) {
+		/*
+		 * Overflow.
+		 */
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
 	opt_state->edges = (struct edge **)calloc(opt_state->n_edges, sizeof(*opt_state->edges));
-	if (opt_state->edges == NULL)
-		bpf_error(cstate, "malloc");
+	if (opt_state->edges == NULL) {
+		opt_error(opt_state, "malloc");
+	}
 
 	/*
 	 * The number of levels is bounded by the number of nodes.
 	 */
 	opt_state->levels = (struct block **)calloc(opt_state->n_blocks, sizeof(*opt_state->levels));
-	if (opt_state->levels == NULL)
-		bpf_error(cstate, "malloc");
+	if (opt_state->levels == NULL) {
+		opt_error(opt_state, "malloc");
+	}
 
-	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;
+	opt_state->edgewords = opt_state->n_edges / BITS_PER_WORD + 1;
+	opt_state->nodewords = opt_state->n_blocks / BITS_PER_WORD + 1;
+
+	/*
+	 * Make sure opt_state->n_blocks * opt_state->nodewords fits
+	 * in a u_int; we use it as a u_int number-of-iterations
+	 * value.
+	 */
+	product = opt_state->n_blocks * opt_state->nodewords;
+	if ((product / opt_state->n_blocks) != opt_state->nodewords) {
+		/*
+		 * XXX - just punt and don't try to optimize?
+		 * In practice, this is unlikely to happen with
+		 * a normal filter.
+		 */
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
+
+	/*
+	 * Make sure the total memory required for that doesn't
+	 * overflow.
+	 */
+	block_memsize = (size_t)2 * product * sizeof(*opt_state->space);
+	if ((block_memsize / product) != 2 * sizeof(*opt_state->space)) {
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
+
+	/*
+	 * Make sure opt_state->n_edges * opt_state->edgewords fits
+	 * in a u_int; we use it as a u_int number-of-iterations
+	 * value.
+	 */
+	product = opt_state->n_edges * opt_state->edgewords;
+	if ((product / opt_state->n_edges) != opt_state->edgewords) {
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
+
+	/*
+	 * Make sure the total memory required for that doesn't
+	 * overflow.
+	 */
+	edge_memsize = (size_t)product * sizeof(*opt_state->space);
+	if (edge_memsize / product != sizeof(*opt_state->space)) {
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
+
+	/*
+	 * Make sure the total memory required for both of them dosn't
+	 * overflow.
+	 */
+	if (block_memsize > SIZE_MAX - edge_memsize) {
+		opt_error(opt_state, "filter is too complex to optimize");
+	}
 
 	/* XXX */
-	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");
+	opt_state->space = (bpf_u_int32 *)malloc(block_memsize + edge_memsize);
+	if (opt_state->space == NULL) {
+		opt_error(opt_state, "malloc");
+	}
 	p = opt_state->space;
 	opt_state->all_dom_sets = p;
 	for (i = 0; i < n; ++i) {
@@ -2101,9 +2654,13 @@
 	 */
 	opt_state->maxval = 3 * max_stmts;
 	opt_state->vmap = (struct vmapinfo *)calloc(opt_state->maxval, sizeof(*opt_state->vmap));
+	if (opt_state->vmap == NULL) {
+		opt_error(opt_state, "malloc");
+	}
 	opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
-	if (opt_state->vmap == NULL || opt_state->vnode_base == NULL)
-		bpf_error(cstate, "malloc");
+	if (opt_state->vnode_base == NULL) {
+		opt_error(opt_state, "malloc");
+	}
 }
 
 /*
@@ -2115,6 +2672,9 @@
 int bids[NBIDS];
 #endif
 
+static void PCAP_NORETURN conv_error(conv_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
 /*
  * Returns true if successful.  Returns false if a branch has
  * an offset that is too large.  If so, we have marked that
@@ -2122,23 +2682,21 @@
  * properly.
  */
 static int
-convert_code_r(compiler_state_t *cstate, conv_state_t *conv_state,
-    struct icode *ic, struct block *p)
+convert_code_r(conv_state_t *conv_state, struct icode *ic, struct block *p)
 {
 	struct bpf_insn *dst;
 	struct slist *src;
 	u_int slen;
 	u_int off;
-	u_int extrajmps;	/* number of extra jumps inserted */
 	struct slist **offset = NULL;
 
 	if (p == 0 || isMarked(ic, p))
 		return (1);
 	Mark(ic, p);
 
-	if (convert_code_r(cstate, conv_state, ic, JF(p)) == 0)
+	if (convert_code_r(conv_state, ic, JF(p)) == 0)
 		return (0);
-	if (convert_code_r(cstate, conv_state, ic, JT(p)) == 0)
+	if (convert_code_r(conv_state, ic, JT(p)) == 0)
 		return (0);
 
 	slen = slength(p->stmts);
@@ -2151,7 +2709,7 @@
 	if (slen) {
 		offset = (struct slist **)calloc(slen, sizeof(struct slist *));
 		if (!offset) {
-			bpf_error(cstate, "not enough core");
+			conv_error(conv_state, "not enough core");
 			/*NOTREACHED*/
 		}
 	}
@@ -2175,7 +2733,8 @@
 		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(cstate, "illegal jmp destination");
+				free(offset);
+				conv_error(conv_state, "illegal jmp destination");
 				/*NOTREACHED*/
 			}
 #endif
@@ -2195,7 +2754,8 @@
 #endif
 
 		if (!src->s.jt || !src->s.jf) {
-			bpf_error(cstate, ljerr, "no jmp destination", off);
+			free(offset);
+			conv_error(conv_state, ljerr, "no jmp destination", off);
 			/*NOTREACHED*/
 		}
 
@@ -2203,12 +2763,14 @@
 		for (i = 0; i < slen; i++) {
 			if (offset[i] == src->s.jt) {
 				if (jt) {
-					bpf_error(cstate, ljerr, "multiple matches", off);
+					free(offset);
+					conv_error(conv_state, ljerr, "multiple matches", off);
 					/*NOTREACHED*/
 				}
 
 				if (i - off - 1 >= 256) {
-					bpf_error(cstate, ljerr, "out-of-range jump", off);
+					free(offset);
+					conv_error(conv_state, ljerr, "out-of-range jump", off);
 					/*NOTREACHED*/
 				}
 				dst->jt = (u_char)(i - off - 1);
@@ -2216,11 +2778,13 @@
 			}
 			if (offset[i] == src->s.jf) {
 				if (jf) {
-					bpf_error(cstate, ljerr, "multiple matches", off);
+					free(offset);
+					conv_error(conv_state, ljerr, "multiple matches", off);
 					/*NOTREACHED*/
 				}
 				if (i - off - 1 >= 256) {
-					bpf_error(cstate, ljerr, "out-of-range jump", off);
+					free(offset);
+					conv_error(conv_state, ljerr, "out-of-range jump", off);
 					/*NOTREACHED*/
 				}
 				dst->jf = (u_char)(i - off - 1);
@@ -2228,7 +2792,8 @@
 			}
 		}
 		if (!jt || !jf) {
-			bpf_error(cstate, ljerr, "no destination found", off);
+			free(offset);
+			conv_error(conv_state, ljerr, "no destination found", off);
 			/*NOTREACHED*/
 		}
 	    }
@@ -2246,21 +2811,17 @@
 	dst->code = (u_short)p->s.code;
 	dst->k = p->s.k;
 	if (JT(p)) {
-		extrajmps = 0;
+		/* number of extra jumps inserted */
+		u_char extrajmps = 0;
 		off = JT(p)->offset - (p->offset + slen) - 1;
 		if (off >= 256) {
 		    /* offset too large for branch, must add a jump */
 		    if (p->longjt == 0) {
-		    	/* mark this instruction and retry */
+			/* mark this instruction and retry */
 			p->longjt++;
 			return(0);
 		    }
-		    /* branch if T to following jump */
-		    if (extrajmps >= 256) {
-			bpf_error(cstate, "too many extra jumps");
-			/*NOTREACHED*/
-		    }
-		    dst->jt = (u_char)extrajmps;
+		    dst->jt = extrajmps;
 		    extrajmps++;
 		    dst[extrajmps].code = BPF_JMP|BPF_JA;
 		    dst[extrajmps].k = off - extrajmps;
@@ -2271,17 +2832,13 @@
 		if (off >= 256) {
 		    /* offset too large for branch, must add a jump */
 		    if (p->longjf == 0) {
-		    	/* mark this instruction and retry */
+			/* mark this instruction and retry */
 			p->longjf++;
 			return(0);
 		    }
 		    /* branch if F to following jump */
 		    /* if two jumps are inserted, F goes to second one */
-		    if (extrajmps >= 256) {
-			bpf_error(cstate, "too many extra jumps");
-			/*NOTREACHED*/
-		    }
-		    dst->jf = (u_char)extrajmps;
+		    dst->jf = extrajmps;
 		    extrajmps++;
 		    dst[extrajmps].code = BPF_JMP|BPF_JA;
 		    dst[extrajmps].k = off - extrajmps;
@@ -2312,13 +2869,20 @@
  * done with the filter program.  See the pcap man page.
  */
 struct bpf_insn *
-icode_to_fcode(compiler_state_t *cstate, struct icode *ic,
-    struct block *root, u_int *lenp)
+icode_to_fcode(struct icode *ic, struct block *root, u_int *lenp,
+    char *errbuf)
 {
 	u_int n;
 	struct bpf_insn *fp;
 	conv_state_t conv_state;
 
+	conv_state.fstart = NULL;
+	conv_state.errbuf = errbuf;
+	if (setjmp(conv_state.top_ctx) != 0) {
+		free(conv_state.fstart);
+		return NULL;
+	}
+
 	/*
 	 * Loop doing convert_code_r() until no branches remain
 	 * with too-large offsets.
@@ -2328,14 +2892,18 @@
 	    n = *lenp = count_stmts(ic, root);
 
 	    fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
-	    if (fp == NULL)
-		    bpf_error(cstate, "malloc");
+	    if (fp == NULL) {
+		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "malloc");
+		free(fp);
+		return NULL;
+	    }
 	    memset((char *)fp, 0, sizeof(*fp) * n);
 	    conv_state.fstart = fp;
 	    conv_state.ftail = fp + n;
 
 	    unMarkAll(ic);
-	    if (convert_code_r(cstate, &conv_state, ic, root))
+	    if (convert_code_r(&conv_state, ic, root))
 		break;
 	    free(fp);
 	}
@@ -2344,6 +2912,22 @@
 }
 
 /*
+ * For iconv_to_fconv() errors.
+ */
+static void PCAP_NORETURN
+conv_error(conv_state_t *conv_state, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	(void)vsnprintf(conv_state->errbuf,
+	    PCAP_ERRBUF_SIZE, fmt, ap);
+	va_end(ap);
+	longjmp(conv_state->top_ctx, 1);
+	/* NOTREACHED */
+}
+
+/*
  * Make a copy of a BPF program and put it in the "fcode" member of
  * a "pcap_t".
  *
@@ -2359,8 +2943,8 @@
 	/*
 	 * Validate the program.
 	 */
-	if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+	if (!pcap_validate_filter(fp->bf_insns, fp->bf_len)) {
+		snprintf(p->errbuf, sizeof(p->errbuf),
 			"BPF program is not valid");
 		return (-1);
 	}
@@ -2397,7 +2981,7 @@
 	icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
 	noffset = min(block->offset + icount, (int)prog->bf_len);
 
-	fprintf(out, "\tblock%d [shape=ellipse, id=\"block-%d\" label=\"BLOCK%d\\n", block->id, block->id, block->id);
+	fprintf(out, "\tblock%u [shape=ellipse, id=\"block-%u\" label=\"BLOCK%u\\n", block->id, block->id, block->id);
 	for (i = block->offset; i < noffset; i++) {
 		fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i));
 	}
@@ -2424,9 +3008,9 @@
 	Mark(ic, block);
 
 	if (JT(block)) {
-		fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n",
+		fprintf(out, "\t\"block%u\":se -> \"block%u\":n [label=\"T\"]; \n",
 				block->id, JT(block)->id);
-		fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n",
+		fprintf(out, "\t\"block%u\":sw -> \"block%u\":n [label=\"F\"]; \n",
 			   block->id, JF(block)->id);
 	}
 	dot_dump_edge(ic, JT(block), out);
@@ -2449,17 +3033,19 @@
     	"block1":sw -> "block3":n [label="F"];
     }
  *
- *  After install graphviz on http://www.graphviz.org/, save it as bpf.dot
+ *  After install graphviz on https://www.graphviz.org/, save it as bpf.dot
  *  and run `dot -Tpng -O bpf.dot' to draw the graph.
  */
-static void
-dot_dump(compiler_state_t *cstate, struct icode *ic)
+static int
+dot_dump(struct icode *ic, char *errbuf)
 {
 	struct bpf_program f;
 	FILE *out = stdout;
 
 	memset(bids, 0, sizeof bids);
-	f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
+	f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+	if (f.bf_insns == NULL)
+		return -1;
 
 	fprintf(out, "digraph BPF {\n");
 	unMarkAll(ic);
@@ -2469,30 +3055,39 @@
 	fprintf(out, "}\n");
 
 	free((char *)f.bf_insns);
+	return 0;
 }
 
-static void
-plain_dump(compiler_state_t *cstate, struct icode *ic)
+static int
+plain_dump(struct icode *ic, char *errbuf)
 {
 	struct bpf_program f;
 
 	memset(bids, 0, sizeof bids);
-	f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
+	f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+	if (f.bf_insns == NULL)
+		return -1;
 	bpf_dump(&f, 1);
 	putchar('\n');
 	free((char *)f.bf_insns);
+	return 0;
 }
 
 static void
-opt_dump(compiler_state_t *cstate, struct icode *ic)
+opt_dump(opt_state_t *opt_state, struct icode *ic)
 {
+	int status;
+	char errbuf[PCAP_ERRBUF_SIZE];
+
 	/*
 	 * If the CFG, in DOT format, is requested, output it rather than
 	 * the code that would be generated from that graph.
 	 */
 	if (pcap_print_dot_graph)
-		dot_dump(cstate, ic);
+		status = dot_dump(ic, errbuf);
 	else
-		plain_dump(cstate, ic);
+		status = plain_dump(ic, errbuf);
+	if (status == -1)
+		opt_error(opt_state, "opt_dump: icode_to_fcode failed: %s", errbuf);
 }
 #endif
diff --git a/org.tcpdump.chmod_bpf.plist b/org.tcpdump.chmod_bpf.plist
index 8ad6852..f6fdfec 100644
--- a/org.tcpdump.chmod_bpf.plist
+++ b/org.tcpdump.chmod_bpf.plist
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
 	<key>Label</key>
diff --git a/pcap-airpcap.c b/pcap-airpcap.c
new file mode 100644
index 0000000..703f23a
--- /dev/null
+++ b/pcap-airpcap.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pcap-int.h"
+
+#include <airpcap.h>
+
+#include "pcap-airpcap.h"
+
+/* Default size of the buffer we allocate in userland. */
+#define	AIRPCAP_DEFAULT_USER_BUFFER_SIZE 256000
+
+/* Default size of the buffer for the AirPcap adapter. */
+#define	AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE 1000000
+
+//
+// We load the AirPcap DLL dynamically, so that the code will
+// work whether you have it installed or not, and there don't
+// have to be two different versions of the library, one linked
+// to the AirPcap library and one not linked to it.
+//
+static pcap_code_handle_t airpcap_lib;
+
+typedef PCHAR (*AirpcapGetLastErrorHandler)(PAirpcapHandle);
+typedef BOOL (*AirpcapGetDeviceListHandler)(PAirpcapDeviceDescription *, PCHAR);
+typedef VOID (*AirpcapFreeDeviceListHandler)(PAirpcapDeviceDescription);
+typedef PAirpcapHandle (*AirpcapOpenHandler)(PCHAR, PCHAR);
+typedef VOID (*AirpcapCloseHandler)(PAirpcapHandle);
+typedef BOOL (*AirpcapSetDeviceMacFlagsHandler)(PAirpcapHandle, UINT);
+typedef BOOL (*AirpcapSetLinkTypeHandler)(PAirpcapHandle, AirpcapLinkType);
+typedef BOOL (*AirpcapGetLinkTypeHandler)(PAirpcapHandle, PAirpcapLinkType);
+typedef BOOL (*AirpcapSetKernelBufferHandler)(PAirpcapHandle, UINT);
+typedef BOOL (*AirpcapSetFilterHandler)(PAirpcapHandle, PVOID, UINT);
+typedef BOOL (*AirpcapSetMinToCopyHandler)(PAirpcapHandle, UINT);
+typedef BOOL (*AirpcapGetReadEventHandler)(PAirpcapHandle, HANDLE *);
+typedef BOOL (*AirpcapReadHandler)(PAirpcapHandle, PBYTE, UINT, PUINT);
+typedef BOOL (*AirpcapWriteHandler)(PAirpcapHandle, PCHAR, ULONG);
+typedef BOOL (*AirpcapGetStatsHandler)(PAirpcapHandle, PAirpcapStats);
+
+static AirpcapGetLastErrorHandler p_AirpcapGetLastError;
+static AirpcapGetDeviceListHandler p_AirpcapGetDeviceList;
+static AirpcapFreeDeviceListHandler p_AirpcapFreeDeviceList;
+static AirpcapOpenHandler p_AirpcapOpen;
+static AirpcapCloseHandler p_AirpcapClose;
+static AirpcapSetDeviceMacFlagsHandler p_AirpcapSetDeviceMacFlags;
+static AirpcapSetLinkTypeHandler p_AirpcapSetLinkType;
+static AirpcapGetLinkTypeHandler p_AirpcapGetLinkType;
+static AirpcapSetKernelBufferHandler p_AirpcapSetKernelBuffer;
+static AirpcapSetFilterHandler p_AirpcapSetFilter;
+static AirpcapSetMinToCopyHandler p_AirpcapSetMinToCopy;
+static AirpcapGetReadEventHandler p_AirpcapGetReadEvent;
+static AirpcapReadHandler p_AirpcapRead;
+static AirpcapWriteHandler p_AirpcapWrite;
+static AirpcapGetStatsHandler p_AirpcapGetStats;
+
+typedef enum LONG
+{
+	AIRPCAP_API_UNLOADED = 0,
+	AIRPCAP_API_LOADED,
+	AIRPCAP_API_CANNOT_LOAD,
+	AIRPCAP_API_LOADING
+} AIRPCAP_API_LOAD_STATUS;
+
+static AIRPCAP_API_LOAD_STATUS	airpcap_load_status;
+
+/*
+ * NOTE: this function should be called by the pcap functions that can
+ *       theoretically deal with the AirPcap library for the first time,
+ *       namely listing the adapters and creating a pcap_t for an adapter.
+ *       All the other ones (activate, close, read, write, set parameters)
+ *       work on a pcap_t for an AirPcap device, meaning we've already
+ *       created the pcap_t and thus have loaded the functions, so we do
+ *       not need to call this function.
+ */
+static AIRPCAP_API_LOAD_STATUS
+load_airpcap_functions(void)
+{
+	AIRPCAP_API_LOAD_STATUS current_status;
+
+	/*
+	 * We don't use a mutex because there's no place that
+	 * we can guarantee we'll be called before any threads
+	 * other than the main thread exists.  (For example,
+	 * this might be a static library, so we can't arrange
+	 * to be called by DllMain(), and there's no guarantee
+	 * that the application called pcap_init() - which is
+	 * supposed to be called only from one thread - so
+	 * we can't arrange to be called from it.)
+	 *
+	 * If nobody's tried to load it yet, mark it as
+	 * loading; in any case, return the status before
+	 * we modified it.
+	 */
+	current_status = InterlockedCompareExchange((LONG *)&airpcap_load_status,
+	    AIRPCAP_API_LOADING, AIRPCAP_API_UNLOADED);
+
+	/*
+	 * If the status was AIRPCAP_API_UNLOADED, we've set it
+	 * to AIRPCAP_API_LOADING, because we're going to be
+	 * the ones to load the library but current_status is
+	 * AIRPCAP_API_UNLOADED.
+	 *
+	 * if it was AIRPCAP_API_LOADING, meaning somebody else
+	 * was trying to load it, spin until they finish and
+	 * set the status to a value reflecting whether they
+	 * succeeded.
+	 */
+	while (current_status == AIRPCAP_API_LOADING) {
+		current_status = InterlockedCompareExchange((LONG*)&airpcap_load_status,
+		    AIRPCAP_API_LOADING, AIRPCAP_API_LOADING);
+		Sleep(10);
+	}
+
+	/*
+	 * At this point, current_status is either:
+	 *
+	 *	AIRPCAP_API_LOADED, in which case another thread
+	 *	loaded the library, so we're done;
+	 *
+	 *	AIRPCAP_API_CANNOT_LOAD, in which another thread
+	 *	tried and failed to load the library, so we're
+	 *	done - we won't try it ourselves;
+	 *
+	 *	AIRPCAP_API_LOADING, in which case *we're* the
+	 *	ones loading it, and should now try to do so.
+	 */
+	if (current_status  == AIRPCAP_API_LOADED)
+		return AIRPCAP_API_LOADED;
+
+	if (current_status == AIRPCAP_API_CANNOT_LOAD)
+		return AIRPCAP_API_CANNOT_LOAD;
+
+	/*
+	 * Start out assuming we can't load it.
+	 */
+	current_status = AIRPCAP_API_CANNOT_LOAD;
+
+	airpcap_lib = pcap_load_code("airpcap.dll");
+	if (airpcap_lib != NULL) {
+		/*
+		 * OK, we've loaded the library; now try to find the
+		 * functions we need in it.
+		 */
+		p_AirpcapGetLastError = (AirpcapGetLastErrorHandler) pcap_find_function(airpcap_lib, "AirpcapGetLastError");
+		p_AirpcapGetDeviceList = (AirpcapGetDeviceListHandler) pcap_find_function(airpcap_lib, "AirpcapGetDeviceList");
+		p_AirpcapFreeDeviceList = (AirpcapFreeDeviceListHandler) pcap_find_function(airpcap_lib, "AirpcapFreeDeviceList");
+		p_AirpcapOpen = (AirpcapOpenHandler) pcap_find_function(airpcap_lib, "AirpcapOpen");
+		p_AirpcapClose = (AirpcapCloseHandler) pcap_find_function(airpcap_lib, "AirpcapClose");
+		p_AirpcapSetDeviceMacFlags = (AirpcapSetDeviceMacFlagsHandler) pcap_find_function(airpcap_lib, "AirpcapSetDeviceMacFlags");
+		p_AirpcapSetLinkType = (AirpcapSetLinkTypeHandler) pcap_find_function(airpcap_lib, "AirpcapSetLinkType");
+		p_AirpcapGetLinkType = (AirpcapGetLinkTypeHandler) pcap_find_function(airpcap_lib, "AirpcapGetLinkType");
+		p_AirpcapSetKernelBuffer = (AirpcapSetKernelBufferHandler) pcap_find_function(airpcap_lib, "AirpcapSetKernelBuffer");
+		p_AirpcapSetFilter = (AirpcapSetFilterHandler) pcap_find_function(airpcap_lib, "AirpcapSetFilter");
+		p_AirpcapSetMinToCopy = (AirpcapSetMinToCopyHandler) pcap_find_function(airpcap_lib, "AirpcapSetMinToCopy");
+		p_AirpcapGetReadEvent = (AirpcapGetReadEventHandler) pcap_find_function(airpcap_lib, "AirpcapGetReadEvent");
+		p_AirpcapRead = (AirpcapReadHandler) pcap_find_function(airpcap_lib, "AirpcapRead");
+		p_AirpcapWrite = (AirpcapWriteHandler) pcap_find_function(airpcap_lib, "AirpcapWrite");
+		p_AirpcapGetStats = (AirpcapGetStatsHandler) pcap_find_function(airpcap_lib, "AirpcapGetStats");
+
+		//
+		// Make sure that we found everything
+		//
+		if (p_AirpcapGetLastError != NULL &&
+		    p_AirpcapGetDeviceList != NULL &&
+		    p_AirpcapFreeDeviceList != NULL &&
+		    p_AirpcapOpen != NULL &&
+		    p_AirpcapClose != NULL &&
+		    p_AirpcapSetDeviceMacFlags != NULL &&
+		    p_AirpcapSetLinkType != NULL &&
+		    p_AirpcapGetLinkType != NULL &&
+		    p_AirpcapSetKernelBuffer != NULL &&
+		    p_AirpcapSetFilter != NULL &&
+		    p_AirpcapSetMinToCopy != NULL &&
+		    p_AirpcapGetReadEvent != NULL &&
+		    p_AirpcapRead != NULL &&
+		    p_AirpcapWrite != NULL &&
+		    p_AirpcapGetStats != NULL) {
+			/*
+			 * We have all we need.
+			 */
+			current_status = AIRPCAP_API_LOADED;
+		}
+	}
+
+	if (current_status != AIRPCAP_API_LOADED) {
+		/*
+		 * We failed; if we found the DLL, close the
+		 * handle for it.
+		 */
+		if (airpcap_lib != NULL) {
+			FreeLibrary(airpcap_lib);
+			airpcap_lib = NULL;
+		}
+	}
+
+	/*
+	 * Now set the status appropriately - and atomically.
+	 */
+	InterlockedExchange((LONG *)&airpcap_load_status, current_status);
+
+	return current_status;
+}
+
+/*
+ * Private data for capturing on AirPcap devices.
+ */
+struct pcap_airpcap {
+	PAirpcapHandle adapter;
+	int filtering_in_kernel;
+	int nonblock;
+	int read_timeout;
+	HANDLE read_event;
+	struct pcap_stat stat;
+};
+
+static int
+airpcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	if (!p_AirpcapSetFilter(pa->adapter, fp->bf_insns,
+	    fp->bf_len * sizeof(struct bpf_insn))) {
+		/*
+		 * Kernel filter not installed.
+		 *
+		 * XXX - we don't know whether this failed because:
+		 *
+		 *  the kernel rejected the filter program as invalid,
+		 *  in which case we should fall back on userland
+		 *  filtering;
+		 *
+		 *  the kernel rejected the filter program as too big,
+		 *  in which case we should again fall back on
+		 *  userland filtering;
+		 *
+		 *  there was some other problem, in which case we
+		 *  should probably report an error;
+		 *
+		 * So we just fall back on userland filtering in
+		 * all cases.
+		 */
+
+		/*
+		 * install_bpf_program() validates the program.
+		 *
+		 * XXX - what if we already have a filter in the kernel?
+		 */
+		if (install_bpf_program(p, fp) < 0)
+			return (-1);
+		pa->filtering_in_kernel = 0;	/* filtering in userland */
+		return (0);
+	}
+
+	/*
+	 * It worked.
+	 */
+	pa->filtering_in_kernel = 1;	/* filtering in the kernel */
+
+	/*
+	 * Discard any previously-received packets, as they might have
+	 * passed whatever filter was formerly in effect, but might
+	 * not pass this filter (BIOCSETF discards packets buffered
+	 * in the kernel, so you can lose packets in any case).
+	 */
+	p->cc = 0;
+	return (0);
+}
+
+static int
+airpcap_set_datalink(pcap_t *p, int dlt)
+{
+	struct pcap_airpcap *pa = p->priv;
+	AirpcapLinkType type;
+
+	switch (dlt) {
+
+	case DLT_IEEE802_11_RADIO:
+		type = AIRPCAP_LT_802_11_PLUS_RADIO;
+		break;
+
+	case DLT_PPI:
+		type = AIRPCAP_LT_802_11_PLUS_PPI;
+		break;
+
+	case DLT_IEEE802_11:
+		type = AIRPCAP_LT_802_11;
+		break;
+
+	default:
+		/* This can't happen; just return. */
+		return (0);
+	}
+	if (!p_AirpcapSetLinkType(pa->adapter, type)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapSetLinkType() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (-1);
+	}
+	p->linktype = dlt;
+	return (0);
+}
+
+static int
+airpcap_getnonblock(pcap_t *p)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	return (pa->nonblock);
+}
+
+static int
+airpcap_setnonblock(pcap_t *p, int nonblock)
+{
+	struct pcap_airpcap *pa = p->priv;
+	int newtimeout;
+
+	if (nonblock) {
+		/*
+		 * Set the packet buffer timeout to -1 for non-blocking
+		 * mode.
+		 */
+		newtimeout = -1;
+	} else {
+		/*
+		 * Restore the timeout set when the device was opened.
+		 * (Note that this may be -1, in which case we're not
+		 * really leaving non-blocking mode.  However, although
+		 * the timeout argument to pcap_set_timeout() and
+		 * pcap_open_live() is an int, you're not supposed to
+		 * supply a negative value, so that "shouldn't happen".)
+		 */
+		newtimeout = p->opt.timeout;
+	}
+	pa->read_timeout = newtimeout;
+	pa->nonblock = (newtimeout == -1);
+	return (0);
+}
+
+static int
+airpcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+	struct pcap_airpcap *pa = p->priv;
+	AirpcapStats tas;
+
+	/*
+	 * Try to get statistics.
+	 */
+	if (!p_AirpcapGetStats(pa->adapter, &tas)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetStats() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (-1);
+	}
+
+	ps->ps_drop = tas.Drops;
+	ps->ps_recv = tas.Recvs;
+	ps->ps_ifdrop = tas.IfDrops;
+
+	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:
+ *
+ *    https://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.
+ */
+static struct pcap_stat *
+airpcap_stats_ex(pcap_t *p, int *pcap_stat_size)
+{
+	struct pcap_airpcap *pa = p->priv;
+	AirpcapStats tas;
+
+	*pcap_stat_size = sizeof (p->stat);
+
+	/*
+	 * Try to get statistics.
+	 */
+	if (!p_AirpcapGetStats(pa->adapter, &tas)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetStats() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (NULL);
+	}
+
+	p->stat.ps_recv = tas.Recvs;
+	p->stat.ps_drop = tas.Drops;
+	p->stat.ps_ifdrop = tas.IfDrops;
+	/*
+	 * Just in case this is ever compiled for a target other than
+	 * Windows, which is extremely unlikely at best.
+	 */
+#ifdef _WIN32
+	p->stat.ps_capt = tas.Capt;
+#endif
+	return (&p->stat);
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+airpcap_setbuff(pcap_t *p, int dim)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	if (!p_AirpcapSetKernelBuffer(pa->adapter, dim)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapSetKernelBuffer() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (-1);
+	}
+	return (0);
+}
+
+/* Set the driver working mode */
+static int
+airpcap_setmode(pcap_t *p, int mode)
+{
+	 if (mode != MODE_CAPT) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Only MODE_CAPT is supported on an AirPcap adapter");
+		return (-1);
+	 }
+	 return (0);
+}
+
+/*set the minimum amount of data that will release a read call*/
+static int
+airpcap_setmintocopy(pcap_t *p, int size)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	if (!p_AirpcapSetMinToCopy(pa->adapter, size)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapSetMinToCopy() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (-1);
+	}
+	return (0);
+}
+
+static HANDLE
+airpcap_getevent(pcap_t *p)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	return (pa->read_event);
+}
+
+static int
+airpcap_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+    size_t *lenp _U_)
+{
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Getting OID values is not supported on an AirPcap adapter");
+	return (PCAP_ERROR);
+}
+
+static int
+airpcap_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+    size_t *lenp _U_)
+{
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Setting OID values is not supported on an AirPcap adapter");
+	return (PCAP_ERROR);
+}
+
+static u_int
+airpcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
+{
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Cannot queue packets for transmission on an AirPcap adapter");
+	return (0);
+}
+
+static int
+airpcap_setuserbuffer(pcap_t *p, int size)
+{
+	unsigned char *new_buff;
+
+	if (size <= 0) {
+		/* Bogus parameter */
+		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) {
+		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
+airpcap_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_,
+    int maxpacks _U_)
+{
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "AirPcap adapters don't support live dump");
+	return (-1);
+}
+
+static int
+airpcap_live_dump_ended(pcap_t *p, int sync _U_)
+{
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "AirPcap adapters don't support live dump");
+	return (-1);
+}
+
+static PAirpcapHandle
+airpcap_get_airpcap_handle(pcap_t *p)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	return (pa->adapter);
+}
+
+static int
+airpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+	struct pcap_airpcap *pa = p->priv;
+	int cc;
+	int n;
+	register u_char *bp, *ep;
+	UINT bytes_read;
+	u_char *datap;
+
+	cc = p->cc;
+	if (cc == 0) {
+		/*
+		 * Has "pcap_breakloop()" been called?
+		 */
+		if (p->break_loop) {
+			/*
+			 * Yes - clear the flag that indicates that it
+			 * has, and return PCAP_ERROR_BREAK to indicate
+			 * that we were told to break out of the loop.
+			 */
+			p->break_loop = 0;
+			return (PCAP_ERROR_BREAK);
+		}
+
+		//
+		// If we're not in non-blocking mode, wait for data to
+		// arrive.
+		//
+		if (pa->read_timeout != -1) {
+			WaitForSingleObject(pa->read_event,
+			    (pa->read_timeout ==0 )? INFINITE: pa->read_timeout);
+		}
+
+		//
+		// Read the data.
+		// p_AirpcapRead doesn't block.
+		//
+		if (!p_AirpcapRead(pa->adapter, (PBYTE)p->buffer,
+		    p->bufsize, &bytes_read)) {
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "AirpcapRead() failed: %s",
+			    p_AirpcapGetLastError(pa->adapter));
+			return (-1);
+		}
+		cc = bytes_read;
+		bp = (u_char *)p->buffer;
+	} else
+		bp = p->bp;
+
+	/*
+	 * Loop through each packet.
+	 */
+#define bhp ((AirpcapBpfHeader *)bp)
+	n = 0;
+	ep = bp + cc;
+	for (;;) {
+		register u_int caplen, hdrlen;
+
+		/*
+		 * Has "pcap_breakloop()" been called?
+		 * If so, return immediately - if we haven't read any
+		 * packets, clear the flag and return PCAP_ERROR_BREAK
+		 * to indicate that we were told to break out of the loop,
+		 * otherwise leave the flag set, so that the *next* call
+		 * will break out of the loop without having read any
+		 * packets, and return the number of packets we've
+		 * processed so far.
+		 */
+		if (p->break_loop) {
+			if (n == 0) {
+				p->break_loop = 0;
+				return (PCAP_ERROR_BREAK);
+			} else {
+				p->bp = bp;
+				p->cc = (int) (ep - bp);
+				return (n);
+			}
+		}
+		if (bp >= ep)
+			break;
+
+		caplen = bhp->Caplen;
+		hdrlen = bhp->Hdrlen;
+		datap = bp + hdrlen;
+		/*
+		 * Short-circuit evaluation: if using BPF filter
+		 * in the AirPcap adapter, no need to do it now -
+		 * we already know the packet passed the filter.
+		 */
+		if (pa->filtering_in_kernel ||
+		    p->fcode.bf_insns == NULL ||
+		    pcap_filter(p->fcode.bf_insns, datap, bhp->Originallen, caplen)) {
+			struct pcap_pkthdr pkthdr;
+
+			pkthdr.ts.tv_sec = bhp->TsSec;
+			pkthdr.ts.tv_usec = bhp->TsUsec;
+			pkthdr.caplen = caplen;
+			pkthdr.len = bhp->Originallen;
+			(*callback)(user, &pkthdr, datap);
+			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
+			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+				p->bp = bp;
+				p->cc = (int)(ep - bp);
+				return (n);
+			}
+		} else {
+			/*
+			 * Skip this packet.
+			 */
+			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
+		}
+	}
+#undef bhp
+	p->cc = 0;
+	return (n);
+}
+
+static int
+airpcap_inject(pcap_t *p, const void *buf, int size)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	/*
+	 * XXX - the second argument to AirpcapWrite() *should* have
+	 * been declared as a const pointer - a write function that
+	 * stomps on what it writes is *extremely* rude - but such
+	 * is life.  We assume it is, in fact, not going to write on
+	 * our buffer.
+	 */
+	if (!p_AirpcapWrite(pa->adapter, (void *)buf, size)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapWrite() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (-1);
+	}
+
+	/*
+	 * We assume it all got sent if "AirpcapWrite()" succeeded.
+	 * "pcap_inject()" is expected to return the number of bytes
+	 * sent.
+	 */
+	return (size);
+}
+
+static void
+airpcap_cleanup(pcap_t *p)
+{
+	struct pcap_airpcap *pa = p->priv;
+
+	if (pa->adapter != NULL) {
+		p_AirpcapClose(pa->adapter);
+		pa->adapter = NULL;
+	}
+	pcap_cleanup_live_common(p);
+}
+
+static void
+airpcap_breakloop(pcap_t *p)
+{
+	HANDLE read_event;
+
+	pcap_breakloop_common(p);
+	struct pcap_airpcap *pa = p->priv;
+
+	/* XXX - what if either of these fail? */
+	/*
+	 * XXX - will SetEvent() force a wakeup and, if so, will
+	 * the AirPcap read code handle that sanely?
+	 */
+	if (!p_AirpcapGetReadEvent(pa->adapter, &read_event))
+		return;
+	SetEvent(read_event);
+}
+
+static int
+airpcap_activate(pcap_t *p)
+{
+	struct pcap_airpcap *pa = p->priv;
+	char *device = p->opt.device;
+	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
+	BOOL status;
+	AirpcapLinkType link_type;
+
+	pa->adapter = p_AirpcapOpen(device, airpcap_errbuf);
+	if (pa->adapter == NULL) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", airpcap_errbuf);
+		return (PCAP_ERROR);
+	}
+
+	/*
+	 * Set monitor mode appropriately.
+	 * Always turn off the "ACK frames sent to the card" mode.
+	 */
+	if (p->opt.rfmon) {
+		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
+		    AIRPCAP_MF_MONITOR_MODE_ON);
+	} else
+		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
+		    AIRPCAP_MF_ACK_FRAMES_ON);
+	if (!status) {
+		p_AirpcapClose(pa->adapter);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapSetDeviceMacFlags() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		return (PCAP_ERROR);
+	}
+
+	/*
+	 * Turn a negative snapshot value (invalid), a snapshot value of
+	 * 0 (unspecified), or a value bigger than the normal maximum
+	 * value, into the maximum allowed value.
+	 *
+	 * If some application really *needs* a bigger snapshot
+	 * length, we should just increase MAXIMUM_SNAPLEN.
+	 */
+	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+		p->snapshot = MAXIMUM_SNAPLEN;
+
+	/*
+	 * If the buffer size wasn't explicitly set, default to
+	 * AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE.
+	 */
+	if (p->opt.buffer_size == 0)
+		p->opt.buffer_size = AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE;
+
+	if (!p_AirpcapSetKernelBuffer(pa->adapter, p->opt.buffer_size)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapSetKernelBuffer() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		goto bad;
+	}
+
+	if(!p_AirpcapGetReadEvent(pa->adapter, &pa->read_event)) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetReadEvent() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		goto bad;
+	}
+
+	/* Set the buffer size */
+	p->bufsize = AIRPCAP_DEFAULT_USER_BUFFER_SIZE;
+	p->buffer = malloc(p->bufsize);
+	if (p->buffer == NULL) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
+		goto bad;
+	}
+
+	if (p->opt.immediate) {
+		/* Tell the driver to copy the buffer as soon as data arrives. */
+		if (!p_AirpcapSetMinToCopy(pa->adapter, 0)) {
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "AirpcapSetMinToCopy() failed: %s",
+			    p_AirpcapGetLastError(pa->adapter));
+			goto bad;
+		}
+	} else {
+		/*
+		 * Tell the driver to copy the buffer only if it contains
+		 * at least 16K.
+		 */
+		if (!p_AirpcapSetMinToCopy(pa->adapter, 16000)) {
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "AirpcapSetMinToCopy() failed: %s",
+			    p_AirpcapGetLastError(pa->adapter));
+			goto bad;
+		}
+	}
+
+	/*
+	 * Find out what the default link-layer header type is,
+	 * and set p->datalink to that.
+	 *
+	 * We don't force it to another value because there
+	 * might be some programs using WinPcap/Npcap that,
+	 * when capturing on AirPcap devices, assume the
+	 * default value set with the AirPcap configuration
+	 * program is what you get.
+	 *
+	 * The out-of-the-box default appears to be radiotap.
+	 */
+	if (!p_AirpcapGetLinkType(pa->adapter, &link_type)) {
+		/* That failed. */
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetLinkType() failed: %s",
+		    p_AirpcapGetLastError(pa->adapter));
+		goto bad;
+	}
+	switch (link_type) {
+
+	case AIRPCAP_LT_802_11_PLUS_RADIO:
+		p->linktype = DLT_IEEE802_11_RADIO;
+		break;
+
+	case AIRPCAP_LT_802_11_PLUS_PPI:
+		p->linktype = DLT_PPI;
+		break;
+
+	case AIRPCAP_LT_802_11:
+		p->linktype = DLT_IEEE802_11;
+		break;
+
+	case AIRPCAP_LT_UNKNOWN:
+	default:
+		/* OK, what? */
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetLinkType() returned unknown link type %u",
+		    link_type);
+		goto bad;
+	}
+
+	/*
+	 * Now provide a list of all the supported types; we
+	 * assume they all work.  We put radiotap at the top,
+	 * followed by PPI, followed by "no radio metadata".
+	 */
+	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 3);
+	if (p->dlt_list == NULL)
+		goto bad;
+	p->dlt_list[0] = DLT_IEEE802_11_RADIO;
+	p->dlt_list[1] = DLT_PPI;
+	p->dlt_list[2] = DLT_IEEE802_11;
+	p->dlt_count = 3;
+
+	p->read_op = airpcap_read;
+	p->inject_op = airpcap_inject;
+	p->setfilter_op = airpcap_setfilter;
+	p->setdirection_op = NULL;	/* Not implemented. */
+	p->set_datalink_op = airpcap_set_datalink;
+	p->getnonblock_op = airpcap_getnonblock;
+	p->setnonblock_op = airpcap_setnonblock;
+	p->breakloop_op = airpcap_breakloop;
+	p->stats_op = airpcap_stats;
+	p->stats_ex_op = airpcap_stats_ex;
+	p->setbuff_op = airpcap_setbuff;
+	p->setmode_op = airpcap_setmode;
+	p->setmintocopy_op = airpcap_setmintocopy;
+	p->getevent_op = airpcap_getevent;
+	p->oid_get_request_op = airpcap_oid_get_request;
+	p->oid_set_request_op = airpcap_oid_set_request;
+	p->sendqueue_transmit_op = airpcap_sendqueue_transmit;
+	p->setuserbuffer_op = airpcap_setuserbuffer;
+	p->live_dump_op = airpcap_live_dump;
+	p->live_dump_ended_op = airpcap_live_dump_ended;
+	p->get_airpcap_handle_op = airpcap_get_airpcap_handle;
+	p->cleanup_op = airpcap_cleanup;
+
+	return (0);
+ bad:
+	airpcap_cleanup(p);
+	return (PCAP_ERROR);
+}
+
+/*
+ * Monitor mode is supported.
+ */
+static int
+airpcap_can_set_rfmon(pcap_t *p)
+{
+	return (1);
+}
+
+int
+device_is_airpcap(const char *device, char *ebuf)
+{
+	static const char airpcap_prefix[] = "\\\\.\\airpcap";
+
+	/*
+	 * We don't determine this by calling AirpcapGetDeviceList()
+	 * and looking at the list, as that appears to be a costly
+	 * operation.
+	 *
+	 * Instead, we just check whether it begins with "\\.\airpcap".
+	 */
+	if (strncmp(device, airpcap_prefix, sizeof airpcap_prefix - 1) == 0) {
+		/*
+		 * Yes, it's an AirPcap device.
+		 */
+		return (1);
+	}
+
+	/*
+	 * No, it's not an AirPcap device.
+	 */
+	return (0);
+}
+
+pcap_t *
+airpcap_create(const char *device, char *ebuf, int *is_ours)
+{
+	int ret;
+	pcap_t *p;
+
+	/*
+	 * This can be called before we've tried loading the library,
+	 * so do so if we haven't already tried to do so.
+	 */
+	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "Couldn't load AirPcap DLL\n");
+		return (NULL);
+	}
+
+	/*
+	 * Is this an AirPcap device?
+	 */
+	ret = device_is_airpcap(device, ebuf);
+	if (ret == 0) {
+		/* No. */
+		*is_ours = 0;
+		return (NULL);
+	}
+
+	/*
+	 * Yes.
+	 */
+	*is_ours = 1;
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
+	if (p == NULL)
+		return (NULL);
+
+	p->activate_op = airpcap_activate;
+	p->can_set_rfmon_op = airpcap_can_set_rfmon;
+	return (p);
+}
+
+/*
+ * Add all AirPcap devices.
+ */
+int
+airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+	AirpcapDeviceDescription *airpcap_devices, *airpcap_device;
+	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
+
+	/*
+	 * This can be called before we've tried loading the library,
+	 * so do so if we haven't already tried to do so.
+	 */
+	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
+		/*
+		 * XXX - unless the error is "no such DLL", report this
+		 * as an error rather than as "no AirPcap devices"?
+		 */
+		return (0);
+	}
+
+	if (!p_AirpcapGetDeviceList(&airpcap_devices, airpcap_errbuf)) {
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "AirpcapGetDeviceList() failed: %s", airpcap_errbuf);
+		return (-1);
+	}
+
+	for (airpcap_device = airpcap_devices; airpcap_device != NULL;
+	    airpcap_device = airpcap_device->next) {
+		if (add_dev(devlistp, airpcap_device->Name, 0,
+		    airpcap_device->Description, errbuf) == NULL) {
+			/*
+			 * Failure.
+			 */
+			p_AirpcapFreeDeviceList(airpcap_devices);
+			return (-1);
+		}
+	}
+	p_AirpcapFreeDeviceList(airpcap_devices);
+	return (0);
+}
diff --git a/pcap-airpcap.h b/pcap-airpcap.h
new file mode 100644
index 0000000..aa1164e
--- /dev/null
+++ b/pcap-airpcap.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+pcap_t *airpcap_create(const char *, char *, int *);
+int airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
+int device_is_airpcap(const char *device, char *ebuf);
diff --git a/pcap-bpf.c b/pcap-bpf.c
index 6ce383b..f0ccb96 100644
--- a/pcap-bpf.c
+++ b/pcap-bpf.c
@@ -115,7 +115,6 @@
 
 #endif /* _AIX */
 
-#include <ctype.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <netdb.h>
@@ -153,7 +152,7 @@
 	 * As there is a header on the front size of the mmap'd buffer, only
 	 * some of the buffer is exposed to libpcap as a whole via bufsize;
 	 * zbufsize is the true size.  zbuffer tracks the current zbuf
-	 * assocated with buffer so that it can be used to decide which the
+	 * associated with buffer so that it can be used to decide which the
 	 * next buffer to read will be.
 	 */
 	u_char *zbuf1, *zbuf2, *zbuffer;
@@ -206,7 +205,7 @@
 #  endif
 
 #  if defined(__APPLE__)
-static void remove_en(pcap_t *);
+static void remove_non_802_11(pcap_t *);
 static void remove_802_11(pcap_t *);
 #  endif
 
@@ -313,7 +312,7 @@
 		    atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
 			pb->bzh = bzh;
 			pb->zbuffer = (u_char *)pb->zbuf2;
-  			p->buffer = pb->zbuffer + sizeof(*bzh);
+			p->buffer = pb->zbuffer + sizeof(*bzh);
 			*cc = bzh->bzh_kernel_len;
 			return (1);
 		}
@@ -445,7 +444,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_bpf);
 	if (p == NULL)
 		return (NULL);
 
@@ -456,7 +455,6 @@
 	 * We claim that we support microsecond and nanosecond time
 	 * stamps.
 	 */
-	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
@@ -466,6 +464,7 @@
 	}
 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
 	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+	p->tstamp_precision_count = 2;
 #endif /* BIOCSTSTAMP */
 	return (p);
 }
@@ -522,7 +521,7 @@
 		 * that isn't in use.
 		 */
 		do {
-			(void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+			(void)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
@@ -557,7 +556,7 @@
 				 * means we probably have no BPF
 				 * devices.
 				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "(there are no BPF devices)");
 			} else {
 				/*
@@ -566,7 +565,7 @@
 				 * devices, but all the ones
 				 * that exist are busy.
 				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "(all BPF devices are busy)");
 			}
 			break;
@@ -597,6 +596,102 @@
 }
 
 /*
+ * Bind a network adapter to a BPF device, given a descriptor for the
+ * BPF device and the name of the network adapter.
+ *
+ * Use BIOCSETLIF if available (meaning "on Solaris"), as it supports
+ * longer device names.
+ *
+ * If the name is longer than will fit, return PCAP_ERROR_NO_SUCH_DEVICE
+ * before trying to bind the interface, as there cannot be such a device.
+ *
+ * If the attempt succeeds, return BPF_BIND_SUCCEEDED.
+ *
+ * If the attempt fails:
+ *
+ *    if it fails with ENXIO, return PCAP_ERROR_NO_SUCH_DEVICE, as
+ *    the device doesn't exist;
+ *
+ *    if it fails with ENETDOWN, return PCAP_ERROR_IFACE_NOT_UP, as
+ *    the interface exists but isn't up and the OS doesn't allow
+ *    binding to an interface that isn't up;
+ *
+ *    if it fails with ENOBUFS, return BPF_BIND_BUFFER_TOO_BIG, and
+ *    fill in an error message, as the buffer being requested is too
+ *    large;
+ *
+ *    otherwise, return PCAP_ERROR and fill in an error message.
+ */
+#define BPF_BIND_SUCCEEDED	0
+#define BPF_BIND_BUFFER_TOO_BIG	1
+
+static int
+bpf_bind(int fd, const char *name, char *errbuf)
+{
+	int status;
+#ifdef LIFNAMSIZ
+	struct lifreq ifr;
+
+	if (strlen(name) >= sizeof(ifr.lifr_name)) {
+		/* The name is too long, so it can't possibly exist. */
+		return (PCAP_ERROR_NO_SUCH_DEVICE);
+	}
+	(void)pcap_strlcpy(ifr.lifr_name, name, sizeof(ifr.lifr_name));
+	status = ioctl(fd, BIOCSETLIF, (caddr_t)&ifr);
+#else
+	struct ifreq ifr;
+
+	if (strlen(name) >= sizeof(ifr.ifr_name)) {
+		/* The name is too long, so it can't possibly exist. */
+		return (PCAP_ERROR_NO_SUCH_DEVICE);
+	}
+	(void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	status = ioctl(fd, BIOCSETIF, (caddr_t)&ifr);
+#endif
+
+	if (status < 0) {
+		switch (errno) {
+
+		case ENXIO:
+			/*
+			 * There's no such device.
+			 */
+			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.
+			 */
+			return (PCAP_ERROR_IFACE_NOT_UP);
+
+		case ENOBUFS:
+			/*
+			 * The buffer size is too big.
+			 * Return a special indication so that, if we're
+			 * trying to crank the buffer size down, we know
+			 * we have to continue; add an error message that
+			 * tells the user what needs to be fixed.
+			 */
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "The requested buffer size for %s is too large",
+			    name);
+			return (BPF_BIND_BUFFER_TOO_BIG);
+
+		default:
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "Binding interface %s to BPF device failed",
+			    name);
+			return (PCAP_ERROR);
+		}
+	}
+	return (BPF_BIND_SUCCEEDED);
+}
+
+/*
  * 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.
@@ -608,7 +703,7 @@
 bpf_open_and_bind(const char *name, char *errbuf)
 {
 	int fd;
-	struct ifreq ifr;
+	int status;
 
 	/*
 	 * First, open a BPF device.
@@ -620,34 +715,18 @@
 	/*
 	 * 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:
+	status = bpf_bind(fd, name, errbuf);
+	if (status != BPF_BIND_SUCCEEDED) {
+		close(fd);
+		if (status == BPF_BIND_BUFFER_TOO_BIG) {
 			/*
-			 * There's no such device.
+			 * We didn't specify a buffer size, so
+			 * this *really* shouldn't fail because
+			 * there's no buffer space.  Fail.
 			 */
-			close(fd);
-			return (PCAP_ERROR_NO_SUCH_DEVICE);
-
-		case ENETDOWN:
-			/*
-			 * Return a "network down" indication, so that
-			 * the application can report that rather than
-			 * saying we had a mysterious failure and
-			 * suggest that they report a problem to the
-			 * libpcap developers.
-			 */
-			close(fd);
-			return (PCAP_ERROR_IFACE_NOT_UP);
-
-		default:
-			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "BIOCSETIF: %s", name);
-			close(fd);
 			return (PCAP_ERROR);
 		}
+		return (status);
 	}
 
 	/*
@@ -656,6 +735,47 @@
 	return (fd);
 }
 
+#ifdef __APPLE__
+static int
+device_exists(int fd, const char *name, char *errbuf)
+{
+	int status;
+	struct ifreq ifr;
+
+	if (strlen(name) >= sizeof(ifr.ifr_name)) {
+		/* The name is too long, so it can't possibly exist. */
+		return (PCAP_ERROR_NO_SUCH_DEVICE);
+	}
+	(void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	status = ioctl(fd, SIOCGIFFLAGS, (caddr_t)&ifr);
+
+	if (status < 0) {
+		if (errno == ENXIO || errno == EINVAL) {
+			/*
+			 * macOS and *BSD return one of those two
+			 * errors if the device doesn't exist.
+			 * Don't fill in an error, as this is
+			 * an "expected" condition.
+			 */
+			return (PCAP_ERROR_NO_SUCH_DEVICE);
+		}
+
+		/*
+		 * Some other error - provide a message for it, as
+		 * it's "unexpected".
+		 */
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+		    "Can't get interface flags on %s", name);
+		return (PCAP_ERROR);
+	}
+
+	/*
+	 * The device exists.
+	 */
+	return (0);
+}
+#endif
+
 #ifdef BIOCGDLTLIST
 static int
 get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
@@ -737,15 +857,15 @@
 }
 #endif
 
+#if defined(__APPLE__)
 static int
 pcap_can_set_rfmon_bpf(pcap_t *p)
 {
-#if defined(__APPLE__)
 	struct utsname osinfo;
-	struct ifreq ifr;
 	int fd;
 #ifdef BIOCGDLTLIST
 	struct bpf_dltlist bdl;
+	int err;
 #endif
 
 	/*
@@ -783,6 +903,9 @@
 		return (0);
 	}
 	if (osinfo.release[0] == '8' && osinfo.release[1] == '.') {
+		char *wlt_name;
+		int status;
+
 		/*
 		 * 10.4 (Darwin 8.x).  s/en/wlt/, and check
 		 * whether the device exists.
@@ -799,16 +922,24 @@
 			    errno, "socket");
 			return (PCAP_ERROR);
 		}
-		strlcpy(ifr.ifr_name, "wlt", 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?
-			 */
+		if (pcap_asprintf(&wlt_name, "wlt%s", p->opt.device + 2) == -1) {
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "malloc");
 			close(fd);
-			return (0);
+			return (PCAP_ERROR);
 		}
+		status = device_exists(fd, wlt_name, p->errbuf);
+		free(wlt_name);
 		close(fd);
+		if (status != 0) {
+			if (status == PCAP_ERROR_NO_SUCH_DEVICE)
+				return (0);
+
+			/*
+			 * Error.
+			 */
+			return (status);
+		}
 		return (1);
 	}
 
@@ -827,34 +958,18 @@
 	/*
 	 * Now bind to the device.
 	 */
-	(void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
-	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
-		switch (errno) {
-
-		case ENXIO:
+	err = bpf_bind(fd, p->opt.device, p->errbuf);
+	if (err != BPF_BIND_SUCCEEDED) {
+		close(fd);
+		if (err == BPF_BIND_BUFFER_TOO_BIG) {
 			/*
-			 * There's no such device.
+			 * We didn't specify a buffer size, so
+			 * this *really* shouldn't fail because
+			 * there's no buffer space.  Fail.
 			 */
-			close(fd);
-			return (PCAP_ERROR_NO_SUCH_DEVICE);
-
-		case ENETDOWN:
-			/*
-			 * Return a "network down" indication, so that
-			 * the application can report that rather than
-			 * saying we had a mysterious failure and
-			 * suggest that they report a problem to the
-			 * libpcap developers.
-			 */
-			close(fd);
-			return (PCAP_ERROR_IFACE_NOT_UP);
-
-		default:
-			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "BIOCSETIF: %s", p->opt.device);
-			close(fd);
 			return (PCAP_ERROR);
 		}
+		return (err);
 	}
 
 	/*
@@ -880,7 +995,11 @@
 	close(fd);
 #endif /* BIOCGDLTLIST */
 	return (0);
+}
 #elif defined(HAVE_BSD_IEEE80211)
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
 	int ret;
 
 	ret = monitor_mode(p, 0);
@@ -889,10 +1008,14 @@
 	if (ret == 0)
 		return (1);	/* success */
 	return (ret);
-#else
-	return (0);
-#endif
 }
+#else
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p _U_)
+{
+	return (0);
+}
+#endif
 
 static int
 pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
@@ -974,7 +1097,7 @@
 		} else
 #endif
 		{
-			cc = read(p->fd, p->buffer, p->bufsize);
+			cc = (int)read(p->fd, p->buffer, p->bufsize);
 		}
 		if (cc < 0) {
 			/* Don't choke when we get ptraced */
@@ -1012,18 +1135,21 @@
 			case EWOULDBLOCK:
 				return (0);
 
-			case ENXIO:
+			case ENXIO:	/* FreeBSD, DragonFly BSD, and Darwin */
+			case EIO:	/* OpenBSD */
+					/* NetBSD appears not to return an error in this case */
 				/*
 				 * The device on which we're capturing
 				 * went away.
 				 *
 				 * XXX - we should really return
-				 * PCAP_ERROR_IFACE_NOT_UP, but
-				 * pcap_dispatch() etc. aren't
-				 * defined to retur that.
+				 * an appropriate error for that,
+				 * but pcap_dispatch() etc. aren't
+				 * documented as having error returns
+				 * other than PCAP_ERROR or PCAP_ERROR_BREAK.
 				 */
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "The interface went down");
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "The interface disappeared");
 				return (PCAP_ERROR);
 
 #if defined(sun) && !defined(BSD) && !defined(__svr4__) && !defined(__SVR4)
@@ -1076,7 +1202,7 @@
 		 */
 		if (p->break_loop) {
 			p->bp = bp;
-			p->cc = ep - bp;
+			p->cc = (int)(ep - bp);
 			/*
 			 * ep is set based on the return value of read(),
 			 * but read() from a BPF device doesn't necessarily
@@ -1116,7 +1242,7 @@
 #endif
 		 */
 		if (pb->filtering_in_kernel ||
-		    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+		    pcap_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
 			struct pcap_pkthdr pkthdr;
 #ifdef BIOCSTSTAMP
 			struct bintime bt;
@@ -1166,7 +1292,7 @@
 			bp += BPF_WORDALIGN(caplen + hdrlen);
 			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
 				p->bp = bp;
-				p->cc = ep - bp;
+				p->cc = (int)(ep - bp);
 				/*
 				 * See comment above about p->cc < 0.
 				 */
@@ -1187,11 +1313,11 @@
 }
 
 static int
-pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
+pcap_inject_bpf(pcap_t *p, const void *buf, int size)
 {
 	int ret;
 
-	ret = write(p->fd, buf, size);
+	ret = (int)write(p->fd, buf, size);
 #ifdef __APPLE__
 	if (ret == -1 && errno == EAFNOSUPPORT) {
 		/*
@@ -1223,7 +1349,7 @@
 		/*
 		 * Now try the write again.
 		 */
-		ret = write(p->fd, buf, size);
+		ret = (int)write(p->fd, buf, size);
 	}
 #endif /* __APPLE__ */
 	if (ret == -1) {
@@ -1243,7 +1369,7 @@
 	if (odm_initialize() == -1) {
 		if (odm_err_msg(odmerrno, &errstr) == -1)
 			errstr = "Unknown error";
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: odm_initialize failed: %s",
 		    errstr);
 		return (PCAP_ERROR);
@@ -1252,7 +1378,7 @@
 	if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
 		if (odm_err_msg(odmerrno, &errstr) == -1)
 			errstr = "Unknown error";
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
 		    errstr);
 		(void)odm_terminate();
@@ -1271,7 +1397,7 @@
 		if (errbuf != NULL) {
 			if (odm_err_msg(odmerrno, &errstr) == -1)
 				errstr = "Unknown error";
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: odm_unlock failed: %s",
 			    errstr);
 		}
@@ -1282,7 +1408,7 @@
 		if (errbuf != NULL) {
 			if (odm_err_msg(odmerrno, &errstr) == -1)
 				errstr = "Unknown error";
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: odm_terminate failed: %s",
 			    errstr);
 		}
@@ -1345,7 +1471,7 @@
 
 	if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
 		for (i = 0; i < BPF_MINORS; i++) {
-			pcap_snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i);
+			snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i);
 			unlink(buf);
 			if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
 				pcap_fmt_errmsg_for_errno(errbuf,
@@ -1358,8 +1484,8 @@
 
 	/* Check if the driver is loaded */
 	memset(&cfg_ld, 0x0, sizeof(cfg_ld));
+	snprintf(buf, sizeof(buf), "%s/%s", DRIVER_PATH, BPF_NAME);
 	cfg_ld.path = buf;
-	pcap_snprintf(cfg_ld.path, sizeof(cfg_ld.path), "%s/%s", DRIVER_PATH, BPF_NAME);
 	if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) ||
 	    (cfg_ld.kmid == 0)) {
 		/* Driver isn't loaded, load it now */
@@ -1426,7 +1552,7 @@
 				    strerror(errno));
 			} else {
 				memset(&req, 0, sizeof(req));
-				strncpy(req.ifm_name, pb->device,
+				pcap_strlcpy(req.ifm_name, pb->device,
 				    sizeof(req.ifm_name));
 				if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
 					fprintf(stderr,
@@ -1440,7 +1566,7 @@
 						 * turn it off.
 						 */
 						memset(&ifr, 0, sizeof(ifr));
-						(void)strncpy(ifr.ifr_name,
+						(void)pcap_strlcpy(ifr.ifr_name,
 						    pb->device,
 						    sizeof(ifr.ifr_name));
 						ifr.ifr_media =
@@ -1469,7 +1595,7 @@
 
 				s = socket(AF_LOCAL, SOCK_DGRAM, 0);
 				if (s >= 0) {
-					strlcpy(ifr.ifr_name, pb->device,
+					pcap_strlcpy(ifr.ifr_name, pb->device,
 					    sizeof(ifr.ifr_name));
 					ioctl(s, SIOCIFDESTROY, &ifr);
 					close(s);
@@ -1508,20 +1634,17 @@
 	pcap_cleanup_live_common(p);
 }
 
+#ifdef __APPLE__
 static int
 check_setif_failure(pcap_t *p, int error)
 {
-#ifdef __APPLE__
 	int fd;
-	struct ifreq ifr;
 	int err;
-#endif
 
-	if (error == ENXIO) {
+	if (error == PCAP_ERROR_NO_SUCH_DEVICE) {
 		/*
 		 * No such device exists.
 		 */
-#ifdef __APPLE__
 		if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
 			/*
 			 * Monitor mode was requested, and we're trying
@@ -1532,33 +1655,38 @@
 			 */
 			fd = socket(AF_INET, SOCK_DGRAM, 0);
 			if (fd != -1) {
-				strlcpy(ifr.ifr_name, "en",
-				    sizeof(ifr.ifr_name));
-				strlcat(ifr.ifr_name, p->opt.device + 3,
-				    sizeof(ifr.ifr_name));
-				if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+				char *en_name;
+
+				if (pcap_asprintf(&en_name, "en%s",
+				    p->opt.device + 3) == -1) {
 					/*
-					 * We assume this failed because
-					 * the underlying device doesn't
-					 * exist.
+					 * We can't find out whether there's
+					 * an underlying "enN" device, so
+					 * just report "no such device".
 					 */
-					err = PCAP_ERROR_NO_SUCH_DEVICE;
 					pcap_fmt_errmsg_for_errno(p->errbuf,
 					    PCAP_ERRBUF_SIZE, errno,
-					    "SIOCGIFFLAGS on %s failed",
-					    ifr.ifr_name);
-				} else {
-					/*
-					 * The underlying "enN" device
-					 * exists, but there's no
-					 * corresponding "wltN" device;
-					 * that means that the "enN"
-					 * device doesn't support
-					 * monitor mode, probably because
-					 * it's an Ethernet device rather
-					 * than a wireless device.
-					 */
-					err = PCAP_ERROR_RFMON_NOTSUP;
+					    "malloc");
+					close(fd);
+					return (PCAP_ERROR_NO_SUCH_DEVICE);
+				}
+				err = device_exists(fd, en_name, p->errbuf);
+				free(en_name);
+				if (err != 0) {
+					if (err == PCAP_ERROR_NO_SUCH_DEVICE) {
+						/*
+						 * The underlying "enN" device
+						 * exists, but there's no
+						 * corresponding "wltN" device;
+						 * that means that the "enN"
+						 * device doesn't support
+						 * monitor mode, probably
+						 * because it's an Ethernet
+						 * device rather than a
+						 * wireless device.
+						 */
+						err = PCAP_ERROR_RFMON_NOTSUP;
+					}
 				}
 				close(fd);
 			} else {
@@ -1574,32 +1702,30 @@
 			}
 			return (err);
 		}
-#endif
+
 		/*
 		 * No such device.
 		 */
-		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "BIOCSETIF failed");
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
-	} else if (errno == 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.
-		 */
-		return (PCAP_ERROR_IFACE_NOT_UP);
-	} else {
-		/*
-		 * Some other error; fill in the error string, and
-		 * return PCAP_ERROR.
-		 */
-		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "BIOCSETIF: %s", p->opt.device);
-		return (PCAP_ERROR);
 	}
+
+	/*
+	 * Just return the error status; it's what we want, and, if it's
+	 * PCAP_ERROR, the error string has been filled in.
+	 */
+	return (error);
 }
+#else
+static int
+check_setif_failure(pcap_t *p _U_, int error)
+{
+	/*
+	 * Just return the error status; it's what we want, and, if it's
+	 * PCAP_ERROR, the error string has been filled in.
+	 */
+	return (error);
+}
+#endif
 
 /*
  * Default capture buffer size.
@@ -1625,15 +1751,9 @@
 	int retv;
 #endif
 	int fd;
-#ifdef LIFNAMSIZ
-	char *zonesep;
+#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
 	struct lifreq ifr;
-	char *ifrname = ifr.lifr_name;
-	const size_t ifnamsiz = sizeof(ifr.lifr_name);
-#else
-	struct ifreq ifr;
-	char *ifrname = ifr.ifr_name;
-	const size_t ifnamsiz = sizeof(ifr.ifr_name);
+	char *zonesep;
 #endif
 	struct bpf_version bv;
 #ifdef __APPLE__
@@ -1675,7 +1795,7 @@
 	}
 	if (bv.bv_major != BPF_MAJOR_VERSION ||
 	    bv.bv_minor < BPF_MINOR_VERSION) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "kernel bpf filter out of date");
 		status = PCAP_ERROR;
 		goto bad;
@@ -1715,13 +1835,13 @@
 		char *lnamep;
 
 		if (ifr.lifr_zoneid != GLOBAL_ZONEID) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "zonename/linkname only valid in global zone.");
 			status = PCAP_ERROR;
 			goto bad;
 		}
 		znamelen = zonesep - p->opt.device;
-		(void) strlcpy(path_zname, p->opt.device, znamelen + 1);
+		(void) pcap_strlcpy(path_zname, p->opt.device, znamelen + 1);
 		ifr.lifr_zoneid = getzoneidbyname(path_zname);
 		if (ifr.lifr_zoneid == -1) {
 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
@@ -1786,24 +1906,19 @@
 					 */
 					sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 					if (sockfd != -1) {
-						strlcpy(ifrname,
-						    p->opt.device, ifnamsiz);
-						if (ioctl(sockfd, SIOCGIFFLAGS,
-						    (char *)&ifr) < 0) {
+						status = device_exists(sockfd,
+						    p->opt.device, p->errbuf);
+						if (status == 0) {
 							/*
-							 * We assume this
-							 * failed because
-							 * the underlying
-							 * device doesn't
-							 * exist.
+							 * The device exists,
+							 * but it's not an
+							 * enN device; that
+							 * means it doesn't
+							 * support monitor
+							 * mode.
 							 */
-							status = PCAP_ERROR_NO_SUCH_DEVICE;
-							pcap_fmt_errmsg_for_errno(p->errbuf,
-							    PCAP_ERRBUF_SIZE,
-							    errno,
-							    "SIOCGIFFLAGS failed");
-						} else
 							status = PCAP_ERROR_RFMON_NOTSUP;
+						}
 						close(sockfd);
 					} else {
 						/*
@@ -1855,6 +1970,7 @@
 			 * it when the pcap_t is closed.
 			 */
 			int s;
+			struct ifreq ifr;
 
 			/*
 			 * Open a socket to use for ioctls to
@@ -1878,7 +1994,7 @@
 				 * "atexit()" failed; don't create the
 				 * interface, just give up.
 				 */
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				     "atexit failed");
 				close(s);
 				status = PCAP_ERROR;
@@ -1888,10 +2004,10 @@
 			/*
 			 * Create the interface.
 			 */
-			strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+			pcap_strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
 			if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
 				if (errno == EINVAL) {
-					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 					    "Invalid USB bus interface %s",
 					    p->opt.device);
 				} else {
@@ -1983,11 +2099,19 @@
 			status = PCAP_ERROR;
 			goto bad;
 		}
-		(void)strncpy(ifrname, p->opt.device, ifnamsiz);
-		if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
-			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "BIOCSETIF: %s", p->opt.device);
-			status = PCAP_ERROR;
+		status = bpf_bind(fd, p->opt.device, ifnamsiz, p->errbuf);
+		if (status != BPF_BIND_SUCCEEDED) {
+			if (status == BPF_BIND_BUFFER_TOO_BIG) {
+				/*
+				 * The requested buffer size
+				 * is too big.  Fail.
+				 *
+				 * XXX - should we do the "keep cutting
+				 * the buffer size in half" loop here if
+				 * we're using the default buffer size?
+				 */
+				status = PCAP_ERROR;
+			}
 			goto bad;
 		}
 		v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
@@ -2014,14 +2138,23 @@
 			/*
 			 * Now bind to the device.
 			 */
-			(void)strncpy(ifrname, p->opt.device, ifnamsiz);
-#ifdef BIOCSETLIF
-			if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
-#else
-			if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0)
-#endif
-			{
-				status = check_setif_failure(p, errno);
+			status = bpf_bind(fd, p->opt.device, p->errbuf);
+			if (status != BPF_BIND_SUCCEEDED) {
+				if (status == BPF_BIND_BUFFER_TOO_BIG) {
+					/*
+					 * The requested buffer size
+					 * is too big.  Fail.
+					 */
+					status = PCAP_ERROR;
+					goto bad;
+				}
+
+				/*
+				 * Special checks on macOS to deal with
+				 * the way monitor mode was done on
+				 * 10.4 Tiger.
+				 */
+				status = check_setif_failure(p, status);
 				goto bad;
 			}
 		} else {
@@ -2047,22 +2180,30 @@
 				 */
 				(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
 
-				(void)strncpy(ifrname, p->opt.device, ifnamsiz);
-#ifdef BIOCSETLIF
-				if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
-#else
-				if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
-#endif
+				status = bpf_bind(fd, p->opt.device, p->errbuf);
+				if (status == BPF_BIND_SUCCEEDED)
 					break;	/* that size worked; we're done */
 
-				if (errno != ENOBUFS) {
-					status = check_setif_failure(p, errno);
+				/*
+				 * If the attempt failed because the
+				 * buffer was too big, cut the buffer
+				 * size in half and try again.
+				 *
+				 * Otherwise, fail.
+				 */
+				if (errno != BPF_BIND_BUFFER_TOO_BIG) {
+					/*
+					 * Special checks on macOS to deal
+					 * with the way monitor mode was
+					 * done on 10.4 Tiger.
+					 */
+					status = check_setif_failure(p, status);
 					goto bad;
 				}
 			}
 
 			if (v == 0) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "BIOCSBLEN: %s: No buffer size worked",
 				    p->opt.device);
 				status = PCAP_ERROR;
@@ -2106,7 +2247,7 @@
 		/*
 		 * We don't know what to map this to yet.
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
 		    v);
 		status = PCAP_ERROR;
 		goto bad;
@@ -2166,9 +2307,9 @@
 	 * we try to select DLT_IEEE802_11.
 	 */
 	if (have_osinfo) {
-		if (isdigit((unsigned)osinfo.release[0]) &&
+		if (PCAP_ISDIGIT((unsigned)osinfo.release[0]) &&
 		     (osinfo.release[0] == '9' ||
-		     isdigit((unsigned)osinfo.release[1]))) {
+		     PCAP_ISDIGIT((unsigned)osinfo.release[1]))) {
 			/*
 			 * 10.5 (Darwin 9.x), or later.
 			 */
@@ -2187,7 +2328,7 @@
 					 * of link-layer types, as selecting
 					 * it will keep monitor mode off.
 					 */
-					remove_en(p);
+					remove_non_802_11(p);
 
 					/*
 					 * If the new mode we want isn't
@@ -2418,7 +2559,7 @@
 		/*
 		 * We don't support immediate mode.  Fail.
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
 		status = PCAP_ERROR;
 		goto bad;
 	}
@@ -2745,15 +2886,40 @@
 		return (-1);
 	}
 	memset(&req, 0, sizeof(req));
-	strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+	pcap_strlcpy(req.ifm_name, name, sizeof(req.ifm_name));
 	if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
 		if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY ||
-		    errno == ENODEV) {
+		    errno == ENODEV || errno == EPERM
+#ifdef EPWROFF
+		    || errno == EPWROFF
+#endif
+		    ) {
 			/*
 			 * Not supported, so we can't provide any
 			 * additional information.  Assume that
 			 * this means that "connected" vs.
 			 * "disconnected" doesn't apply.
+			 *
+			 * The ioctl routine for Apple's pktap devices,
+			 * annoyingly, checks for "are you root?" before
+			 * checking whether the ioctl is valid, so it
+			 * returns EPERM, rather than ENOTSUP, for the
+			 * invalid SIOCGIFMEDIA, unless you're root.
+			 * So, just as we do for some ethtool ioctls
+			 * on Linux, which makes the same mistake, we
+			 * also treat EPERM as meaning "not supported".
+			 *
+			 * And it appears that Apple's llw0 device, which
+			 * appears to be part of the Skywalk subsystem:
+			 *
+			 *    http://newosxbook.com/bonus/vol1ch16.html
+			 *
+			 * can sometimes return EPWROFF ("Device power
+			 * is off") for that ioctl, so we treat *that*
+			 * as another indication that we can't get a
+			 * connection status.  (If it *isn't* "powered
+			 * off", it's reported as a wireless device,
+			 * complete with an active/inactive state.)
 			 */
 			*flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
 			close(sock);
@@ -2863,7 +3029,7 @@
 	}
 
 	memset(&req, 0, sizeof req);
-	strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
+	pcap_strlcpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
 
 	/*
 	 * Find out how many media types we have.
@@ -2890,7 +3056,7 @@
 
 		default:
 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "SIOCGIFMEDIA 1");
+			    errno, "SIOCGIFMEDIA");
 			close(sock);
 			return (PCAP_ERROR);
 		}
@@ -2973,7 +3139,7 @@
 				return (PCAP_ERROR);
 			}
 			memset(&ifr, 0, sizeof(ifr));
-			(void)strncpy(ifr.ifr_name, p->opt.device,
+			(void)pcap_strlcpy(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) {
@@ -3032,8 +3198,12 @@
 				new_dlt = bdlp->bfl_list[i];
 			break;
 
+#ifdef DLT_PRISM_HEADER
 		case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
 		case DLT_AIRONET_HEADER:
+#endif
 		case DLT_IEEE802_11_RADIO_AVS:
 			/*
 			 * 802.11 with radio, but not radiotap.
@@ -3068,24 +3238,25 @@
 
 #if defined(__APPLE__) && defined(BIOCGDLTLIST)
 /*
- * Remove DLT_EN10MB from the list of DLT_ values, as we're in monitor mode,
- * and DLT_EN10MB isn't supported in monitor mode.
+ * Remove non-802.11 header types from the list of DLT_ values, as we're in
+ * monitor mode, and those header types aren't supported in monitor mode.
  */
 static void
-remove_en(pcap_t *p)
+remove_non_802_11(pcap_t *p)
 {
 	int i, j;
 
 	/*
-	 * Scan the list of DLT_ values and discard DLT_EN10MB.
+	 * Scan the list of DLT_ values and discard non-802.11 ones.
 	 */
 	j = 0;
 	for (i = 0; i < p->dlt_count; i++) {
 		switch (p->dlt_list[i]) {
 
 		case DLT_EN10MB:
+		case DLT_RAW:
 			/*
-			 * Don't offer this one.
+			 * Not 802.11.  Don't offer this one.
 			 */
 			continue;
 
@@ -3127,10 +3298,17 @@
 		switch (p->dlt_list[i]) {
 
 		case DLT_IEEE802_11:
+#ifdef DLT_PRISM_HEADER
 		case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
 		case DLT_AIRONET_HEADER:
+#endif
 		case DLT_IEEE802_11_RADIO:
 		case DLT_IEEE802_11_RADIO_AVS:
+#ifdef DLT_PPI
+		case DLT_PPI:
+#endif
 			/*
 			 * 802.11.  Don't offer this one.
 			 */
@@ -3222,61 +3400,188 @@
  * Set direction flag: Which packets do we accept on a forwarding
  * single device? IN, OUT or both?
  */
+#if defined(BIOCSDIRECTION)
 static int
 pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
 {
-#if defined(BIOCSDIRECTION)
 	u_int direction;
-
-	direction = (d == PCAP_D_IN) ? BPF_D_IN :
-	    ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
-	if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
-		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
-		    errno, "Cannot set direction to %s",
-		        (d == PCAP_D_IN) ? "PCAP_D_IN" :
-			((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"));
-		return (-1);
-	}
-	return (0);
-#elif defined(BIOCSSEESENT)
-	u_int seesent;
+	const char *direction_name;
 
 	/*
-	 * We don't support PCAP_D_OUT.
+	 * FreeBSD and NetBSD.
 	 */
-	if (d == PCAP_D_OUT) {
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
-		    "Setting direction to PCAP_D_OUT is not supported on BPF");
-		return -1;
+	switch (d) {
+
+	case PCAP_D_IN:
+		/*
+		 * Incoming, but not outgoing, so accept only
+		 * incoming packets.
+		 */
+		direction = BPF_D_IN;
+		direction_name = "\"incoming only\"";
+		break;
+
+	case PCAP_D_OUT:
+		/*
+		 * Outgoing, but not incoming, so accept only
+		 * outgoing packets.
+		 */
+		direction = BPF_D_OUT;
+		direction_name = "\"outgoing only\"";
+		break;
+
+	default:
+		/*
+		 * Incoming and outgoing, so accept both
+		 * incoming and outgoing packets.
+		 *
+		 * It's guaranteed, at this point, that d is a valid
+		 * direction value, so we know that this is PCAP_D_INOUT
+		 * if it's not PCAP_D_IN or PCAP_D_OUT.
+		 */
+		direction = BPF_D_INOUT;
+		direction_name = "\"incoming and outgoing\"";
+		break;
 	}
 
-	seesent = (d == PCAP_D_INOUT);
-	if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
+	if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
-		    errno, "Cannot set direction to %s",
-		    (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN");
+		    errno, "Cannot set direction to %s", direction_name);
 		return (-1);
 	}
 	return (0);
-#else
-	(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
-	    "This system doesn't support BIOCSSEESENT, so the direction can't be set");
-	return (-1);
-#endif
 }
+#elif defined(BIOCSDIRFILT)
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
+	u_int dirfilt;
+	const char *direction_name;
 
+	/*
+	 * OpenBSD; same functionality, different names, different
+	 * semantics (the flags mean "*don't* capture packets in
+	 * that direction", not "*capture only* packets in that
+	 * direction").
+	 */
+	switch (d) {
+
+	case PCAP_D_IN:
+		/*
+		 * Incoming, but not outgoing, so filter out
+		 * outgoing packets.
+		 */
+		dirfilt = BPF_DIRECTION_OUT;
+		direction_name = "\"incoming only\"";
+		break;
+
+	case PCAP_D_OUT:
+		/*
+		 * Outgoing, but not incoming, so filter out
+		 * incoming packets.
+		 */
+		dirfilt = BPF_DIRECTION_IN;
+		direction_name = "\"outgoing only\"";
+		break;
+
+	default:
+		/*
+		 * Incoming and outgoing, so don't filter out
+		 * any packets based on direction.
+		 *
+		 * It's guaranteed, at this point, that d is a valid
+		 * direction value, so we know that this is PCAP_D_INOUT
+		 * if it's not PCAP_D_IN or PCAP_D_OUT.
+		 */
+		dirfilt = 0;
+		direction_name = "\"incoming and outgoing\"";
+		break;
+	}
+	if (ioctl(p->fd, BIOCSDIRFILT, &dirfilt) == -1) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+		    errno, "Cannot set direction to %s", direction_name);
+		return (-1);
+	}
+	return (0);
+}
+#elif defined(BIOCSSEESENT)
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
+	u_int seesent;
+	const char *direction_name;
+
+	/*
+	 * OS with just BIOCSSEESENT.
+	 */
+	switch (d) {
+
+	case PCAP_D_IN:
+		/*
+		 * Incoming, but not outgoing, so we don't want to
+		 * see transmitted packets.
+		 */
+		seesent = 0;
+		direction_name = "\"incoming only\"";
+		break;
+
+	case PCAP_D_OUT:
+		/*
+		 * Outgoing, but not incoming; we can't specify that.
+		 */
+		snprintf(p->errbuf, sizeof(p->errbuf),
+		    "Setting direction to \"outgoing only\" is not supported on this device");
+		return (-1);
+
+	default:
+		/*
+		 * Incoming and outgoing, so we want to see transmitted
+		 * packets.
+		 *
+		 * It's guaranteed, at this point, that d is a valid
+		 * direction value, so we know that this is PCAP_D_INOUT
+		 * if it's not PCAP_D_IN or PCAP_D_OUT.
+		 */
+		seesent = 1;
+		direction_name = "\"incoming and outgoing\"";
+		break;
+	}
+
+	if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+		    errno, "Cannot set direction to %s", direction_name);
+		return (-1);
+	}
+	return (0);
+}
+#else
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d _U_)
+{
+	(void) snprintf(p->errbuf, sizeof(p->errbuf),
+	    "Setting direction is not supported on this device");
+	return (-1);
+}
+#endif
+
+#ifdef BIOCSDLT
 static int
 pcap_set_datalink_bpf(pcap_t *p, int dlt)
 {
-#ifdef BIOCSDLT
 	if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
 		    errno, "Cannot set DLT %d", dlt);
 		return (-1);
 	}
-#endif
 	return (0);
 }
+#else
+static int
+pcap_set_datalink_bpf(pcap_t *p _U_, int dlt _U_)
+{
+	return (0);
+}
+#endif
 
 /*
  * Platform-specific information.
diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c
index 07ed1c7..2969ff8 100644
--- a/pcap-bt-linux.c
+++ b/pcap-bt-linux.c
@@ -58,7 +58,7 @@
 /* forward declaration */
 static int bt_activate(pcap_t *);
 static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *);
-static int bt_inject_linux(pcap_t *, const void *, size_t);
+static int bt_inject_linux(pcap_t *, const void *, int);
 static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
 static int bt_stats_linux(pcap_t *, struct pcap_stat *);
 
@@ -74,13 +74,14 @@
 {
 	struct hci_dev_list_req *dev_list;
 	struct hci_dev_req *dev_req;
-	int i, sock;
+	int sock;
+	unsigned i;
 	int ret = 0;
 
 	sock  = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
 	if (sock < 0)
 	{
-		/* if bluetooth is not supported this this is not fatal*/
+		/* if bluetooth is not supported this is not fatal*/
 		if (errno == EAFNOSUPPORT)
 			return 0;
 		pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
@@ -91,7 +92,7 @@
 	dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
 	if (!dev_list)
 	{
-		pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+		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;
@@ -109,10 +110,10 @@
 
 	dev_req = dev_list->dev_req;
 	for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
-		char dev_name[20], dev_descr[30];
+		char dev_name[20], dev_descr[40];
 
-		pcap_snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
-		pcap_snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
+		snprintf(dev_name, sizeof(dev_name), BT_IFACE"%u", dev_req->dev_id);
+		snprintf(dev_descr, sizeof(dev_descr), "Bluetooth adapter number %u", i);
 
 		/*
 		 * Bluetooth is a wireless technology.
@@ -172,7 +173,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_bt));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_bt);
 	if (p == NULL)
 		return (NULL);
 
@@ -193,7 +194,7 @@
 	/* get bt interface id */
 	if (sscanf(handle->opt.device, BT_IFACE"%d", &dev_id) != 1)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't get Bluetooth device index from %s",
 			 handle->opt.device);
 		return PCAP_ERROR;
@@ -345,7 +346,7 @@
 		return -1;
 	}
 
-	pkth.caplen = ret;
+	pkth.caplen = (bpf_u_int32)ret;
 
 	/* get direction and timestamp*/
 	cmsg = CMSG_FIRSTHDR(&msg);
@@ -361,15 +362,27 @@
 		}
 		cmsg = CMSG_NXTHDR(&msg, cmsg);
 	}
-	if ((in && (handle->direction == PCAP_D_OUT)) ||
-				((!in) && (handle->direction == PCAP_D_IN)))
-		return 0;
+	switch (handle->direction) {
+
+	case PCAP_D_IN:
+		if (!in)
+			return 0;
+		break;
+
+	case PCAP_D_OUT:
+		if (in)
+			return 0;
+		break;
+
+	default:
+		break;
+	}
 
 	bthdr->direction = htonl(in != 0);
 	pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
 	pkth.len = pkth.caplen;
 	if (handle->fcode.bf_insns == NULL ||
-	    bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+	    pcap_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
 		callback(user, &pkth, pktd);
 		return 1;
 	}
@@ -377,10 +390,10 @@
 }
 
 static int
-bt_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+bt_inject_linux(pcap_t *handle, const void *buf _U_, int size _U_)
 {
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
-    		"bluetooth devices");
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packet injection is not supported on Bluetooth devices");
 	return (-1);
 }
 
@@ -417,6 +430,10 @@
 static int
 bt_setdirection_linux(pcap_t *p, pcap_direction_t d)
 {
+	/*
+	 * It's guaranteed, at this point, that d is a valid
+	 * direction value.
+	 */
 	p->direction = d;
 	return 0;
 }
diff --git a/pcap-bt-monitor-linux.c b/pcap-bt-monitor-linux.c
index c222c10..ad4fc37 100644
--- a/pcap-bt-monitor-linux.c
+++ b/pcap-bt-monitor-linux.c
@@ -50,6 +50,14 @@
 #define INTERFACE_NAME "bluetooth-monitor"
 
 /*
+ * Private data.
+ * Currently contains nothing.
+ */
+struct pcap_bt_monitor {
+	int	dummy;
+};
+
+/*
  * 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.
  */
@@ -124,7 +132,7 @@
         return -1;
     }
 
-    pkth.caplen = ret - sizeof(hdr) + sizeof(pcap_bluetooth_linux_monitor_header);
+    pkth.caplen = (bpf_u_int32)(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)) {
@@ -139,7 +147,7 @@
     bthdr->opcode = htons(hdr.opcode);
 
     if (handle->fcode.bf_insns == NULL ||
-        bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+        pcap_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
         callback(user, &pkth, pktd);
         return 1;
     }
@@ -147,20 +155,14 @@
 }
 
 static int
-bt_monitor_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
+bt_monitor_inject(pcap_t *handle, const void *buf _U_, int size _U_)
 {
-    pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported yet");
+    snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+        "Packet injection is not supported yet on Bluetooth monitor devices");
     return -1;
 }
 
 static int
-bt_monitor_setdirection(pcap_t *p, pcap_direction_t d)
-{
-    p->direction = d;
-    return 0;
-}
-
-static int
 bt_monitor_stats(pcap_t *handle _U_, struct pcap_stat *stats)
 {
     stats->ps_recv = 0;
@@ -199,7 +201,7 @@
     handle->read_op = bt_monitor_read;
     handle->inject_op = bt_monitor_inject;
     handle->setfilter_op = install_bpf_program; /* no kernel filtering */
-    handle->setdirection_op = bt_monitor_setdirection;
+    handle->setdirection_op = NULL; /* Not implemented */
     handle->set_datalink_op = NULL; /* can't change data link type */
     handle->getnonblock_op = pcap_getnonblock_fd;
     handle->setnonblock_op = pcap_setnonblock_fd;
@@ -262,7 +264,7 @@
     }
 
     *is_ours = 1;
-    p = pcap_create_common(ebuf, 0);
+    p = PCAP_CREATE_COMMON(ebuf, struct pcap_bt_monitor);
     if (p == NULL)
         return NULL;
 
diff --git a/pcap-common.c b/pcap-common.c
index b379d8f..51d0666 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -326,7 +326,7 @@
  * 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 first byte of the PPP header (0xff03) is modified to accommodate
  * the direction - 0x00 = IN, 0x01 = OUT.
  */
 #define LINKTYPE_PPP_PPPD	166
@@ -361,7 +361,7 @@
 /*
  * 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
+ * https://www.endace.com/support/EndaceRecordFormat.pdf) in front of
  * the link-layer header.
  */
 #define LINKTYPE_ERF_ETH	175	/* Ethernet */
@@ -495,7 +495,7 @@
 
 /*
  * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ * (https://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
  */
 #define LINKTYPE_SITA		196
 
@@ -514,11 +514,20 @@
 #define LINKTYPE_RAIF1		198
 
 /*
- * IPMB packet for IPMI, beginning with the I2C slave address, followed
- * by the netFn and LUN, etc..  Requested by Chanthy Toeung
- * <chanthy.toeung@ca.kontron.com>.
+ * IPMB packet for IPMI, beginning with a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - its DLT_ value used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header.  We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value.  If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
  */
-#define LINKTYPE_IPMB		199
+#define LINKTYPE_IPMB_KONTRON	199
 
 /*
  * Juniper-private data link type, as per request from
@@ -550,14 +559,33 @@
 #define LINKTYPE_LAPD		203
 
 /*
- * Variants of various link-layer headers, with a one-byte direction
- * pseudo-header prepended - zero means "received by this host",
- * non-zero (any non-zero value) means "sent by this host" - as per
- * Will Barker <w.barker@zen.co.uk>.
+ * PPP, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host", non-zero (any non-zero value) means "sent by
+ * this host" - as per Will Barker <w.barker@zen.co.uk>.
  */
-#define LINKTYPE_PPP_WITH_DIR	204	/* PPP */
+#define LINKTYPE_PPP_WITH_DIR	204	/* Don't confuse with LINKTYPE_PPP_PPPD */
+
+/*
+ * Cisco HDLC, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host", non-zero (any non-zero value) means
+ * "sent by this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
 #define LINKTYPE_C_HDLC_WITH_DIR 205	/* Cisco HDLC */
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
 #define LINKTYPE_FRELAY_WITH_DIR 206	/* Frame Relay */
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
 #define LINKTYPE_LAPB_WITH_DIR	207	/* LAPB */
 
 /*
@@ -579,7 +607,7 @@
 
 /*
  * Media Oriented Systems Transport (MOST) bus for multimedia
- * transport - http://www.mostcooperation.com/ - as requested
+ * transport - https://www.mostcooperation.com/ - as requested
  * by Hannes Kaelber <hannes.kaelber@x2e.de>.
  */
 #define LINKTYPE_MOST		211
@@ -765,16 +793,16 @@
 /*
  * Raw D-Bus:
  *
- *	http://www.freedesktop.org/wiki/Software/dbus
+ *	https://www.freedesktop.org/wiki/Software/dbus
  *
  * messages:
  *
- *	http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *	https://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
+ *	https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
  *
  * Requested by Martin Vidner <martin@vidner.net>.
  */
@@ -792,7 +820,7 @@
  * DVB-CI (DVB Common Interface for communication between a PC Card
  * module and a DVB receiver).  See
  *
- *	http://www.kaiser.cx/pcap-dvbci.html
+ *	https://www.kaiser.cx/pcap-dvbci.html
  *
  * for the specification.
  *
@@ -916,7 +944,7 @@
  *
  * Requested by Chris Bontje <chris_bontje@selinc.com>.
  */
-#define DLT_RTAC_SERIAL		250
+#define LINKTYPE_RTAC_SERIAL		250
 
 /*
  * Bluetooth Low Energy air interface link-layer packets.
@@ -1050,9 +1078,9 @@
 
 /*
  * per: Stefanha at gmail.com for
- *   http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ *   https://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
  * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
- * for: http://qemu-project.org/Features/VirtioVsock
+ * for: https://qemu-project.org/Features/VirtioVsock
  */
 #define LINKTYPE_VSOCK          271
 
@@ -1064,7 +1092,7 @@
 /*
  * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
  *   per: bruno.verstuyft at excentis.com
- *        http://www.xra31.com/xra-header
+ *        https://www.xra31.com/xra-header
  */
 #define LINKTYPE_DOCSIS31_XRA31	273
 
@@ -1076,12 +1104,94 @@
 
 /*
  * DisplayPort AUX channel monitoring data as specified by VESA
- * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ * DisplayPort(DP) Standard preceded by a pseudo-header.
  *    per dirk.eibach at gdsys.cc
  */
 #define LINKTYPE_DISPLAYPORT_AUX	275
 
-#define LINKTYPE_MATCHING_MAX	275		/* highest value in the "matching" range */
+/*
+ * Linux cooked sockets v2.
+ */
+#define LINKTYPE_LINUX_SLL2	276
+
+/*
+ * Sercos Monitor, per Manuel Jacob <manuel.jacob at steinbeis-stg.de>
+ */
+#define LINKTYPE_SERCOS_MONITOR 277
+
+/*
+ * OpenVizsla http://openvizsla.org is open source USB analyzer hardware.
+ * It consists of FPGA with attached USB phy and FTDI chip for streaming
+ * the data to the host PC.
+ *
+ * Current OpenVizsla data encapsulation format is described here:
+ * https://github.com/matwey/libopenvizsla/wiki/OpenVizsla-protocol-description
+ *
+ */
+#define LINKTYPE_OPENVIZSLA     278
+
+/*
+ * The Elektrobit High Speed Capture and Replay (EBHSCR) protocol is produced
+ * by a PCIe Card for interfacing high speed automotive interfaces.
+ *
+ * The specification for this frame format can be found at:
+ *   https://www.elektrobit.com/ebhscr
+ *
+ * for Guenter.Ebermann at elektrobit.com
+ *
+ */
+#define LINKTYPE_EBHSCR	        279
+
+/*
+ * The https://fd.io vpp graph dispatch tracer produces pcap trace files
+ * in the format documented here:
+ * https://fdio-vpp.readthedocs.io/en/latest/gettingstarted/developers/vnet.html#graph-dispatcher-pcap-tracing
+ */
+#define LINKTYPE_VPP_DISPATCH	280
+
+/*
+ * Broadcom Ethernet switches (ROBO switch) 4 bytes proprietary tagging format.
+ */
+#define LINKTYPE_DSA_TAG_BRCM	281
+#define LINKTYPE_DSA_TAG_BRCM_PREPEND	282
+
+/*
+ * IEEE 802.15.4 with pseudo-header and optional meta-data TLVs, PHY payload
+ * exactly as it appears in the spec (no padding, no nothing), and FCS if
+ * specified by FCS Type TLV;  requested by James Ko <jck@exegin.com>.
+ * Specification at https://github.com/jkcko/ieee802.15.4-tap
+ */
+#define LINKTYPE_IEEE802_15_4_TAP       283
+
+/*
+ * Marvell (Ethertype) Distributed Switch Architecture proprietary tagging format.
+ */
+#define LINKTYPE_DSA_TAG_DSA	284
+#define LINKTYPE_DSA_TAG_EDSA	285
+
+/*
+ * Payload of lawful intercept packets using the ELEE protocol;
+ * https://socket.hr/draft-dfranusic-opsawg-elee-00.xml
+ * https://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://socket.hr/draft-dfranusic-opsawg-elee-00.xml&modeAsFormat=html/ascii
+ */
+#define LINKTYPE_ELEE		286
+
+/*
+ * Serial frames transmitted between a host and a Z-Wave chip.
+ */
+#define LINKTYPE_Z_WAVE_SERIAL	287
+
+/*
+ * USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
+ */
+#define LINKTYPE_USB_2_0	288
+
+/*
+ * ATSC Link-Layer Protocol (A/330) packets.
+ */
+#define LINKTYPE_ATSC_ALP	289
+
+#define LINKTYPE_MATCHING_MAX	289		/* highest value in the "matching" range */
 
 /*
  * The DLT_ and LINKTYPE_ values in the "matching" range should be the
@@ -1110,7 +1220,7 @@
 	{ DLT_ARCNET,		LINKTYPE_ARCNET_BSD },
 	{ DLT_SLIP,		LINKTYPE_SLIP },
 	{ DLT_PPP,		LINKTYPE_PPP },
-	{ DLT_FDDI,	 	LINKTYPE_FDDI },
+	{ DLT_FDDI,		LINKTYPE_FDDI },
 	{ DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL },
 
 	/*
@@ -1214,11 +1324,20 @@
 		return (DLT_PKTAP);
 
 	/*
-	 * For all other values in the matching range, the LINKTYPE
-	 * value is the same as the DLT value.
+	 * For all other values in the matching range, except for
+	 * LINKTYPE_ATM_CLIP, the LINKTYPE value is the same as
+	 * the DLT value.
+	 *
+	 * LINKTYPE_ATM_CLIP is a special case.  DLT_ATM_CLIP is
+	 * not on all platforms, but, so far, there don't appear
+	 * to be any platforms that define it as anything other
+	 * than 19; we define LINKTYPE_ATM_CLIP as something
+	 * other than 19, just in case.  That value is in the
+	 * matching range, so we have to check for it.
 	 */
 	if (linktype >= LINKTYPE_MATCHING_MIN &&
-	    linktype <= LINKTYPE_MATCHING_MAX)
+	    linktype <= LINKTYPE_MATCHING_MAX &&
+	    linktype != LINKTYPE_ATM_CLIP)
 		return (linktype);
 
 	/*
@@ -1231,7 +1350,7 @@
 
 	/*
 	 * If we don't have an entry for this LINKTYPE, return
-	 * the link type value; it may be a DLT from an older
+	 * the link type value; it may be a DLT from an newer
 	 * version of libpcap.
 	 */
 	return linktype;
@@ -1240,18 +1359,37 @@
 /*
  * Return the maximum snapshot length for a given DLT_ value.
  *
- * For most link-layer types, we use MAXIMUM_SNAPLEN, but for DLT_DBUS,
- * the maximum is 134217728, as per
+ * For most link-layer types, we use MAXIMUM_SNAPLEN.
+ *
+ * For DLT_DBUS, the maximum is 128MiB, as per
  *
  *    https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * For DLT_EBHSCR, the maximum is 8MiB, as per
+ *
+ *    https://www.elektrobit.com/ebhscr
+ *
+ * For DLT_USBPCAP, the maximum is 1MiB, as per
+ *
+ *    https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=15985
  */
 u_int
 max_snaplen_for_dlt(int dlt)
 {
-	if (dlt == DLT_DBUS)
-		return 134217728;
-	else
+	switch (dlt) {
+
+	case DLT_DBUS:
+		return 128*1024*1024;
+
+	case DLT_EBHSCR:
+		return 8*1024*1024;
+
+	case DLT_USBPCAP:
+		return 1024*1024;
+
+	default:
 		return MAXIMUM_SNAPLEN;
+	}
 }
 
 /*
@@ -1278,7 +1416,7 @@
 		return;
 	}
 
-	protocol = EXTRACT_16BITS(&shdr->sll_protocol);
+	protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
 	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
 		return;
 
diff --git a/pcap-config.1 b/pcap-config.1
index 0388d0f..fe8d799 100644
--- a/pcap-config.1
+++ b/pcap-config.1
@@ -69,4 +69,4 @@
 flag causes it to write flags appropriate for compiling with a
 statically-linked version of libpcap.
 .SH "SEE ALSO"
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap-dag.c b/pcap-dag.c
index 6b7c791..b207dd8 100644
--- a/pcap-dag.c
+++ b/pcap-dag.c
@@ -1,14 +1,6 @@
 /*
  * pcap-dag.c: Packet capture interface for Endace DAG cards.
  *
- * The functionality of this code attempts to mimic that of pcap-linux as much
- * as possible.  This code is compiled in several different ways depending on
- * whether DAG_ONLY and HAVE_DAG_API are defined.  If HAVE_DAG_API is not
- * defined it should not get compiled in, otherwise if DAG_ONLY is defined then
- * the 'dag_' function calls are renamed to 'pcap_' equivalents.  If DAG_ONLY
- * is not defined then nothing is altered - the dag_ functions will be
- * called as required from their pcap-linux/bpf equivalents.
- *
  * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
  * Modifications: Jesper Peterson
  *                Koryn Grant
@@ -27,7 +19,6 @@
 
 #include "pcap-int.h"
 
-#include <ctype.h>
 #include <netinet/in.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
@@ -216,7 +207,6 @@
 #define dag_size_t uint32_t
 #endif
 
-static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
 static int dag_stats(pcap_t *p, struct pcap_stat *ps);
 static int dag_set_datalink(pcap_t *p, int dlt);
 static int dag_get_datalink(pcap_t *p);
@@ -258,12 +248,18 @@
 
 	if(pd->dag_ref != NULL) {
 		dag_config_dispose(pd->dag_ref);
+		/*
+		 * Note: we don't need to call close(p->fd) or
+		 * dag_close(p->fd), as dag_config_dispose(pd->dag_ref)
+		 * does this.
+		 *
+		 * Set p->fd to -1 to make sure that's not done.
+		 */
 		p->fd = -1;
 		pd->dag_ref = NULL;
 	}
 	delete_pcap_dag(p);
 	pcap_cleanup_live_common(p);
-	/* Note: don't need to call close(p->fd) or dag_close(p->fd) as dag_config_dispose(pd->dag_ref) does this. */
 }
 
 static void
@@ -337,7 +333,7 @@
 /*
  *  Read at most max_packets from the capture stream and call the callback
  *  for each of them. Returns the number of packets handled, -1 if an
- *  error occured, or -2 if we were told to break out of the loop.
+ *  error occurred, or -2 if we were told to break out of the loop.
  */
 static int
 dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
@@ -423,7 +419,8 @@
 		rlen = ntohs(header->rlen);
 		if (rlen < dag_record_size)
 		{
-			strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
+			pcap_strlcpy(p->errbuf, "dag_read: record too small",
+			    PCAP_ERRBUF_SIZE);
 			return -1;
 		}
 		pd->dag_mem_bottom += rlen;
@@ -666,7 +663,7 @@
 			caplen = p->snapshot;
 
 		/* Run the packet filter if there is one. */
-		if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+		if ((p->fcode.bf_insns == NULL) || pcap_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
 
 			/* convert between timestamp formats */
 			register unsigned long long ts;
@@ -720,9 +717,9 @@
 }
 
 static int
-dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+dag_inject(pcap_t *p, const void *buf _U_, int size _U_)
 {
-	strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
+	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
 	    PCAP_ERRBUF_SIZE);
 	return (-1);
 }
@@ -746,18 +743,20 @@
 	daginf_t* daginf;
 	char * newDev = NULL;
 	char * device = p->opt.device;
+	int ret;
 	dag_size_t mindata;
 	struct timeval maxwait;
 	struct timeval poll;
 
 	if (device == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
-		return -1;
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
+		return PCAP_ERROR;
 	}
 
 	/* Initialize some components of the pcap structure. */
 	newDev = (char *)malloc(strlen(device) + 16);
 	if (newDev == NULL) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "Can't allocate string for device name");
 		goto fail;
@@ -765,6 +764,13 @@
 
 	/* Parse input name to get dag device and stream number if provided */
 	if (dag_parse_name(device, newDev, strlen(device) + 16, &pd->dag_stream) < 0) {
+		/*
+		 * XXX - it'd be nice if this indicated what was wrong
+		 * with the name.  Does this reliably set errno?
+		 * Should this return PCAP_ERROR_NO_SUCH_DEVICE in some
+		 * cases?
+		 */
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_parse_name");
 		goto fail;
@@ -772,25 +778,40 @@
 	device = newDev;
 
 	if (pd->dag_stream%2) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
+		ret = PCAP_ERROR;
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
 		goto fail;
 	}
 
 	/* setup device parameters */
 	if((pd->dag_ref = dag_config_init((char *)device)) == NULL) {
+		/*
+		 * XXX - does this reliably set errno?
+		 */
+		if (errno == ENOENT)
+			ret = PCAP_ERROR_NO_SUCH_DEVICE;
+		else if (errno == EPERM || errno == EACCES)
+			ret = PCAP_ERROR_PERM_DENIED;
+		else
+			ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_config_init %s", device);
 		goto fail;
 	}
 
 	if((p->fd = dag_config_get_card_fd(pd->dag_ref)) < 0) {
+		/*
+		 * XXX - does this reliably set errno?
+		 */
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_config_get_card_fd %s", device);
-		goto fail;
+		goto failclose;
 	}
 
 	/* Open requested stream. Can fail if already locked or on error */
 	if (dag_attach_stream64(p->fd, pd->dag_stream, 0, 0) < 0) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_attach_stream");
 		goto failclose;
@@ -809,6 +830,7 @@
 	 */
 	if (dag_get_stream_poll64(p->fd, pd->dag_stream,
 				&mindata, &maxwait, &poll) < 0) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_get_stream_poll");
 		goto faildetach;
@@ -853,6 +875,7 @@
 
 	if (dag_set_stream_poll64(p->fd, pd->dag_stream,
 				mindata, &maxwait, &poll) < 0) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_set_stream_poll");
 		goto faildetach;
@@ -875,6 +898,7 @@
 #endif
 
 	if(dag_start_stream(p->fd, pd->dag_stream) < 0) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "dag_start_stream %s", device);
 		goto faildetach;
@@ -910,7 +934,8 @@
 			if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
 				pd->dag_fcs_bits = n;
 			} else {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				ret = PCAP_ERROR;
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
 				goto failstop;
 			}
@@ -932,12 +957,15 @@
 	pd->dag_timeout	= p->opt.timeout;
 
 	p->linktype = -1;
-	if (dag_get_datalink(p) < 0)
+	if (dag_get_datalink(p) < 0) {
+		ret = PCAP_ERROR;
 		goto failstop;
+	}
 
 	p->bufsize = 0;
 
 	if (new_pcap_dag(p) < 0) {
+		ret = PCAP_ERROR;
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "new_pcap_dag %s", device);
 		goto failstop;
@@ -954,7 +982,7 @@
 
 	p->read_op = dag_read;
 	p->inject_op = dag_inject;
-	p->setfilter_op = dag_setfilter;
+	p->setfilter_op = install_bpf_program;
 	p->setdirection_op = NULL; /* Not implemented.*/
 	p->set_datalink_op = dag_set_datalink;
 	p->getnonblock_op = pcap_getnonblock_fd;
@@ -977,6 +1005,14 @@
 
 failclose:
 	dag_config_dispose(pd->dag_ref);
+	/*
+	 * Note: we don't need to call close(p->fd) or dag_close(p->fd),
+	 * as dag_config_dispose(pd->dag_ref) does this.
+	 *
+	 * Set p->fd to -1 to make sure that's not done.
+	 */
+	p->fd = -1;
+	pd->dag_ref = NULL;
 	delete_pcap_dag(p);
 
 fail:
@@ -985,7 +1021,7 @@
 		free((char *)newDev);
 	}
 
-	return PCAP_ERROR;
+	return ret;
 }
 
 pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
@@ -1035,7 +1071,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_dag));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dag);
 	if (p == NULL)
 		return NULL;
 
@@ -1048,7 +1084,6 @@
 	 * XXX Our native precision is 2^-32s, but libpcap doesn't support
 	 * power of two precisions yet. We can convert to either MICRO or NANO.
 	 */
-	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
@@ -1058,6 +1093,7 @@
 	}
 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
 	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+	p->tstamp_precision_count = 2;
 	return p;
 }
 
@@ -1078,10 +1114,10 @@
 		/* Note this counter is cleared at start of capture and will wrap at UINT_MAX.
 		 * The application is responsible for polling ps_drop frequently enough
 		 * to detect each wrap and integrate total drop with a wider counter */
-		if ((dag_error = dag_config_get_uint32_attribute_ex(pd->dag_ref, pd->drop_attr, &stream_drop) == kDagErrNone)) {
+		if ((dag_error = dag_config_get_uint32_attribute_ex(pd->dag_ref, pd->drop_attr, &stream_drop)) == kDagErrNone) {
 			pd->stat.ps_drop = stream_drop;
 		} else {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "reading stream drop attribute: %s",
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "reading stream drop attribute: %s",
 				 dag_config_strerror(dag_error));
 			return -1;
 		}
@@ -1109,10 +1145,10 @@
 
 	/* Try all the DAGs 0-DAG_MAX_BOARDS */
 	for (c = 0; c < DAG_MAX_BOARDS; c++) {
-		pcap_snprintf(name, 12, "dag%d", c);
+		snprintf(name, 12, "dag%d", c);
 		if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
 		{
-			(void) pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void) snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "dag: device name %s can't be parsed", name);
 			return (-1);
 		}
@@ -1137,10 +1173,10 @@
 			}
 			rxstreams = dag_rx_get_stream_count(dagfd);
 			for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
-				if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
+				if (0 == dag_attach_stream64(dagfd, stream, 0, 0)) {
 					dag_detach_stream(dagfd, stream);
 
-					pcap_snprintf(name,  10, "dag%d:%d", c, stream);
+					snprintf(name,  10, "dag%d:%d", c, stream);
 					if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
 						/*
 						 * Failure.
@@ -1161,30 +1197,6 @@
 	return (0);
 }
 
-/*
- * Installs the given bpf filter program in the given pcap structure.  There is
- * no attempt to store the filter in kernel memory as that is not supported
- * with DAG cards.
- */
-static int
-dag_setfilter(pcap_t *p, struct bpf_program *fp)
-{
-	if (!p)
-		return -1;
-	if (!fp) {
-		strncpy(p->errbuf, "setfilter: No filter specified",
-			sizeof(p->errbuf));
-		return -1;
-	}
-
-	/* Make our private copy of the filter */
-
-	if (install_bpf_program(p, fp) < 0)
-		return -1;
-
-	return (0);
-}
-
 static int
 dag_set_datalink(pcap_t *p, int dlt)
 {
@@ -1414,7 +1426,7 @@
 pcap_t *
 pcap_create_interface(const char *device, char *errbuf)
 {
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(errbuf, PCAP_ERRBUF_SIZE,
 	    "This version of libpcap only supports DAG cards");
 	return NULL;
 }
diff --git a/pcap-dbus.c b/pcap-dbus.c
index 1252975..506f150 100644
--- a/pcap-dbus.c
+++ b/pcap-dbus.c
@@ -68,7 +68,7 @@
 	while (!message) {
 		/* XXX handle->opt.timeout = timeout_ms; */
 		if (!dbus_connection_read_write(handlep->conn, 100)) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
 			return -1;
 		}
 
@@ -81,7 +81,7 @@
 	}
 
 	if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
 		return -1;
 	}
 
@@ -91,7 +91,7 @@
 
 		gettimeofday(&pkth.ts, NULL);
 		if (handle->fcode.bf_insns == NULL ||
-		    bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
+		    pcap_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
 			handlep->packets_read++;
 			callback(user, &pkth, (u_char *)raw_msg);
 			count++;
@@ -103,7 +103,7 @@
 }
 
 static int
-dbus_write(pcap_t *handle, const void *buf, size_t size)
+dbus_write(pcap_t *handle, const void *buf, int size)
 {
 	/* XXX, not tested */
 	struct pcap_dbus *handlep = handle->priv;
@@ -112,7 +112,7 @@
 	DBusMessage *msg;
 
 	if (!(msg = dbus_message_demarshal(buf, size, &error))) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
 		dbus_error_free(&error);
 		return -1;
 	}
@@ -154,7 +154,7 @@
 static int
 dbus_getnonblock(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for capturing on D-Bus");
 	return (-1);
 }
@@ -162,7 +162,7 @@
 static int
 dbus_setnonblock(pcap_t *p, int nonblock _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for capturing on D-Bus");
 	return (-1);
 }
@@ -189,14 +189,14 @@
 
 	if (strcmp(dev, "dbus-system") == 0) {
 		if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
+			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))) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
@@ -205,19 +205,19 @@
 		const char *addr = dev + 7;
 
 		if (!(handlep->conn = dbus_connection_open(addr, &error))) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
+			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)) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
 
 	} else {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.device);
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.device);
 		return PCAP_ERROR;
 	}
 
@@ -289,7 +289,7 @@
 			/* try without eavesdrop */
 			dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
 			if (dbus_error_is_set(&error)) {
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
+				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;
@@ -314,7 +314,7 @@
 	}
 
 	*is_ours = 1;
-	p = pcap_create_common(ebuf, sizeof (struct pcap_dbus));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dbus);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
index 430051e..208a63b 100644
--- a/pcap-dlpi.c
+++ b/pcap-dlpi.c
@@ -96,7 +96,6 @@
 #include <net/if.h>
 #endif
 
-#include <ctype.h>
 #ifdef HAVE_HPUX9
 #include <nlist.h>
 #endif
@@ -108,12 +107,7 @@
 #include <string.h>
 #include <stropts.h>
 #include <unistd.h>
-
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#else
-#define INT_MAX		2147483647
-#endif
 
 #include "pcap-int.h"
 #include "dlpisubs.h"
@@ -252,7 +246,7 @@
 }
 
 static int
-pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
+pcap_inject_dlpi(pcap_t *p, const void *buf, int size)
 {
 #ifdef DL_HP_RAWDLS
 	struct pcap_dlpi *pd = p->priv;
@@ -268,7 +262,7 @@
 	}
 #elif defined(DL_HP_RAWDLS)
 	if (pd->send_fd < 0) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "send: Output FD couldn't be opened");
 		return (-1);
 	}
@@ -307,7 +301,7 @@
 	 * it should check "p->linktype" and reject the send request if
 	 * it's anything other than DLT_EN10MB.
 	 */
-	strlcpy(p->errbuf, "send: Not supported on this version of this OS",
+	pcap_strlcpy(p->errbuf, "send: Not supported on this version of this OS",
 	    PCAP_ERRBUF_SIZE);
 	ret = -1;
 #endif /* raw mode */
@@ -363,9 +357,9 @@
 	*/
 	cp = strrchr(name, '/');
 	if (cp == NULL)
-		strlcpy(dname, name, sizeof(dname));
+		pcap_strlcpy(dname, name, sizeof(dname));
 	else
-		strlcpy(dname, cp + 1, sizeof(dname));
+		pcap_strlcpy(dname, cp + 1, sizeof(dname));
 
 	/*
 	 * Split the device name into a device type name and a unit number;
@@ -415,9 +409,9 @@
 	 * device name.
 	 */
 	if (*name == '/')
-		strlcpy(dname, name, sizeof(dname));
+		pcap_strlcpy(dname, name, sizeof(dname));
 	else
-		pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
+		snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
 		    name);
 
 	/*
@@ -432,7 +426,7 @@
 	 * Make a copy of the device pathname, and then remove the unit
 	 * number from the device pathname.
 	 */
-	strlcpy(dname2, dname, sizeof(dname));
+	pcap_strlcpy(dname2, dname, sizeof(dname));
 	*cp = '\0';
 
 	/* Try device without unit number */
@@ -475,7 +469,7 @@
 				 * interface is just a symptom of that
 				 * inability.
 				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "%s: No DLPI device found", name);
 			} else {
 				if (errno == EPERM || errno == EACCES)
@@ -639,7 +633,7 @@
 	**/
 	if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
 	    dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) {
-	    	status = PCAP_ERROR;
+		status = PCAP_ERROR;
 		goto bad;
 	}
 #endif /* AIX vs. HP-UX vs. other */
@@ -767,7 +761,7 @@
 	*/
 	if (dlinforeq(p->fd, p->errbuf) < 0 ||
 	    dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) {
-	    	status = PCAP_ERROR;
+		status = PCAP_ERROR;
 		goto bad;
 	}
 
@@ -805,7 +799,7 @@
 	get_release(release, sizeof (release), &osmajor, &osminor, &osmicro);
 	if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
 	    getenv("BUFMOD_FIXED") == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
 		    release);
 		ss = 0;
@@ -880,7 +874,7 @@
 	 */
 	cp = device + strlen(device) - 1;
 	if (*cp < '0' || *cp > '9') {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
 		    device);
 		return (NULL);
 	}
@@ -892,16 +886,16 @@
 	errno = 0;
 	unit = strtol(cp, &eos, 10);
 	if (*eos != '\0') {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
 		return (NULL);
 	}
 	if (errno == ERANGE || unit > INT_MAX) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
 		    device);
 		return (NULL);
 	}
 	if (unit < 0) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
 		    device);
 		return (NULL);
 	}
@@ -968,7 +962,7 @@
 		*ebuf = '\0';
 		hpsap++;
 		if (hpsap > 100) {
-			strlcpy(ebuf,
+			pcap_strlcpy(ebuf,
 			    "All SAPs from 22 through 100 are in use",
 			    PCAP_ERRBUF_SIZE);
 			return (-1);
@@ -1115,7 +1109,7 @@
 		return (-1);
 	}
 	for (i = 0; i < buf.nunits; i++) {
-		pcap_snprintf(baname, sizeof baname, "ba%u", i);
+		snprintf(baname, sizeof baname, "ba%u", i);
 		/*
 		 * XXX - is there a notion of "up" and "running"?
 		 * And is there a way to determine whether the
@@ -1202,7 +1196,7 @@
 			break;
 
 		default:
-			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			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)
@@ -1214,14 +1208,14 @@
 		return (PCAP_ERROR);
 
 	default:
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "recv_ack: %s: Unexpected primitive ack %s",
 		    what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive));
 		return (PCAP_ERROR);
 	}
 
 	if (ctl.len < size) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "recv_ack: %s: Ack too small (%d < %d)",
 		    what, ctl.len, size);
 		return (PCAP_ERROR);
@@ -1332,7 +1326,7 @@
 		return ("Pending outstanding connect indications");
 
 	default:
-		pcap_snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
+		snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
 		return (errbuf);
 	}
 }
@@ -1424,7 +1418,7 @@
 		return ("DL_RESET_CON");
 
 	default:
-		pcap_snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
+		snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
 		    prim);
 		return (primbuf);
 	}
@@ -1547,11 +1541,11 @@
 	*minorp = 0;
 	*microp = 0;
 	if (sysinfo(SI_RELEASE, buf, bufsize) < 0) {
-		strlcpy(buf, "?", bufsize);
+		pcap_strlcpy(buf, "?", bufsize);
 		return;
 	}
 	cp = buf;
-	if (!isdigit((unsigned char)*cp))
+	if (!PCAP_ISDIGIT((unsigned char)*cp))
 		return;
 	*majorp = strtol(cp, &cp, 10);
 	if (*cp++ != '.')
@@ -1651,21 +1645,21 @@
 		return (PCAP_ERROR);
 	}
 	if (ctl.len == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
 		return (PCAP_ERROR);
 	}
 
 	dlp = (dl_hp_ppa_ack_t *)ctl.buf;
 	if (dlp->dl_primitive != DL_HP_PPA_ACK) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
 		    (bpf_u_int32)dlp->dl_primitive);
 		return (PCAP_ERROR);
 	}
 
 	if ((size_t)ctl.len < DL_HP_PPA_ACK_SIZE) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		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);
@@ -1688,12 +1682,12 @@
 		return (PCAP_ERROR);
 	}
 	if (ctl.len == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
 		return (PCAP_ERROR);
 	}
 	if ((u_int)ctl.len < dlp->dl_length) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		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);
@@ -1750,7 +1744,7 @@
 		 * device number of a device with the name "/dev/<dev><unit>",
 		 * if such a device exists, as the old code did.
 		 */
-		pcap_snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit);
+		snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit);
 		if (stat(dname, &statbuf) < 0) {
 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 			    errno, "stat: %s", dname);
@@ -1769,12 +1763,12 @@
 		}
 	}
 	if (i == ap->dl_count) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "can't find /dev/dlpi PPA for %s%u", device, unit);
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	}
 	if (ip->dl_hdw_state == HDW_DEAD) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "%s%d: hardware state: DOWN\n", device, unit);
 		free(ppa_data_buf);
 		return (PCAP_ERROR);
@@ -1813,13 +1807,13 @@
 	if (cp != NULL)
 		ifname = cp + 1;
 	if (nlist(path_vmunix, &nl) < 0) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
 		    path_vmunix);
 		return (PCAP_ERROR);
 	}
 	if (nl[NL_IFNET].n_value == 0) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-		    "could't find %s kernel symbol",
+		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		    "couldn't find %s kernel symbol",
 		    nl[NL_IFNET].n_name);
 		return (PCAP_ERROR);
 	}
@@ -1849,7 +1843,7 @@
 		}
 	}
 
-	pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+	snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
 	return (PCAP_ERROR_NO_SUCH_DEVICE);
 }
 
@@ -1870,7 +1864,7 @@
 		    errno, "read");
 		return (-1);
 	} else if (cc != len) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
 		    len);
 		return (-1);
 	}
@@ -1886,7 +1880,7 @@
 	struct pcap_dlpi *pd;
 #endif
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-dos.c b/pcap-dos.c
index b1b9ecd..cdd60ea 100644
--- a/pcap-dos.c
+++ b/pcap-dos.c
@@ -153,7 +153,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dos);
 	if (p == NULL)
 		return (NULL);
 
@@ -215,7 +215,7 @@
   }
   else if (stricmp(active_dev->name,pcap->opt.device))
   {
-    pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+    snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
                    "Cannot use different devices simultaneously "
                    "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
     /* XXX - free pcap->buffer? */
@@ -283,7 +283,7 @@
       pcap.len    = rx_len;
 
       if (callback &&
-          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
+          (!p->fcode.bf_insns || pcap_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
       {
         filter_count++;
 
@@ -413,14 +413,14 @@
 
   if (!dev || !dev->get_stats)
   {
-    strlcpy (p->errbuf, "detailed device statistics not available",
+    pcap_strlcpy (p->errbuf, "detailed device statistics not available",
              PCAP_ERRBUF_SIZE);
     return (-1);
   }
 
   if (!strnicmp(dev->name,"pkt",3))
   {
-    strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
+    pcap_strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
              PCAP_ERRBUF_SIZE);
     return (-1);
   }
@@ -539,7 +539,7 @@
        net = IN_CLASSC_NET;
     else
     {
-      pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
+      snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
       return (-1);
     }
   }
@@ -667,7 +667,7 @@
 
       if (!(*dev->probe)(dev))    /* call the xx_probe() function */
       {
-        pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
+        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 */
@@ -689,7 +689,7 @@
 
     if (!(*dev->open)(dev))
     {
-      pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
+      snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
       if (pktInfo.error && !strncmp(dev->name,"pkt",3))
       {
         strcat (ebuf, ": ");
@@ -698,7 +698,7 @@
       return (NULL);
     }
 
-    /* Some devices need this to operate in promiscous mode
+    /* Some devices need this to operate in promiscuous mode
      */
     if (promisc && dev->set_multicast_list)
        (*dev->set_multicast_list) (dev);
@@ -711,14 +711,14 @@
    */
   if (!dev)
   {
-    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
+    snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
     return (NULL);
   }
 
 not_probed:
   if (!probed_dev)
   {
-    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
+    snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
     return (NULL);
   }
   return (dev);
@@ -943,7 +943,7 @@
 }
 
 /*
- * Supress PRINT message from Watt-32's sock_init()
+ * Suppress PRINT message from Watt-32's sock_init()
  */
 static void null_print (void) {}
 
@@ -1005,7 +1005,7 @@
   }
   else if (rc && using_pktdrv)
   {
-    pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
+    snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
     return (0);
   }
 
@@ -1031,11 +1031,9 @@
   pcap_save.linktype       = _eth_get_hwtype (NULL, NULL);
   pcap_save.snapshot       = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
 
-#if 1
   /* prevent use of resolve() and resolve_ip()
    */
   last_nameserver = 0;
-#endif
   return (1);
 }
 
diff --git a/pcap-dpdk.c b/pcap-dpdk.c
new file mode 100644
index 0000000..765abe5
--- /dev/null
+++ b/pcap-dpdk.c
@@ -0,0 +1,1070 @@
+/*
+ * Copyright (C) 2018 jingle YANG. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+Date: Dec 16, 2018
+
+Description:
+1. Pcap-dpdk provides libpcap the ability to use DPDK with the device name as dpdk:{portid}, such as dpdk:0.
+2. DPDK is a set of libraries and drivers for fast packet processing. (https://www.dpdk.org/)
+3. The testprogs/capturetest provides 6.4Gbps/800,000 pps on Intel 10-Gigabit X540-AT2 with DPDK 18.11.
+
+Limitations:
+1. DPDK support will be on if DPDK is available. Please set DIR for --with-dpdk[=DIR] with ./configure or -DDPDK_DIR[=DIR] with cmake if DPDK is installed manually.
+2. Only support link libdpdk.so dynamically, because the libdpdk.a will not work correctly.
+3. Only support read operation, and packet injection has not been supported yet.
+
+Usage:
+1. Compile DPDK as shared library and install.(https://github.com/DPDK/dpdk.git)
+
+You shall modify the file $RTE_SDK/$RTE_TARGET/.config and set:
+CONFIG_RTE_BUILD_SHARED_LIB=y
+By the following command:
+sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/' $RTE_SDK/$RTE_TARGET/.config
+
+2. Launch l2fwd that is one of DPDK examples correctly, and get device information.
+
+You shall learn how to bind nic with DPDK-compatible driver by $RTE_SDK/usertools/dpdk-devbind.py, such as igb_uio.
+And enable hugepages by dpdk-setup.sh
+
+Then launch the l2fwd with dynamic dirver support. For example:
+$RTE_SDK/examples/l2fwd/$RTE_TARGET/l2fwd -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so -- -p 0x1
+
+3. Compile libpcap with dpdk options.
+
+If DPDK has not been found automatically, you shall export DPDK environment variable which are used for compiling DPDK. And then pass $RTE_SDK/$RTE_TARGET to --with-dpdk or -DDPDK_DIR
+
+export RTE_SDK={your DPDK base directory}
+export RTE_TARGET={your target name}
+
+3.1 With configure
+
+./configure --with-dpdk=$RTE_SDK/$RTE_TARGET && make -s all && make -s testprogs && make install
+
+3.2 With cmake
+
+mkdir -p build && cd build && cmake -DDPDK_DIR=$RTE_SDK/$RTE_TARGET ../ && make -s all && make -s testprogs && make install
+
+4. Link your own program with libpcap, and use DPDK with the device name as dpdk:{portid}, such as dpdk:0.
+And you shall set DPDK configure options by environment variable DPDK_CFG
+For example, the testprogs/capturetest could be lanched by:
+
+env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so" ./capturetest -i dpdk:0
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <sys/time.h>
+
+//header for calling dpdk
+#include <rte_config.h>
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_bus.h>
+
+#include "pcap-int.h"
+#include "pcap-dpdk.h"
+
+/*
+ * Deal with API changes that break source compatibility.
+ */
+
+#ifdef HAVE_STRUCT_RTE_ETHER_ADDR
+#define ETHER_ADDR_TYPE	struct rte_ether_addr
+#else
+#define ETHER_ADDR_TYPE	struct ether_addr
+#endif
+
+#define DPDK_DEF_LOG_LEV RTE_LOG_ERR
+//
+// This is set to 0 if we haven't initialized DPDK yet, 1 if we've
+// successfully initialized it, a negative value, which is the negative
+// of the rte_errno from rte_eal_init(), if we tried to initialize it
+// and got an error.
+//
+static int is_dpdk_pre_inited=0;
+#define DPDK_LIB_NAME "libpcap_dpdk"
+#define DPDK_DESC "Data Plane Development Kit (DPDK) Interface"
+#define DPDK_ERR_PERM_MSG "permission denied, DPDK needs root permission"
+#define DPDK_ARGC_MAX 64
+#define DPDK_CFG_MAX_LEN 1024
+#define DPDK_DEV_NAME_MAX 32
+#define DPDK_DEV_DESC_MAX 512
+#define DPDK_CFG_ENV_NAME "DPDK_CFG"
+#define DPDK_DEF_MIN_SLEEP_MS 1
+static char dpdk_cfg_buf[DPDK_CFG_MAX_LEN];
+#define DPDK_MAC_ADDR_SIZE 32
+#define DPDK_DEF_MAC_ADDR "00:00:00:00:00:00"
+#define DPDK_PCI_ADDR_SIZE 16
+#define DPDK_DEF_CFG "--log-level=error -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so"
+#define DPDK_PREFIX "dpdk:"
+#define DPDK_PORTID_MAX 65535U
+#define MBUF_POOL_NAME "mbuf_pool"
+#define DPDK_TX_BUF_NAME "tx_buffer"
+//The number of elements in the mbuf pool.
+#define DPDK_NB_MBUFS 8192U
+#define MEMPOOL_CACHE_SIZE 256
+#define MAX_PKT_BURST 32
+// Configurable number of RX/TX ring descriptors
+#define RTE_TEST_RX_DESC_DEFAULT 1024
+#define RTE_TEST_TX_DESC_DEFAULT 1024
+
+static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
+static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+
+#ifdef RTE_ETHER_MAX_JUMBO_FRAME_LEN
+#define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
+#else
+#define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN
+#endif
+
+static struct rte_eth_dev_tx_buffer *tx_buffer;
+
+struct dpdk_ts_helper{
+	struct timeval start_time;
+	uint64_t start_cycles;
+	uint64_t hz;
+};
+struct pcap_dpdk{
+	pcap_t * orig;
+	uint16_t portid; // portid of DPDK
+	int must_clear_promisc;
+	uint64_t bpf_drop;
+	int nonblock;
+	struct timeval required_select_timeout;
+	struct timeval prev_ts;
+	struct rte_eth_stats prev_stats;
+	struct timeval curr_ts;
+	struct rte_eth_stats curr_stats;
+	uint64_t pps;
+	uint64_t bps;
+	struct rte_mempool * pktmbuf_pool;
+	struct dpdk_ts_helper ts_helper;
+	ETHER_ADDR_TYPE eth_addr;
+	char mac_addr[DPDK_MAC_ADDR_SIZE];
+	char pci_addr[DPDK_PCI_ADDR_SIZE];
+	unsigned char pcap_tmp_buf[RTE_ETH_PCAP_SNAPLEN];
+};
+
+static struct rte_eth_conf port_conf = {
+	.rxmode = {
+		.split_hdr_size = 0,
+	},
+	.txmode = {
+		.mq_mode = ETH_MQ_TX_NONE,
+	},
+};
+
+static void	dpdk_fmt_errmsg_for_rte_errno(char *, size_t, int,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+
+/*
+ * Generate an error message based on a format, arguments, and an
+ * rte_errno, with a message for the rte_errno after the formatted output.
+ */
+static void dpdk_fmt_errmsg_for_rte_errno(char *errbuf, size_t errbuflen,
+    int errnum, const char *fmt, ...)
+{
+	va_list ap;
+	size_t msglen;
+	char *p;
+	size_t errbuflen_remaining;
+
+	va_start(ap, fmt);
+	vsnprintf(errbuf, errbuflen, fmt, ap);
+	va_end(ap);
+	msglen = strlen(errbuf);
+
+	/*
+	 * Do we have enough space to append ": "?
+	 * Including the terminating '\0', that's 3 bytes.
+	 */
+	if (msglen + 3 > errbuflen) {
+		/* No - just give them what we've produced. */
+		return;
+	}
+	p = errbuf + msglen;
+	errbuflen_remaining = errbuflen - msglen;
+	*p++ = ':';
+	*p++ = ' ';
+	*p = '\0';
+	msglen += 2;
+	errbuflen_remaining -= 2;
+
+	/*
+	 * Now append the string for the error code.
+	 * rte_strerror() is thread-safe, at least as of dpdk 18.11,
+	 * unlike strerror() - it uses strerror_r() rather than strerror()
+	 * for UN*X errno values, and prints to what I assume is a per-thread
+	 * buffer (based on the "PER_LCORE" in "RTE_DEFINE_PER_LCORE" used
+	 * to declare the buffers statically) for DPDK errors.
+	 */
+	snprintf(p, errbuflen_remaining, "%s", rte_strerror(errnum));
+}
+
+static int dpdk_init_timer(struct pcap_dpdk *pd){
+	gettimeofday(&(pd->ts_helper.start_time),NULL);
+	pd->ts_helper.start_cycles = rte_get_timer_cycles();
+	pd->ts_helper.hz = rte_get_timer_hz();
+	if (pd->ts_helper.hz == 0){
+		return -1;
+	}
+	return 0;
+}
+static inline void calculate_timestamp(struct dpdk_ts_helper *helper,struct timeval *ts)
+{
+	uint64_t cycles;
+	// delta
+	struct timeval cur_time;
+	cycles = rte_get_timer_cycles() - helper->start_cycles;
+	cur_time.tv_sec = (time_t)(cycles/helper->hz);
+	cur_time.tv_usec = (suseconds_t)((cycles%helper->hz)*1e6/helper->hz);
+	timeradd(&(helper->start_time), &cur_time, ts);
+}
+
+static uint32_t dpdk_gather_data(unsigned char *data, uint32_t len, struct rte_mbuf *mbuf)
+{
+	uint32_t total_len = 0;
+	while (mbuf && (total_len+mbuf->data_len) < len ){
+		rte_memcpy(data+total_len, rte_pktmbuf_mtod(mbuf,void *),mbuf->data_len);
+		total_len+=mbuf->data_len;
+		mbuf=mbuf->next;
+	}
+	return total_len;
+}
+
+
+static int dpdk_read_with_timeout(pcap_t *p, struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){
+	struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
+	int nb_rx = 0;
+	int timeout_ms = p->opt.timeout;
+	int sleep_ms = 0;
+	if (pd->nonblock){
+		// In non-blocking mode, just read once, no matter how many packets are captured.
+		nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt);
+	}else{
+		// In blocking mode, read many times until packets are captured or timeout or break_loop is set.
+		// if timeout_ms == 0, it may be blocked forever.
+		while (timeout_ms == 0 || sleep_ms < timeout_ms){
+			nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt);
+			if (nb_rx){ // got packets within timeout_ms
+				break;
+			}else{ // no packet arrives at this round.
+				if (p->break_loop){
+					break;
+				}
+				// sleep for a very short while.
+				// block sleep is the only choice, since usleep() will impact performance dramatically.
+				rte_delay_us_block(DPDK_DEF_MIN_SLEEP_MS*1000);
+				sleep_ms += DPDK_DEF_MIN_SLEEP_MS;
+			}
+		}
+	}
+	return nb_rx;
+}
+
+static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *cb_arg)
+{
+	struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
+	int burst_cnt = 0;
+	int nb_rx = 0;
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	struct rte_mbuf *m;
+	struct pcap_pkthdr pcap_header;
+	// In DPDK, pkt_len is sum of lengths for all segments. And data_len is for one segment
+	uint32_t pkt_len = 0;
+	uint32_t caplen = 0;
+	u_char *bp = NULL;
+	int i=0;
+	unsigned int gather_len =0;
+	int pkt_cnt = 0;
+	u_char *large_buffer=NULL;
+	int timeout_ms = p->opt.timeout;
+
+	if ( !PACKET_COUNT_IS_UNLIMITED(max_cnt) && max_cnt < MAX_PKT_BURST){
+		burst_cnt = max_cnt;
+	}else{
+		burst_cnt = MAX_PKT_BURST;
+	}
+
+	while( PACKET_COUNT_IS_UNLIMITED(max_cnt) || pkt_cnt < max_cnt){
+		if (p->break_loop){
+			p->break_loop = 0;
+			return PCAP_ERROR_BREAK;
+		}
+		// read once in non-blocking mode, or try many times waiting for timeout_ms.
+		// if timeout_ms == 0, it will be blocked until one packet arrives or break_loop is set.
+		nb_rx = dpdk_read_with_timeout(p, pkts_burst, burst_cnt);
+		if (nb_rx == 0){
+			if (pd->nonblock){
+				RTE_LOG(DEBUG, USER1, "dpdk: no packets available in non-blocking mode.\n");
+			}else{
+				if (p->break_loop){
+					RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is set in blocking mode.\n");
+					p->break_loop = 0;
+					return PCAP_ERROR_BREAK;
+
+				}
+				RTE_LOG(DEBUG, USER1, "dpdk: no packets available for timeout %d ms in blocking mode.\n", timeout_ms);
+			}
+			// break if dpdk reads 0 packet, no matter in blocking(timeout) or non-blocking mode.
+			break;
+		}
+		pkt_cnt += nb_rx;
+		for ( i = 0; i < nb_rx; i++) {
+			m = pkts_burst[i];
+			calculate_timestamp(&(pd->ts_helper),&(pcap_header.ts));
+			pkt_len = rte_pktmbuf_pkt_len(m);
+			// caplen = min(pkt_len, p->snapshot);
+			// caplen will not be changed, no matter how long the rte_pktmbuf
+			caplen = pkt_len < (uint32_t)p->snapshot ? pkt_len: (uint32_t)p->snapshot;
+			pcap_header.caplen = caplen;
+			pcap_header.len = pkt_len;
+			// volatile prefetch
+			rte_prefetch0(rte_pktmbuf_mtod(m, void *));
+			bp = NULL;
+			if (m->nb_segs == 1)
+			{
+				bp = rte_pktmbuf_mtod(m, u_char *);
+			}else{
+				// use fast buffer pcap_tmp_buf if pkt_len is small, no need to call malloc and free
+				if ( pkt_len <= RTE_ETH_PCAP_SNAPLEN)
+				{
+					gather_len = dpdk_gather_data(pd->pcap_tmp_buf, RTE_ETH_PCAP_SNAPLEN, m);
+					bp = pd->pcap_tmp_buf;
+				}else{
+					// need call free later
+					large_buffer = (u_char *)malloc(caplen*sizeof(u_char));
+					gather_len = dpdk_gather_data(large_buffer, caplen, m);
+					bp = large_buffer;
+				}
+
+			}
+			if (bp){
+				if (p->fcode.bf_insns==NULL || pcap_filter(p->fcode.bf_insns, bp, pcap_header.len, pcap_header.caplen)){
+					cb(cb_arg, &pcap_header, bp);
+				}else{
+					pd->bpf_drop++;
+				}
+			}
+			//free all pktmbuf
+			rte_pktmbuf_free(m);
+			if (large_buffer){
+				free(large_buffer);
+				large_buffer=NULL;
+			}
+		}
+	}
+	return pkt_cnt;
+}
+
+static int pcap_dpdk_inject(pcap_t *p, const void *buf _U_, int size _U_)
+{
+	//not implemented yet
+	pcap_strlcpy(p->errbuf,
+	    "dpdk error: Inject function has not been implemented yet",
+	    PCAP_ERRBUF_SIZE);
+	return PCAP_ERROR;
+}
+
+static void pcap_dpdk_close(pcap_t *p)
+{
+	struct pcap_dpdk *pd = p->priv;
+	if (pd==NULL)
+	{
+		return;
+	}
+	if (pd->must_clear_promisc)
+	{
+		rte_eth_promiscuous_disable(pd->portid);
+	}
+	rte_eth_dev_stop(pd->portid);
+	rte_eth_dev_close(pd->portid);
+	pcap_cleanup_live_common(p);
+}
+
+static void nic_stats_display(struct pcap_dpdk *pd)
+{
+	uint16_t portid = pd->portid;
+	struct rte_eth_stats stats;
+	rte_eth_stats_get(portid, &stats);
+	RTE_LOG(INFO,USER1, "portid:%d, RX-packets: %-10"PRIu64"  RX-errors:  %-10"PRIu64
+	       "  RX-bytes:  %-10"PRIu64"  RX-Imissed:  %-10"PRIu64"\n", portid, stats.ipackets, stats.ierrors,
+	       stats.ibytes,stats.imissed);
+	RTE_LOG(INFO,USER1, "portid:%d, RX-PPS: %-10"PRIu64" RX-Mbps: %.2lf\n", portid, pd->pps, pd->bps/1e6f );
+}
+
+static int pcap_dpdk_stats(pcap_t *p, struct pcap_stat *ps)
+{
+	struct pcap_dpdk *pd = p->priv;
+	calculate_timestamp(&(pd->ts_helper), &(pd->curr_ts));
+	rte_eth_stats_get(pd->portid,&(pd->curr_stats));
+	if (ps){
+		ps->ps_recv = pd->curr_stats.ipackets;
+		ps->ps_drop = pd->curr_stats.ierrors;
+		ps->ps_drop += pd->bpf_drop;
+		ps->ps_ifdrop = pd->curr_stats.imissed;
+	}
+	uint64_t delta_pkt = pd->curr_stats.ipackets - pd->prev_stats.ipackets;
+	struct timeval delta_tm;
+	timersub(&(pd->curr_ts),&(pd->prev_ts), &delta_tm);
+	uint64_t delta_usec = delta_tm.tv_sec*1e6+delta_tm.tv_usec;
+	uint64_t delta_bit = (pd->curr_stats.ibytes-pd->prev_stats.ibytes)*8;
+	RTE_LOG(DEBUG, USER1, "delta_usec: %-10"PRIu64" delta_pkt: %-10"PRIu64" delta_bit: %-10"PRIu64"\n", delta_usec, delta_pkt, delta_bit);
+	pd->pps = (uint64_t)(delta_pkt*1e6f/delta_usec);
+	pd->bps = (uint64_t)(delta_bit*1e6f/delta_usec);
+	nic_stats_display(pd);
+	pd->prev_stats = pd->curr_stats;
+	pd->prev_ts = pd->curr_ts;
+	return 0;
+}
+
+static int pcap_dpdk_setnonblock(pcap_t *p, int nonblock){
+	struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
+	pd->nonblock = nonblock;
+	return 0;
+}
+
+static int pcap_dpdk_getnonblock(pcap_t *p){
+	struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
+	return pd->nonblock;
+}
+static int check_link_status(uint16_t portid, struct rte_eth_link *plink)
+{
+	// wait up to 9 seconds to get link status
+	rte_eth_link_get(portid, plink);
+	return plink->link_status == ETH_LINK_UP;
+}
+static void eth_addr_str(ETHER_ADDR_TYPE *addrp, char* mac_str, int len)
+{
+	int offset=0;
+	if (addrp == NULL){
+		snprintf(mac_str, len-1, DPDK_DEF_MAC_ADDR);
+		return;
+	}
+	for (int i=0; i<6; i++)
+	{
+		if (offset >= len)
+		{ // buffer overflow
+			return;
+		}
+		if (i==0)
+		{
+			snprintf(mac_str+offset, len-1-offset, "%02X",addrp->addr_bytes[i]);
+			offset+=2; // FF
+		}else{
+			snprintf(mac_str+offset, len-1-offset, ":%02X", addrp->addr_bytes[i]);
+			offset+=3; // :FF
+		}
+	}
+	return;
+}
+// return portid by device name, otherwise return -1
+static uint16_t portid_by_device(char * device)
+{
+	uint16_t ret = DPDK_PORTID_MAX;
+	int len = strlen(device);
+	int prefix_len = strlen(DPDK_PREFIX);
+	unsigned long ret_ul = 0L;
+	char *pEnd;
+	if (len<=prefix_len || strncmp(device, DPDK_PREFIX, prefix_len)) // check prefix dpdk:
+	{
+		return ret;
+	}
+	//check all chars are digital
+	for (int i=prefix_len; device[i]; i++){
+		if (device[i]<'0' || device[i]>'9'){
+			return ret;
+		}
+	}
+	ret_ul = strtoul(&(device[prefix_len]), &pEnd, 10);
+	if (pEnd == &(device[prefix_len]) || *pEnd != '\0'){
+		return ret;
+	}
+	// too large for portid
+	if (ret_ul >= DPDK_PORTID_MAX){
+		return ret;
+	}
+	ret = (uint16_t)ret_ul;
+	return ret;
+}
+
+static int parse_dpdk_cfg(char* dpdk_cfg,char** dargv)
+{
+	int cnt=0;
+	memset(dargv,0,sizeof(dargv[0])*DPDK_ARGC_MAX);
+	//current process name
+	int skip_space = 1;
+	int i=0;
+	RTE_LOG(INFO, USER1,"dpdk cfg: %s\n",dpdk_cfg);
+	// find first non space char
+	// The last opt is NULL
+	for (i=0;dpdk_cfg[i] && cnt<DPDK_ARGC_MAX-1;i++){
+		if (skip_space && dpdk_cfg[i]!=' '){ // not space
+			skip_space=!skip_space; // skip normal char
+			dargv[cnt++] = dpdk_cfg+i;
+		}
+		if (!skip_space && dpdk_cfg[i]==' '){ // fint a space
+			dpdk_cfg[i]=0x00; // end of this opt
+			skip_space=!skip_space; // skip space char
+		}
+	}
+	dargv[cnt]=NULL;
+	return cnt;
+}
+
+// only called once
+// Returns:
+//
+//    1 on success;
+//
+//    0 if "the EAL cannot initialize on this system", which we treat as
+//    meaning "DPDK isn't available";
+//
+//    a PCAP_ERROR_ code for other errors.
+//
+// If eaccess_not_fatal is non-zero, treat "a permissions issue" the way
+// we treat "the EAL cannot initialize on this system".  We use that
+// when trying to find DPDK devices, as we don't want to fail to return
+// *any* devices just because we can't support DPDK; when we're trying
+// to open a device, we need to return a permissions error in that case.
+static int dpdk_pre_init(char * ebuf, int eaccess_not_fatal)
+{
+	int dargv_cnt=0;
+	char *dargv[DPDK_ARGC_MAX];
+	char *ptr_dpdk_cfg = NULL;
+	int ret;
+	// globale var
+	if (is_dpdk_pre_inited != 0)
+	{
+		// already inited; did that succeed?
+		if (is_dpdk_pre_inited < 0)
+		{
+			// failed
+			goto error;
+		}
+		else
+		{
+			// succeeded
+			return 1;
+		}
+	}
+	// init EAL
+	ptr_dpdk_cfg = getenv(DPDK_CFG_ENV_NAME);
+	// set default log level to debug
+	rte_log_set_global_level(DPDK_DEF_LOG_LEV);
+	if (ptr_dpdk_cfg == NULL)
+	{
+		RTE_LOG(INFO,USER1,"env $DPDK_CFG is unset, so using default: %s\n",DPDK_DEF_CFG);
+		ptr_dpdk_cfg = DPDK_DEF_CFG;
+	}
+	memset(dpdk_cfg_buf,0,sizeof(dpdk_cfg_buf));
+	snprintf(dpdk_cfg_buf,DPDK_CFG_MAX_LEN-1,"%s %s",DPDK_LIB_NAME,ptr_dpdk_cfg);
+	dargv_cnt = parse_dpdk_cfg(dpdk_cfg_buf,dargv);
+	ret = rte_eal_init(dargv_cnt,dargv);
+	if (ret == -1)
+	{
+		// Indicate that we've called rte_eal_init() by setting
+		// is_dpdk_pre_inited to the negative of the error code,
+		// and process the error.
+		is_dpdk_pre_inited = -rte_errno;
+		goto error;
+	}
+	// init succeeded, so we do not need to do it again later.
+	is_dpdk_pre_inited = 1;
+	return 1;
+
+error:
+	switch (-is_dpdk_pre_inited)
+	{
+		case EACCES:
+			// This "indicates a permissions issue.".
+			RTE_LOG(ERR, USER1, "%s\n", DPDK_ERR_PERM_MSG);
+			// If we were told to treat this as just meaning
+			// DPDK isn't available, do so.
+			if (eaccess_not_fatal)
+				return 0;
+			// Otherwise report a fatal error.
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "DPDK requires that it run as root");
+			return PCAP_ERROR_PERM_DENIED;
+
+		case EAGAIN:
+			// This "indicates either a bus or system
+			// resource was not available, setup may
+			// be attempted again."
+			// There's no such error in pcap, so I'm
+			// not sure what we should do here.
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "Bus or system resource was not available");
+			break;
+
+		case EALREADY:
+			// This "indicates that the rte_eal_init
+			// function has already been called, and
+			// cannot be called again."
+			// That's not an error; set the "we've
+			// been here before" flag and return
+			// success.
+			is_dpdk_pre_inited = 1;
+			return 1;
+
+		case EFAULT:
+			// This "indicates the tailq configuration
+			// name was not found in memory configuration."
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "The tailq configuration name was not found in the memory configuration");
+			return PCAP_ERROR;
+
+		case EINVAL:
+			// This "indicates invalid parameters were
+			// passed as argv/argc."  Those came from
+			// the configuration file.
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "The configuration file has invalid parameters");
+			break;
+
+		case ENOMEM:
+			// This "indicates failure likely caused by
+			// an out-of-memory condition."
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "Out of memory");
+			break;
+
+		case ENODEV:
+			// This "indicates memory setup issues."
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "An error occurred setting up memory");
+			break;
+
+		case ENOTSUP:
+			// This "indicates that the EAL cannot
+			// initialize on this system."  We treat
+			// that as meaning DPDK isn't available
+			// on this machine, rather than as a
+			// fatal error, and let our caller decide
+			// whether that's a fatal error (if trying
+			// to activate a DPDK device) or not (if
+			// trying to enumerate devices).
+			return 0;
+
+		case EPROTO:
+			// This "indicates that the PCI bus is
+			// either not present, or is not readable
+			// by the eal."  Does "the PCI bus is not
+			// present" mean "this machine has no PCI
+			// bus", which strikes me as a "not available"
+			// case?  If so, should "is not readable by
+			// the EAL" also something we should treat
+			// as a "not available" case?  If not, we
+			// can't distinguish between the two, so
+			// we're stuck.
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "PCI bus is not present or not readable by the EAL");
+			break;
+
+		case ENOEXEC:
+			// This "indicates that a service core
+			// failed to launch successfully."
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "A service core failed to launch successfully");
+			break;
+
+		default:
+			//
+			// That's not in the list of errors in
+			// the documentation; let it be reported
+			// as an error.
+			//
+			dpdk_fmt_errmsg_for_rte_errno(ebuf,
+			    PCAP_ERRBUF_SIZE, -is_dpdk_pre_inited,
+			    "dpdk error: dpdk_pre_init failed");
+			break;
+	}
+	// Error.
+	return PCAP_ERROR;
+}
+
+static int pcap_dpdk_activate(pcap_t *p)
+{
+	struct pcap_dpdk *pd = p->priv;
+	pd->orig = p;
+	int ret = PCAP_ERROR;
+	uint16_t nb_ports=0;
+	uint16_t portid= DPDK_PORTID_MAX;
+	unsigned nb_mbufs = DPDK_NB_MBUFS;
+	struct rte_eth_rxconf rxq_conf;
+	struct rte_eth_txconf txq_conf;
+	struct rte_eth_conf local_port_conf = port_conf;
+	struct rte_eth_dev_info dev_info;
+	int is_port_up = 0;
+	struct rte_eth_link link;
+	do{
+		//init EAL; fail if we have insufficient permission
+		char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
+		ret = dpdk_pre_init(dpdk_pre_init_errbuf, 0);
+		if (ret < 0)
+		{
+			// This returns a negative value on an error.
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "Can't open device %s: %s",
+			    p->opt.device, dpdk_pre_init_errbuf);
+			// ret is set to the correct error
+			break;
+		}
+		if (ret == 0)
+		{
+			// This means DPDK isn't available on this machine.
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "Can't open device %s: DPDK is not available on this machine",
+			    p->opt.device);
+			return PCAP_ERROR_NO_SUCH_DEVICE;
+		}
+
+		ret = dpdk_init_timer(pd);
+		if (ret<0)
+		{
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				"dpdk error: Init timer is zero with device %s",
+				p->opt.device);
+			ret = PCAP_ERROR;
+			break;
+		}
+
+		nb_ports = rte_eth_dev_count_avail();
+		if (nb_ports == 0)
+		{
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "dpdk error: No Ethernet ports");
+			ret = PCAP_ERROR;
+			break;
+		}
+
+		portid = portid_by_device(p->opt.device);
+		if (portid == DPDK_PORTID_MAX){
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "dpdk error: portid is invalid. device %s",
+			    p->opt.device);
+			ret = PCAP_ERROR_NO_SUCH_DEVICE;
+			break;
+		}
+
+		pd->portid = portid;
+
+		if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+		{
+			p->snapshot = MAXIMUM_SNAPLEN;
+		}
+		// create the mbuf pool
+		pd->pktmbuf_pool = rte_pktmbuf_pool_create(MBUF_POOL_NAME, nb_mbufs,
+			MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+			rte_socket_id());
+		if (pd->pktmbuf_pool == NULL)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, rte_errno,
+			    "dpdk error: Cannot init mbuf pool");
+			ret = PCAP_ERROR;
+			break;
+		}
+		// config dev
+		rte_eth_dev_info_get(portid, &dev_info);
+		if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
+		{
+			local_port_conf.txmode.offloads |=DEV_TX_OFFLOAD_MBUF_FAST_FREE;
+		}
+		// only support 1 queue
+		ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
+		if (ret < 0)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, -ret,
+			    "dpdk error: Cannot configure device: port=%u",
+			    portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+		// adjust rx tx
+		ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
+		if (ret < 0)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, -ret,
+			    "dpdk error: Cannot adjust number of descriptors: port=%u",
+			    portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+		// get MAC addr
+		rte_eth_macaddr_get(portid, &(pd->eth_addr));
+		eth_addr_str(&(pd->eth_addr), pd->mac_addr, DPDK_MAC_ADDR_SIZE-1);
+
+		// init one RX queue
+		rxq_conf = dev_info.default_rxconf;
+		rxq_conf.offloads = local_port_conf.rxmode.offloads;
+		ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
+					     rte_eth_dev_socket_id(portid),
+					     &rxq_conf,
+					     pd->pktmbuf_pool);
+		if (ret < 0)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, -ret,
+			    "dpdk error: rte_eth_rx_queue_setup:port=%u",
+			    portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+
+		// init one TX queue
+		txq_conf = dev_info.default_txconf;
+		txq_conf.offloads = local_port_conf.txmode.offloads;
+		ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
+				rte_eth_dev_socket_id(portid),
+				&txq_conf);
+		if (ret < 0)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, -ret,
+			    "dpdk error: rte_eth_tx_queue_setup:port=%u",
+			    portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+		// Initialize TX buffers
+		tx_buffer = rte_zmalloc_socket(DPDK_TX_BUF_NAME,
+				RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
+				rte_eth_dev_socket_id(portid));
+		if (tx_buffer == NULL)
+		{
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "dpdk error: Cannot allocate buffer for tx on port %u", portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+		rte_eth_tx_buffer_init(tx_buffer, MAX_PKT_BURST);
+		// Start device
+		ret = rte_eth_dev_start(portid);
+		if (ret < 0)
+		{
+			dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+			    PCAP_ERRBUF_SIZE, -ret,
+			    "dpdk error: rte_eth_dev_start:port=%u",
+			    portid);
+			ret = PCAP_ERROR;
+			break;
+		}
+		// set promiscuous mode
+		if (p->opt.promisc){
+			pd->must_clear_promisc=1;
+			rte_eth_promiscuous_enable(portid);
+		}
+		// check link status
+		is_port_up = check_link_status(portid, &link);
+		if (!is_port_up){
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "dpdk error: link is down, port=%u",portid);
+			ret = PCAP_ERROR_IFACE_NOT_UP;
+			break;
+		}
+		// reset statistics
+		rte_eth_stats_reset(pd->portid);
+		calculate_timestamp(&(pd->ts_helper), &(pd->prev_ts));
+		rte_eth_stats_get(pd->portid,&(pd->prev_stats));
+		// format pcap_t
+		pd->portid = portid;
+		p->fd = pd->portid;
+		if (p->snapshot <=0 || p->snapshot> MAXIMUM_SNAPLEN)
+		{
+			p->snapshot = MAXIMUM_SNAPLEN;
+		}
+		p->linktype = DLT_EN10MB; // Ethernet, the 10MB is historical.
+		p->selectable_fd = p->fd;
+		p->read_op = pcap_dpdk_dispatch;
+		p->inject_op = pcap_dpdk_inject;
+		// using pcap_filter currently, though DPDK provides their own BPF function. Because DPDK BPF needs load a ELF file as a filter.
+		p->setfilter_op = install_bpf_program;
+		p->setdirection_op = NULL;
+		p->set_datalink_op = NULL;
+		p->getnonblock_op = pcap_dpdk_getnonblock;
+		p->setnonblock_op = pcap_dpdk_setnonblock;
+		p->stats_op = pcap_dpdk_stats;
+		p->cleanup_op = pcap_dpdk_close;
+		p->breakloop_op = pcap_breakloop_common;
+		// set default timeout
+		pd->required_select_timeout.tv_sec = 0;
+		pd->required_select_timeout.tv_usec = DPDK_DEF_MIN_SLEEP_MS*1000;
+		p->required_select_timeout = &pd->required_select_timeout;
+		ret = 0; // OK
+	}while(0);
+
+	if (ret <= PCAP_ERROR) // all kinds of error code
+	{
+		pcap_cleanup_live_common(p);
+	}else{
+		rte_eth_dev_get_name_by_port(portid,pd->pci_addr);
+		RTE_LOG(INFO, USER1,"Port %d device: %s, MAC:%s, PCI:%s\n", portid, p->opt.device, pd->mac_addr, pd->pci_addr);
+		RTE_LOG(INFO, USER1,"Port %d Link Up. Speed %u Mbps - %s\n",
+							portid, link.link_speed,
+					(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+						("full-duplex") : ("half-duplex\n"));
+	}
+	return ret;
+}
+
+// device name for dpdk should be in the form as dpdk:number, such as dpdk:0
+pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours)
+{
+	pcap_t *p=NULL;
+	*is_ours = 0;
+
+	*is_ours = !strncmp(device, "dpdk:", 5);
+	if (! *is_ours)
+		return NULL;
+	//memset will happen
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dpdk);
+
+	if (p == NULL)
+		return NULL;
+	p->activate_op = pcap_dpdk_activate;
+	return p;
+}
+
+int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf)
+{
+	int ret=0;
+	unsigned int nb_ports = 0;
+	char dpdk_name[DPDK_DEV_NAME_MAX];
+	char dpdk_desc[DPDK_DEV_DESC_MAX];
+	ETHER_ADDR_TYPE eth_addr;
+	char mac_addr[DPDK_MAC_ADDR_SIZE];
+	char pci_addr[DPDK_PCI_ADDR_SIZE];
+	do{
+		// init EAL; return "DPDK not available" if we
+		// have insufficient permission
+		char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
+		ret = dpdk_pre_init(dpdk_pre_init_errbuf, 1);
+		if (ret < 0)
+		{
+			// This returns a negative value on an error.
+			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "Can't look for DPDK devices: %s",
+			    dpdk_pre_init_errbuf);
+			ret = PCAP_ERROR;
+			break;
+		}
+		if (ret == 0)
+		{
+			// This means DPDK isn't available on this machine.
+			// That just means "don't return any devices".
+			break;
+		}
+		nb_ports = rte_eth_dev_count_avail();
+		if (nb_ports == 0)
+		{
+			// That just means "don't return any devices".
+			ret = 0;
+			break;
+		}
+		for (unsigned int i=0; i<nb_ports; i++){
+			snprintf(dpdk_name, DPDK_DEV_NAME_MAX-1,
+			    "%s%u", DPDK_PREFIX, i);
+			// mac addr
+			rte_eth_macaddr_get(i, &eth_addr);
+			eth_addr_str(&eth_addr,mac_addr,DPDK_MAC_ADDR_SIZE);
+			// PCI addr
+			rte_eth_dev_get_name_by_port(i,pci_addr);
+			snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr);
+			if (add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){
+				ret = PCAP_ERROR;
+				break;
+			}
+		}
+	}while(0);
+	return ret;
+}
+
+#ifdef DPDK_ONLY
+/*
+ * This libpcap build supports only DPDK, not regular network interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just DPDK interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
+{
+	return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+	snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	    "This version of libpcap only supports DPDK");
+	return NULL;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+	return (PCAP_VERSION_STRING " (DPDK-only)");
+}
+#endif
diff --git a/pcap-dpdk.h b/pcap-dpdk.h
new file mode 100644
index 0000000..b759b7f
--- /dev/null
+++ b/pcap-dpdk.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 jingle YANG. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+pcap_t *pcap_dpdk_create(const char *, char *, int *);
+int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/pcap-enet.c b/pcap-enet.c
index cd8cdbb..6f0512f 100644
--- a/pcap-enet.c
+++ b/pcap-enet.c
@@ -75,7 +75,7 @@
 			ph = (struct packet_header *)bp;
 			caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
 .th_wirelen ;
-			if (bpf_filter(fcode, (char *)ph->packet,
+			if (pcap_filter(fcode, (char *)ph->packet,
 						ph->tap.th_wirelen, caplen)) {
 				if (cnt >= 0 && --cnt < 0)
 					goto out;
@@ -89,7 +89,7 @@
 		}
 #else	/* !IBMRTPC */
 		caplen = cc > snaplen ? snaplen : cc ;
-		if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
+		if (pcap_filter(fcode, buf.hdr.packet, cc, caplen)) {
 			if (cnt >= 0 && --cnt < 0)
 				goto out;
 			(*printit)(buf.hdr.packet, &tv, cc, caplen);
diff --git a/pcap-filter.manmisc b/pcap-filter.manmisc
deleted file mode 100644
index 3548691..0000000
--- a/pcap-filter.manmisc
+++ /dev/null
@@ -1,1050 +0,0 @@
-.\" 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 "5 November 2017"
-.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 numerical MAC address of the
-form "xx:xx:xx:xx:xx:xx", "xx.xx.xx.xx.xx.xx", "xx-xx-xx-xx-xx-xx",
-"xxxx.xxxx.xxxx", "xxxxxxxxxxxx", or various mixes of ':', '.', and '-',
-where each "x" is a hex digit (0-9, a-f, or A-F).
-.IP "\fBether src \fIehost\fP"
-True if the Ethernet source address is \fIehost\fP.
-.IP "\fBether host \fIehost\fP"
-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), \fBicmp6type (ICMP v6 type field)
-\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMP v6 code field), and
-\fBtcpflags\fP (TCP flags field).
-
-The following ICMP type field values are available: \fBicmp-echoreply\fP,
-\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
-\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 ICMPv6 type fields are available: \fBicmp6-echo\fP,
-\fBicmp6-echoreply\fP, \fBicmp6-multicastlistenerquery\fP,
-\fBicmp6-multicastlistenerreportv1\fP, \fBicmp6-multicastlistenerdone\fP,
-\fBicmp6-routersolicit\fP, \fBicmp6-routeradvert\fP,
-\fBicmp6-neighborsolicit\fP, \fBicmp6-neighboradvert\fP, \fBicmp6-redirect\fP,
-\fBicmp6-routerrenum\fP, \fBicmp6-nodeinformationquery\fP,
-\fBicmp6-nodeinformationresponse\fP, \fBicmp6-ineighbordiscoverysolicit\fP,
-\fBicmp6-ineighbordiscoveryadvert\fP, \fBicmp6-multicastlistenerreportv2\fP,
-\fBicmp6-homeagentdiscoveryrequest\fP, \fBicmp6-homeagentdiscoveryreply\fP,
-\fBicmp6-mobileprefixsolicit\fP, \fBicmp6-mobileprefixadvert\fP,
-\fBicmp6-certpathsolicit\fP, \fBicmp6-certpathadvert\fP,
-\fBicmp6-multicastrouteradvert\fP, \fBicmp6-multicastroutersolicit\fP,
-\fBicmp6-multicastrouterterm\fP.
-
-The following TCP flags field values are available: \fBtcp-fin\fP,
-\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
-\fBtcp-ack\fP, \fBtcp-urg\fP, \fBtcp-ece\fP,
-\fBtcp-cwr\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
-To report a security issue please send an e-mail to security@tcpdump.org.
-.LP
-To report bugs and other problems, contribute patches, request a
-feature, provide generic feedback etc please see the file
-.I CONTRIBUTING
-in the libpcap source tree root.
-.LP
-Filter expressions on fields other than those in Token Ring headers will
-not correctly handle source-routed Token Ring packets.
-.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 3232f7e..e0f883d 100644
--- a/pcap-filter.manmisc.in
+++ b/pcap-filter.manmisc.in
@@ -18,22 +18,22 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-FILTER @MAN_MISC_INFO@ "5 November 2017"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "2 September 2020"
 .SH NAME
 pcap-filter \- packet filter syntax
 .br
 .ad
 .SH DESCRIPTION
 .LP
-.B pcap_compile()
+.BR 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() ,
+.BR pcap_loop (3PCAP),
+.BR pcap_dispatch (3PCAP),
+.BR pcap_next (3PCAP),
 or
-.BR pcap_next_ex() .
+.BR pcap_next_ex (3PCAP).
 .LP
 The \fIfilter expression\fP consists of one or more
 .IR primitives .
@@ -47,11 +47,11 @@
 qualifiers say what kind of thing the id name or number refers to.
 Possible types are
 .BR host ,
-.B net ,
+.BR net ,
 .B port
 and
 .BR portrange .
-E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+E.g., `\fBhost\fP foo', `\fBnet\fP 128.3', `\fBport\fP 20', `\fBportrange\fP 6000-6008'.
 If there is no type
 qualifier,
 .B host
@@ -72,11 +72,9 @@
 .BR addr3 ,
 and
 .BR addr4 .
-E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+E.g., `\fBsrc\fP foo', `\fBdst net\fP 128.3', `\fBsrc or dst port\fP ftp-data'.
 If
-there is no dir qualifier,
-.B "src or dst"
-is assumed.
+there is no dir qualifier, `\fBsrc or dst\fP' is assumed.
 The
 .BR ra ,
 .BR ta ,
@@ -86,12 +84,6 @@
 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.
@@ -109,25 +101,26 @@
 .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'.
+E.g., `\fBether src\fP foo', `\fBarp net\fP 128.3', `\fBtcp port\fP 21',
+`\fBudp portrange\fP 7000-7009', `\fBwlan addr2\fP 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'.
+E.g., `\fBsrc\fP foo' means `\fB(ip or arp or rarp) src\fP foo'
+(except the latter is not legal syntax), `\fBnet\fP bar' means `\fB(ip or
+arp or rarp) net\fP bar' and `\fBport\fP 53' means `\fB(tcp or udp)
+port\fP 53'.
 .LP
-[`fddi' is actually an alias for `ether'; the parser treats them
+[\fBfddi\fP is actually an alias for \fBether\fP; the parser treats them
 identically as meaning ``the data link level used on the specified
-network interface.''  FDDI headers contain Ethernet-like source
+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
+Similarly, \fBtr\fP and \fBwlan\fP are aliases for \fBether\fP; 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
@@ -147,12 +140,13 @@
 .B or
 and
 .B not
+(or equivalently: `\fB&&\fP', `\fB||\fP' and `\fB!\fP' respectively)
 to combine primitives.
-E.g., `host foo and not port ftp and not port ftp-data'.
+E.g., `\fBhost\fP foo \fBand not port\fP ftp \fBand not port\fP 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'.
+`\fBtcp dst port\fP ftp \fBor\fP ftp-data \fBor\fP domain' is exactly the same as
+`\fBtcp dst port\fP ftp \fBor tcp dst port\fP ftp-data \fBor tcp dst port\fP domain'.
 .LP
 Allowable primitives are:
 .IP "\fBdst host \fIhost\fR"
@@ -173,10 +167,10 @@
 which is equivalent to:
 .in +.5i
 .nf
-\fBether proto \fI\\ip\fB and host \fIhost\fR
+\fBether proto \\ip and host \fIhost\fR
 .fi
 .in -.5i
-If \fIhost\fR is a name with multiple IP addresses, each address will
+If \fIhost\fR is a name with multiple IPv4 addresses, each address will
 be checked for a match.
 .IP "\fBether dst \fIehost\fP"
 True if the Ethernet destination address is \fIehost\fP.
@@ -234,24 +228,24 @@
 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
+True if the packet is IPv4 TCP, IPv4 UDP, IPv6 TCP or IPv6 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)
+.BR tcp (4P)
 and
-.IR udp (4P)).
+.BR 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
+only the port number is checked (e.g., `\fBdst port\fR 513' 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
+.IP "\fBdst portrange \fIport1-port2\fR"
+True if the packet is IPv4 TCP, IPv4 UDP, IPv6 TCP or IPv6 UDP and has a
 destination port value between \fIport1\fP and \fIport2\fP.
 .I port1
 and
@@ -260,10 +254,10 @@
 .I port
 parameter for
 .BR port .
-.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+.IP "\fBsrc portrange \fIport1-port2\fR"
 True if the packet has a source port value between \fIport1\fP and
 \fIport2\fP.
-.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+.IP "\fBportrange \fIport1-port2\fR"
 True if either the source or destination port of the packet is between
 \fIport1\fP and \fIport2\fP.
 .IP
@@ -274,13 +268,13 @@
 \fBtcp src port \fIport\fR
 .fi
 .in -.5i
-which matches only tcp packets whose source port is \fIport\fP.
+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.
+\fBlen <= \fIlength\fP
 .fi
 .in -.5i
 .IP "\fBgreater \fIlength\fR"
@@ -288,12 +282,12 @@
 This is equivalent to:
 .in +.5i
 .nf
-\fBlen >= \fIlength\fP.
+\fBlen >= \fIlength\fP
 .fi
 .in -.5i
 .IP "\fBip proto \fIprotocol\fR"
 True if the packet is an IPv4 packet (see
-.IR ip (4P))
+.BR 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,
@@ -312,10 +306,10 @@
 Abbreviations for:
 .in +.5i
 .nf
-\fBproto \fIp\fR\fB
+\fBproto \\\fIprotocol\fR\fB
 .fi
 .in -.5i
-where \fIp\fR is one of the above protocols.
+where \fIprotocol\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
@@ -323,7 +317,7 @@
 For example,
 .in +.5i
 .nf
-\fBip6 protochain 6\fR
+\fBip6 protochain\fR 6
 .fi
 .in -.5i
 matches any IPv6 packet with TCP protocol header in the protocol header chain.
@@ -342,7 +336,7 @@
 header chain.
 .IP "\fBether broadcast\fR"
 True if the packet is an Ethernet broadcast packet.
-The \fIether\fP
+The \fBether\fP
 keyword is optional.
 .IP "\fBip broadcast\fR"
 True if the packet is an IPv4 broadcast packet.
@@ -359,7 +353,7 @@
 True if the packet is an Ethernet multicast packet.
 The \fBether\fP
 keyword is optional.
-This is shorthand for `\fBether[0] & 1 != 0\fP'.
+This is shorthand for `\fBether[\fP0\fB] & \fP1\fB != \fP0'.
 .IP "\fBip multicast\fR"
 True if the packet is an IPv4 multicast packet.
 .IP "\fBip6 multicast\fR"
@@ -367,15 +361,15 @@
 .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
+\fBaarp\fP, \fBarp\fP, \fBatalk\fP, \fBdecnet\fP, \fBip\fP, \fBip6\fP,
+\fBipx\fP, \fBiso\fP, \fBlat\fP, \fBloopback\fP, \fBmopdl\fP, \fBmoprc\fP, \fBnetbeui\fP,
+\fBrarp\fP, \fBsca\fP or \fBstp\fP.
+Note these identifiers (except \fBloopback\fP) 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
+[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.
@@ -425,33 +419,33 @@
 Abbreviations for:
 .in +.5i
 .nf
-\fBether proto \fIp\fR
+\fBether proto \\\fIprotocol\fR
 .fi
 .in -.5i
-where \fIp\fR is one of the above protocols.
+where \fIprotocol\fR is one of the above protocols.
 .IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
 Abbreviations for:
 .in +.5i
 .nf
-\fBether proto \fIp\fR
+\fBether proto \\\fIprotocol\fR
 .fi
 .in -.5i
-where \fIp\fR is one of the above protocols.
+where \fIprotocol\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
+True if the DECnet source address is
 .IR host ,
-which may be an address of the form ``10.123'', or a DECNET 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.]
+[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
+True if the DECnet destination address is
 .IR host .
 .IP "\fBdecnet host \fIhost\fR"
-True if either the DECNET source or destination address is
+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:
@@ -466,9 +460,7 @@
 FDDI packets (no check is done for LLC frames);
 .IP
 LLC-encapsulated ATM packets, for SunATM on Solaris.
-.IP
-
-.IP "\fBllc\fP \Fitype\fR"
+.IP "\fBllc\fP \fItype\fR"
 True if the packet has an 802.2 LLC header and has the specified
 .IR type .
 .I type
@@ -514,6 +506,16 @@
 \fBfrmr\fR
 Frame Reject (FRMR) U PDUs
 .RE
+.IP \fBinbound\fP
+Packet was received by the host performing the capture rather than being
+sent by that host.  This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP \fBoutbound\fP
+Packet was sent by the host performing the capture rather than being
+received by that host.  This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
 .IP "\fBifname \fIinterface\fR"
 True if the packet was logged as coming from the specified interface (applies
 only to packets logged by OpenBSD's or FreeBSD's
@@ -666,51 +668,51 @@
 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
+If the optional \fIvlan_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
+Note that the first \fBvlan\fR keyword encountered in an expression
+changes the decoding offsets for the remainder of the expression on
+the assumption that the packet is a VLAN packet.  The `\fBvlan
+\fI[vlan_id]\fR` keyword may be used more than once, to filter on VLAN
+hierarchies.  Each use of that keyword increments the filter offsets
 by 4.
 .IP
 For example:
 .in +.5i
 .nf
-\fBvlan 100 && vlan 200\fR
+\fBvlan\fP 100 \fB&& vlan\fR 200
 .fi
 .in -.5i
 filters on VLAN 200 encapsulated within VLAN 100, and
 .in +.5i
 .nf
-\fBvlan && vlan 300 && ip\fR
+\fBvlan && vlan \fP300 \fB&& ip\fR
 .fi
 .in -.5i
-filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+filters IPv4 protocol 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
+If the optional \fIlabel_num\fR is specified, only true if 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
+Note that the first \fBmpls\fR keyword encountered in an expression
+changes the decoding offsets for the remainder of the expression 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
+`\fBmpls \fI[label_num]\fR` keyword may be used more than once, to
+filter on MPLS hierarchies.  Each use of that keyword increments the
 filter offsets by 4.
 .IP
 For example:
 .in +.5i
 .nf
-\fBmpls 100000 && mpls 1024\fR
+\fBmpls\fP 100000 \fB&& mpls\fR 1024
 .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
+\fBmpls && mpls\fP 1024 \fB&& host\fR 192.9.200.1
 .fi
 .in -.5i
 filters packets to or from 192.9.200.1 with an inner label of 1024 and
@@ -721,34 +723,34 @@
 .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
+If the optional \fIsession_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
+Note that the first \fBpppoes\fR keyword encountered in an expression
+changes the decoding offsets for the remainder of the expression on
 the assumption that the packet is a PPPoE session packet.
 .IP
 For example:
 .in +.5i
 .nf
-\fBpppoes 0x27 && ip\fR
+\fBpppoes\fP 0x27 \fB&& ip\fR
 .fi
 .in -.5i
-filters IPv4 protocols encapsulated in PPPoE session id 0x27.
+filters IPv4 protocol 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
+True if the packet is a Geneve packet (UDP port 6081). If the optional \fIvni\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.
+an expression, it changes the decoding offsets for the remainder of
+the expression on the assumption that the packet is a Geneve packet.
 .IP
 For example:
 .in +.5i
 .nf
-\fBgeneve 0xb && ip\fR
+\fBgeneve\fP 0xb \fB&& 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
+filters IPv4 protocol encapsulated in Geneve with VNI 0xb. This will
+match both IPv4 directly encapsulated in Geneve as well as IPv4 contained
 inside an Ethernet frame.
 .IP "\fBiso proto \fIprotocol\fR"
 True if the packet is an OSI packet of protocol type \fIprotocol\fP.
@@ -758,10 +760,10 @@
 Abbreviations for:
 .in +.5i
 .nf
-\fBiso proto \fIp\fR
+\fBiso proto \\\fIprotocol\fR
 .fi
 .in -.5i
-where \fIp\fR is one of the above protocols.
+where \fIprotocol\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"
@@ -775,8 +777,8 @@
 .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
+Note that the first \fBlane\fR keyword encountered in an expression
+changes the tests done in the remainder of the expression
 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
@@ -839,7 +841,7 @@
 (\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
+Note that \fBtcp\fR, \fBudp\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.
@@ -848,24 +850,24 @@
 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'
+For example, `\fBether[\fP0\fB] &\fP 1 \fB!=\fP 0' catches all multicast traffic.
+The expression `\fBip[\fP0\fB] &\fP 0xf \fB!=\fP 5'
 catches all IPv4 packets with options.
 The expression
-`\fBip[6:2] & 0x1fff = 0\fP'
+`\fBip[\fP6:2\fB] &\fP 0x1fff \fB=\fP 0'
 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
+For instance, \fBtcp[\fP0\fB]\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), \fBicmp6type (ICMP v6 type field)
-\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMP v6 code field), and
+available: \fBicmptype\fP (ICMP type field), \fBicmp6type\fP (ICMPv6 type field),
+\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMPv6 code field) and
 \fBtcpflags\fP (TCP flags field).
 
 The following ICMP type field values are available: \fBicmp-echoreply\fP,
@@ -875,7 +877,9 @@
 \fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
 \fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
 
-The following ICMPv6 type fields are available: \fBicmp6-echo\fP,
+The following ICMPv6 type fields are available: \fBicmp6-destinationrunreach\fP,
+\fBicmp6-packettoobig\fP, \fBicmp6-timeexceeded\fP,
+\fBicmp6-parameterproblem\fP, \fBicmp6-echo\fP,
 \fBicmp6-echoreply\fP, \fBicmp6-multicastlistenerquery\fP,
 \fBicmp6-multicastlistenerreportv1\fP, \fBicmp6-multicastlistenerdone\fP,
 \fBicmp6-routersolicit\fP, \fBicmp6-routeradvert\fP,
@@ -904,7 +908,7 @@
 .IP
 Alternation (`\fB||\fP' or `\fBor\fP').
 .LP
-Negation has highest precedence.
+Negation has the highest precedence.
 Alternation and concatenation have equal precedence and associate
 left to right.
 Note that explicit \fBand\fR tokens, not juxtaposition,
@@ -915,67 +919,64 @@
 For example,
 .in +.5i
 .nf
-\fBnot host vs and ace\fR
+\fBnot host\fP vs \fBand\fR ace
 .fi
 .in -.5i
 is short for
 .in +.5i
 .nf
-\fBnot host vs and host ace\fR
+\fBnot host\fP vs \fBand host\fR ace
 .fi
 .in -.5i
 which should not be confused with
 .in +.5i
 .nf
-\fBnot ( host vs or ace )\fR
+\fBnot (host \fPvs\fB or \fPace\fB)\fR
 .fi
 .in -.5i
 .SH EXAMPLES
 .LP
-To select all packets arriving at or departing from \fIsundown\fP:
+To select all packets arriving at or departing from `sundown':
 .RS
 .nf
-\fBhost sundown\fP
+\fBhost\fP sundown
 .fi
 .RE
 .LP
-To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+To select traffic between `helios' and either `hot' or `ace':
 .RS
 .nf
-\fBhost helios and \\( hot or ace \\)\fP
+\fBhost\fP helios \fBand (\fPhot \fBor\fP ace\fB)\fP
 .fi
 .RE
 .LP
-To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+To select all IPv4 packets between `ace' and any host except `helios':
 .RS
 .nf
-\fBip host ace and not helios\fP
+\fBip host\fP ace \fBand not\fP helios
 .fi
 .RE
 .LP
 To select all traffic between local hosts and hosts at Berkeley:
 .RS
 .nf
-.B
-net ucb-ether
+\fBnet\fP ucb-ether
 .fi
 .RE
 .LP
-To select all ftp traffic through internet gateway \fIsnup\fP:
+To select all FTP traffic through Internet gateway `snup':
 .RS
 .nf
-.B
-gateway snup and (port ftp or ftp-data)
+\fBgateway\fP snup \fBand (port\fP ftp \fBor\fP ftp-data\fB)\fP
 .fi
 .RE
 .LP
-To select traffic neither sourced from nor destined for local hosts
+To select IPv4 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
+\fBip and not net \fPlocalnet
 .fi
 .RE
 .LP
@@ -983,8 +984,17 @@
 TCP conversation that involves a non-local host.
 .RS
 .nf
+\fBtcp[tcpflags] & (tcp-syn|tcp-fin) !=\fP 0 \fBand not src and dst net\fP localnet
+.fi
+.RE
+.LP
+To select the TCP packets with flags RST and ACK both set.
+(i.e. select only the RST and ACK flags in the flags field, and if the result
+is "RST and ACK both set", match)
+.RS
+.nf
 .B
-tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+tcp[tcpflags] & (tcp-rst|tcp-ack) == (tcp-rst|tcp-ack)
 .fi
 .RE
 .LP
@@ -993,26 +1003,23 @@
 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)
+\fBtcp port\fP 80 \fBand (((ip[\fP2:2\fB] - ((ip[\fP0\fB]&\fP0xf\fB)<<\fP2\fB)) - ((tcp[\fP12\fB]&\fP0xf0\fB)>>\fP2\fB)) != \fP0\fB)
 .fi
 .RE
 .LP
-To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+To select IPv4 packets longer than 576 bytes sent through gateway `snup':
 .RS
 .nf
-.B
-gateway snup and ip[2:2] > 576
+\fBgateway\fP snup \fBand ip[\fP2:2\fB] >\fP 576
 .fi
 .RE
 .LP
-To select IP broadcast or multicast packets that were
+To select IPv4 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
+\fBether[\fP0\fB] &\fP 1 \fB=\fP 0 \fBand ip[\fP16\fB] >=\fP 224
 .fi
 .RE
 .LP
@@ -1022,16 +1029,18 @@
 .nf
 .B
 icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.B
+icmp6[icmp6type] != icmp6-echo and icmp6[icmp6type] != icmp6-echoreply
 .fi
 .RE
 .SH "SEE ALSO"
-pcap(3PCAP)
+.BR pcap (3PCAP)
 .SH BUGS
 To report a security issue please send an e-mail to security@tcpdump.org.
 .LP
 To report bugs and other problems, contribute patches, request a
 feature, provide generic feedback etc please see the file
-.I CONTRIBUTING
+.I CONTRIBUTING.md
 in the libpcap source tree root.
 .LP
 Filter expressions on fields other than those in Token Ring headers will
@@ -1040,10 +1049,11 @@
 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"
+`\fBip6 proto\fP'
 should chase header chain, but at this moment it does not.
-.BR "ip6 protochain"
-is supplied for this behavior.
+`\fBip6 protochain\fP'
+is supplied for this behavior.  For example, to match IPv6 fragments:
+`\fBip6 protochain\fP 44'
 .LP
 Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
 does not work against IPv6 packets.
diff --git a/pcap-haiku.cpp b/pcap-haiku.cpp
new file mode 100644
index 0000000..701cac3
--- /dev/null
+++ b/pcap-haiku.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *		Axel Dörfler, axeld@pinc-software.de
+ *		James Woodcock
+ */
+
+
+#include "config.h"
+#include "pcap-int.h"
+
+#include <OS.h>
+
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * Private data for capturing on Haiku sockets.
+ */
+struct pcap_haiku {
+	struct pcap_stat	stat;
+	char	*device;	/* device name */
+};
+
+
+bool
+prepare_request(struct ifreq& request, const char* name)
+{
+	if (strlen(name) >= IF_NAMESIZE)
+		return false;
+
+	strcpy(request.ifr_name, name);
+	return true;
+}
+
+
+static int
+pcap_read_haiku(pcap_t* handle, int maxPackets, pcap_handler callback,
+	u_char* userdata)
+{
+	// Receive a single packet
+
+	struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
+	u_char* buffer = (u_char*)handle->buffer + handle->offset;
+	struct sockaddr_dl from;
+	ssize_t bytesReceived;
+	do {
+		if (handle->break_loop) {
+			// Clear the break loop flag, and return -2 to indicate our
+			// reasoning
+			handle->break_loop = 0;
+			return -2;
+		}
+
+		socklen_t fromLength = sizeof(from);
+		bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC,
+			(struct sockaddr*)&from, &fromLength);
+	} while (bytesReceived < 0 && errno == B_INTERRUPTED);
+
+	if (bytesReceived < 0) {
+		if (errno == B_WOULD_BLOCK) {
+			// there is no packet for us
+			return 0;
+		}
+
+		snprintf(handle->errbuf, sizeof(handle->errbuf),
+			"recvfrom: %s", strerror(errno));
+		return -1;
+	}
+
+	int32 captureLength = bytesReceived;
+	if (captureLength > handle->snapshot)
+		captureLength = handle->snapshot;
+
+	// run the packet filter
+	if (handle->fcode.bf_insns) {
+		if (pcap_filter(handle->fcode.bf_insns, buffer, bytesReceived,
+				captureLength) == 0) {
+			// packet got rejected
+			return 0;
+		}
+	}
+
+	// fill in pcap_header
+	pcap_pkthdr header;
+	header.caplen = captureLength;
+	header.len = bytesReceived;
+	header.ts.tv_usec = system_time() % 1000000;
+	header.ts.tv_sec = system_time() / 1000000;
+	// TODO: get timing from packet!!!
+
+	/* Call the user supplied callback function */
+	callback(userdata, &header, buffer);
+	return 1;
+}
+
+
+static int
+pcap_inject_haiku(pcap_t *handle, const void *buffer, int size)
+{
+	// we don't support injecting packets yet
+	// TODO: use the AF_LINK protocol (we need another socket for this) to
+	// inject the packets
+	strlcpy(handle->errbuf, "Sending packets isn't supported yet",
+		PCAP_ERRBUF_SIZE);
+	return -1;
+}
+
+
+static int
+pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats)
+{
+	struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
+	ifreq request;
+	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
+	if (socket < 0) {
+		return -1;
+	}
+	prepare_request(request, handlep->device);
+	if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) {
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s",
+			strerror(errno));
+		close(socket);
+		return -1;
+	}
+
+	close(socket);
+	handlep->stat.ps_recv += request.ifr_stats.receive.packets;
+	handlep->stat.ps_drop += request.ifr_stats.receive.dropped;
+	*stats = handlep->stat;
+	return 0;
+}
+
+
+static int
+pcap_activate_haiku(pcap_t *handle)
+{
+	struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
+
+	const char* device = handle->opt.device;
+
+	handle->read_op = pcap_read_haiku;
+	handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+	handle->inject_op = pcap_inject_haiku;
+	handle->stats_op = pcap_stats_haiku;
+
+	// use default hooks where possible
+	handle->getnonblock_op = pcap_getnonblock_fd;
+	handle->setnonblock_op = pcap_setnonblock_fd;
+
+	handlep->device	= strdup(device);
+	if (handlep->device == NULL) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+			errno, "strdup");
+		return PCAP_ERROR;
+	}
+
+	handle->bufsize = 65536;
+	// TODO: should be determined by interface MTU
+
+	// allocate buffer for monitoring the device
+	handle->buffer = (u_char*)malloc(handle->bufsize);
+	if (handle->buffer == NULL) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+			errno, "buffer malloc");
+		return PCAP_ERROR;
+	}
+
+	handle->offset = 0;
+	handle->linktype = DLT_EN10MB;
+	// TODO: check interface type!
+
+	return 0;
+}
+
+
+//	#pragma mark - pcap API
+
+
+extern "C" pcap_t *
+pcap_create_interface(const char *device, char *errorBuffer)
+{
+	// TODO: handle promiscuous mode!
+
+	// we need a socket to talk to the networking stack
+	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
+	if (socket < 0) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
+			"The networking stack doesn't seem to be available.\n");
+		return NULL;
+	}
+
+	struct ifreq request;
+	if (!prepare_request(request, device)) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
+			"Interface name \"%s\" is too long.", device);
+		close(socket);
+		return NULL;
+	}
+
+	// check if the interface exist
+	if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
+			"Interface \"%s\" does not exist.\n", device);
+		close(socket);
+		return NULL;
+	}
+
+	close(socket);
+	// no longer needed after this point
+
+	// get link level interface for this interface
+
+	socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
+	if (socket < 0) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
+			strerror(errno));
+		return NULL;
+	}
+
+	// start monitoring
+	if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
+			strerror(errno));
+		close(socket);
+		return NULL;
+	}
+
+	pcap_t* handle = PCAP_CREATE_COMMON(errorBuffer, struct pcap_haiku);
+	if (handle == NULL) {
+		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno));
+		close(socket);
+		return NULL;
+	}
+
+	handle->selectable_fd = socket;
+	handle->fd = socket;
+
+	handle->activate_op = pcap_activate_haiku;
+
+	return handle;
+}
+
+static int
+can_be_bound(const char *name)
+{
+	return 1;
+}
+
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+	/* TODO */
+	if (*flags & PCAP_IF_LOOPBACK) {
+		/*
+		 * Loopback devices aren't wireless, and "connected"/
+		 * "disconnected" doesn't apply to them.
+		 */
+		*flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+		return (0);
+	}
+	return (0);
+}
+
+extern "C" int
+pcap_platform_finddevs(pcap_if_list_t* _allDevices, char* errorBuffer)
+{
+	return pcap_findalldevs_interfaces(_allDevices, errorBuffer, can_be_bound,
+		get_if_flags);
+}
diff --git a/pcap-int.h b/pcap-int.h
index 5888df7..3c18dae 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -34,6 +34,8 @@
 #ifndef pcap_int_h
 #define	pcap_int_h
 
+#include <stddef.h>
+
 #include <signal.h>
 
 #include <pcap/pcap.h>
@@ -51,6 +53,33 @@
 extern "C" {
 #endif
 
+/*
+ * If pcap_new_api is set, we disable pcap_lookupdev(), because:
+ *
+ *    it's not thread-safe, and is marked as deprecated, on all
+ *    platforms;
+ *
+ *    on Windows, it may return UTF-16LE strings, which the program
+ *    might then pass to pcap_create() (or to pcap_open_live(), which
+ *    then passes them to pcap_create()), requiring pcap_create() to
+ *    check for UTF-16LE strings using a hack, and that hack 1)
+ *    *cannot* be 100% reliable and 2) runs the risk of going past the
+ *    end of the string.
+ *
+ * We keep it around in legacy mode for compatibility.
+ *
+ * We also disable the aforementioned hack in pcap_create().
+ */
+extern int pcap_new_api;
+
+/*
+ * If pcap_utf_8_mode is set, on Windows we treat strings as UTF-8.
+ *
+ * On UN*Xes, we assume all strings are and should be in UTF-8, regardless
+ * of the setting of this flag.
+ */
+extern int pcap_utf_8_mode;
+
 #ifdef MSDOS
   #include <fcntl.h>
   #include <io.h>
@@ -77,7 +106,7 @@
  *    1) big enough for maximum-size Linux loopback packets (65549)
  *       and some USB packets captured with USBPcap:
  *
- *           http://desowin.org/usbpcap/
+ *           https://desowin.org/usbpcap/
  *
  *       (> 131072, < 262144)
  *
@@ -86,12 +115,29 @@
  *    2) small enough not to cause attempts to allocate huge amounts of
  *       memory; some applications might use the snapshot length in a
  *       savefile header to control the size of the buffer they allocate,
- *       so a size of, say, 2^31-1 might not work well.
+ *       so a size of, say, 2^31-1 might not work well.  (libpcap uses it
+ *       as a hint, but doesn't start out allocating a buffer bigger than
+ *       2 KiB, and grows the buffer as necessary, but not beyond the
+ *       per-linktype maximum snapshot length.  Other code might naively
+ *       use it; we want to avoid writing a too-large snapshot length,
+ *       in order not to cause that code problems.)
  *
  * We don't enforce this in pcap_set_snaplen(), but we use it internally.
  */
 #define MAXIMUM_SNAPLEN		262144
 
+/*
+ * Locale-independent macros for testing character types.
+ * These can be passed any integral value, without worrying about, for
+ * example, sign-extending char values, unlike the C macros.
+ */
+#define PCAP_ISDIGIT(c) \
+	((c) >= '0' && (c) <= '9')
+#define PCAP_ISXDIGIT(c) \
+	(((c) >= '0' && (c) <= '9') || \
+	 ((c) >= 'A' && (c) <= 'F') || \
+	 ((c) >= 'a' && (c) <= 'f'))
+
 struct pcap_opt {
 	char	*device;
 	int	timeout;	/* timeout for buffering */
@@ -118,7 +164,7 @@
 typedef int	(*can_set_rfmon_op_t)(pcap_t *);
 typedef int	(*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
 typedef int	(*next_packet_op_t)(pcap_t *, struct pcap_pkthdr *, u_char **);
-typedef int	(*inject_op_t)(pcap_t *, const void *, size_t);
+typedef int	(*inject_op_t)(pcap_t *, const void *, int);
 typedef void	(*save_current_filter_op_t)(pcap_t *, const char *);
 typedef int	(*setfilter_op_t)(pcap_t *, struct bpf_program *);
 typedef int	(*setdirection_op_t)(pcap_t *, pcap_direction_t);
@@ -126,6 +172,7 @@
 typedef int	(*getnonblock_op_t)(pcap_t *);
 typedef int	(*setnonblock_op_t)(pcap_t *, int);
 typedef int	(*stats_op_t)(pcap_t *, struct pcap_stat *);
+typedef void	(*breakloop_op_t)(pcap_t *);
 #ifdef _WIN32
 typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
 typedef int	(*setbuff_op_t)(pcap_t *, int);
@@ -195,8 +242,7 @@
 
 	int snapshot;
 	int linktype;		/* Network linktype */
-	int linktype_ext;       /* Extended information stored in the linktype field of a file */
-	int tzoff;		/* timezone offset */
+	int linktype_ext;	/* Extended information stored in the linktype field of a file */
 	int offset;		/* offset for proper alignment */
 	int activated;		/* true if the capture is really started */
 	int oldstyle;		/* if we're opening with pcap_open_live() */
@@ -234,7 +280,7 @@
 	 * pcap_t's with a required timeout, and the code must be
 	 * prepared not to see any packets from the attempt.
 	 */
-	struct timeval *required_select_timeout;
+	const struct timeval *required_select_timeout;
 #endif
 
 	/*
@@ -243,6 +289,9 @@
 	struct bpf_program fcode;
 
 	char errbuf[PCAP_ERRBUF_SIZE + 1];
+#ifdef _WIN32
+	char acp_errbuf[PCAP_ERRBUF_SIZE + 1];	/* buffer for local code page error strings */
+#endif
 	int dlt_count;
 	u_int *dlt_list;
 	int tstamp_type_count;
@@ -265,6 +314,7 @@
 	getnonblock_op_t getnonblock_op;
 	setnonblock_op_t setnonblock_op;
 	stats_op_t stats_op;
+	breakloop_op_t breakloop_op;
 
 	/*
 	 * Routine to use as callback for pcap_next()/pcap_next_ex().
@@ -335,7 +385,7 @@
  *
  * Then supply the changes by forking the branch at
  *
- *	https://github.com/the-tcpdump-group/libpcap/issues
+ *	https://github.com/the-tcpdump-group/libpcap/tree/master
  *
  * and issuing a pull request, so that future versions of libpcap and
  * programs that use it (such as tcpdump) will be able to read your new
@@ -345,7 +395,7 @@
 struct pcap_sf_pkthdr {
     struct pcap_timeval ts;	/* time stamp */
     bpf_u_int32 caplen;		/* length of portion present */
-    bpf_u_int32 len;		/* length this packet (off wire) */
+    bpf_u_int32 len;		/* length of this packet (off wire) */
 };
 
 /*
@@ -361,7 +411,7 @@
 struct pcap_sf_patched_pkthdr {
     struct pcap_timeval ts;	/* time stamp */
     bpf_u_int32 caplen;		/* length of portion present */
-    bpf_u_int32 len;		/* length this packet (off wire) */
+    bpf_u_int32 len;		/* length of this packet (off wire) */
     int		index;
     unsigned short protocol;
     unsigned char pkt_type;
@@ -413,12 +463,25 @@
  * by pcap_create routines.
  */
 pcap_t	*pcap_create_interface(const char *, char *);
-pcap_t	*pcap_create_common(char *, size_t);
+
+/*
+ * This wrapper takes an error buffer pointer and a type to use for the
+ * private data, and calls pcap_create_common(), passing it the error
+ * buffer pointer, the size fo the private data type, in bytes, and the
+ * offset of the private data from the beginning of the structure, in
+ * bytes.
+ */
+#define PCAP_CREATE_COMMON(ebuf, type) \
+	pcap_create_common(ebuf, \
+	    sizeof (struct { pcap_t __common; type __private; }), \
+	    offsetof (struct { pcap_t __common; type __private; }, __private))
+pcap_t	*pcap_create_common(char *, size_t, 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_check_activated(pcap_t *);
+void	pcap_breakloop_common(pcap_t *);
 
 /*
  * Internal interfaces for "pcap_findalldevs()".
@@ -467,17 +530,89 @@
 #endif
 
 /*
- * Internal interfaces for "pcap_open_offline()".
+ * Internal interfaces for "pcap_open_offline()" and other savefile
+ * I/O routines.
  *
  * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use
  * by pcap_open_offline routines.
  *
+ * "pcap_adjust_snapshot()" adjusts the snapshot to be non-zero and
+ * fit within an int.
+ *
  * "sf_cleanup()" closes the file handle associated with a pcap_t, if
  * appropriate, and frees all data common to all modules for handling
  * savefile types.
+ *
+ * "charset_fopen()", in UTF-8 mode on Windows, does an fopen() that
+ * treats the pathname as being in UTF-8, rather than the local
+ * code page, on Windows.
  */
-pcap_t	*pcap_open_offline_common(char *ebuf, size_t size);
+
+/*
+ * This wrapper takes an error buffer pointer and a type to use for the
+ * private data, and calls pcap_create_common(), passing it the error
+ * buffer pointer, the size fo the private data type, in bytes, and the
+ * offset of the private data from the beginning of the structure, in
+ * bytes.
+ */
+#define PCAP_OPEN_OFFLINE_COMMON(ebuf, type) \
+	pcap_open_offline_common(ebuf, \
+	    sizeof (struct { pcap_t __common; type __private; }), \
+	    offsetof (struct { pcap_t __common; type __private; }, __private))
+pcap_t	*pcap_open_offline_common(char *ebuf, size_t total_size,
+    size_t private_data);
+bpf_u_int32 pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen);
 void	sf_cleanup(pcap_t *p);
+#ifdef _WIN32
+FILE	*charset_fopen(const char *path, const char *mode);
+#else
+/*
+ * On other OSes, just use Boring Old fopen().
+ */
+#define charset_fopen(path, mode)	fopen((path), (mode))
+#endif
+
+/*
+ * Internal interfaces for loading code at run time.
+ */
+#ifdef _WIN32
+#define pcap_code_handle_t	HMODULE
+#define pcap_funcptr_t		FARPROC
+
+pcap_code_handle_t	pcap_load_code(const char *);
+pcap_funcptr_t		pcap_find_function(pcap_code_handle_t, const char *);
+#endif
+
+/*
+ * Internal interfaces for doing user-mode filtering of packets and
+ * validating filter programs.
+ */
+/*
+ * Auxiliary data, for use when interpreting a filter intended for the
+ * Linux kernel when the kernel rejects the filter (requiring us to
+ * run it in userland).  It contains VLAN tag information.
+ */
+struct bpf_aux_data {
+	u_short vlan_tag_present;
+	u_short vlan_tag;
+};
+
+/*
+ * Filtering routine that takes the auxiliary data as an additional
+ * argument.
+ */
+u_int	pcap_filter_with_aux_data(const struct bpf_insn *,
+    const u_char *, u_int, u_int, const struct bpf_aux_data *);
+
+/*
+ * Filtering routine that doesn't.
+ */
+u_int	pcap_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+
+/*
+ * Routine to validate a BPF program.
+ */
+int	pcap_validate_filter(const struct bpf_insn *, int);
 
 /*
  * Internal interfaces for both "pcap_create()" and routines that
@@ -488,14 +623,20 @@
  */
 void	pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *);
 
-#ifdef _WIN32
-void	pcap_win32_err_to_str(DWORD, char *);
-#endif
-
 int	install_bpf_program(pcap_t *, struct bpf_program *);
 
 int	pcap_strcasecmp(const char *, const char *);
 
+/*
+ * Internal interfaces for pcap_createsrcstr and pcap_parsesrcstr with
+ * the additional bit of information regarding SSL support (rpcap:// vs.
+ * rpcaps://).
+ */
+int	pcap_createsrcstr_ex(char *, int, const char *, const char *,
+    const char *, unsigned char, char *);
+int	pcap_parsesrcstr_ex(const char *, int *, char *, char *,
+    char *, unsigned char *, char *);
+
 #ifdef YYDEBUG
 extern int pcap_debug;
 #endif
diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c
index a0d1669..ef3fdac 100644
--- a/pcap-libdlpi.c
+++ b/pcap-libdlpi.c
@@ -46,7 +46,7 @@
 /* Forwards. */
 static int dlpromiscon(pcap_t *, bpf_u_int32);
 static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
-static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
+static int pcap_inject_libdlpi(pcap_t *, const void *, int);
 static void pcap_libdlpi_err(const char *, const char *, int, char *);
 static void pcap_cleanup_libdlpi(pcap_t *);
 
@@ -80,7 +80,7 @@
 		lwp->lw_err = ENOMEM;
 		return (B_TRUE);
 	}
-	(void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
+	(void) pcap_strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
 
 	if (lwp->lw_list == NULL) {
 		lwp->lw_list = entry;
@@ -427,7 +427,7 @@
 }
 
 static int
-pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
+pcap_inject_libdlpi(pcap_t *p, const void *buf, int size)
 {
 	struct pcap_dlpi *pd = p->priv;
 	int retv;
@@ -468,7 +468,7 @@
 static void
 pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
 {
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+	snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
 	    func, linkname, dlpi_strerror(err));
 }
 
@@ -477,7 +477,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_dlpi);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-linktype.manmisc b/pcap-linktype.manmisc
deleted file mode 100644
index 20f2ea2..0000000
--- a/pcap-linktype.manmisc
+++ /dev/null
@@ -1,48 +0,0 @@
-.\" 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
-https://www.tcpdump.org/linktypes.html.
-.SH SEE ALSO
-pcap_datalink(3PCAP)
diff --git a/pcap-linktype.manmisc.in b/pcap-linktype.manmisc.in
index 68919a7..736a91c 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@ "7 April 2014"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "6 April 2020"
 .SH NAME
 pcap-linktype \- link-layer header types supported by libpcap
 .SH DESCRIPTION
@@ -38,11 +38,11 @@
 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() .
+.BR pcap_datalink ().
 The names for those values begin with
 .BR LINKTYPE_ .
 .PP
 The link-layer header types supported by libpcap are described at
-https://www.tcpdump.org/linktypes.html.
+https://www.tcpdump.org/linktypes.html .
 .SH SEE ALSO
-pcap_datalink(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap-linux.c b/pcap-linux.c
index 49144b6..7481689 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -67,48 +67,6 @@
  * SUCH DAMAGE.
  */
 
-/*
- * Known problems with 2.0[.x] kernels:
- *
- *   - The loopback device gives every packet twice; on 2.2[.x] kernels,
- *     if we use PF_PACKET, we can filter out the transmitted version
- *     of the packet by using data in the "sockaddr_ll" returned by
- *     "recvfrom()", but, on 2.0[.x] kernels, we have to use
- *     PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a
- *     "sockaddr_pkt" which doesn't give us enough information to let
- *     us do that.
- *
- *   - We have to set the interface's IFF_PROMISC flag ourselves, if
- *     we're to run in promiscuous mode, which means we have to turn
- *     it off ourselves when we're done; the kernel doesn't keep track
- *     of how many sockets are listening promiscuously, which means
- *     it won't get turned off automatically when no sockets are
- *     listening promiscuously.  We catch "pcap_close()" and, for
- *     interfaces we put into promiscuous mode, take them out of
- *     promiscuous mode - which isn't necessarily the right thing to
- *     do, if another socket also requested promiscuous mode between
- *     the time when we opened the socket and the time when we close
- *     the socket.
- *
- *   - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()"
- *     return the amount of data that you could have read, rather than
- *     the amount that was returned, so we can't just allocate a buffer
- *     whose size is the snapshot length and pass the snapshot length
- *     as the byte count, and also pass MSG_TRUNC, so that the return
- *     value tells us how long the packet was on the wire.
- *
- *     This means that, if we want to get the actual size of the packet,
- *     so we can return it in the "len" field of the packet header,
- *     we have to read the entire packet, not just the part that fits
- *     within the snapshot length, and thus waste CPU time copying data
- *     from the kernel that our caller won't see.
- *
- *     We have to get the actual size, and supply it in "len", because
- *     otherwise, the IP dissector in tcpdump, for example, will complain
- *     about "truncated-ip", as the packet will appear to have been
- *     shorter, on the wire, than the IP header said it should have been.
- */
-
 
 #define _GNU_SOURCE
 
@@ -119,7 +77,6 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <ctype.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -132,114 +89,56 @@
 #include <linux/if.h>
 #include <linux/if_packet.h>
 #include <linux/sockios.h>
+#include <linux/ethtool.h>
 #include <netinet/in.h>
 #include <linux/if_ether.h>
-#include <net/if_arp.h>
+#include <linux/if_arp.h>
 #include <poll.h>
 #include <dirent.h>
+#include <sys/eventfd.h>
 
 #include "pcap-int.h"
 #include "pcap/sll.h"
 #include "pcap/vlan.h"
 
+#include "diag-control.h"
+
 /*
- * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
- * sockets rather than SOCK_PACKET sockets.
- *
- * To use them, we include <linux/if_packet.h> rather than
- * <netpacket/packet.h>; we do so because
- *
- *	some Linux distributions (e.g., Slackware 4.0) have 2.2 or
- *	later kernels and libc5, and don't provide a <netpacket/packet.h>
- *	file;
- *
- *	not all versions of glibc2 have a <netpacket/packet.h> file
- *	that defines stuff needed for some of the 2.4-or-later-kernel
- *	features, so if the system has a 2.4 or later kernel, we
- *	still can't use those features.
- *
- * We're already including a number of other <linux/XXX.h> headers, and
- * this code is Linux-specific (no other OS has PF_PACKET sockets as
- * a raw packet capture mechanism), so it's not as if you gain any
- * useful portability by using <netpacket/packet.h>
- *
- * XXX - should we just include <linux/if_packet.h> even if PF_PACKET
- * isn't defined?  It only defines one data structure in 2.0.x, so
- * it shouldn't cause any problems.
+ * We require TPACKET_V2 support.
  */
-#ifdef PF_PACKET
-# include <linux/if_packet.h>
+#ifndef TPACKET2_HDRLEN
+#error "Libpcap will only work if TPACKET_V2 is supported; you must build for a 2.6.27 or later kernel"
+#endif
 
- /*
-  * On at least some Linux distributions (for example, Red Hat 5.2),
-  * there's no <netpacket/packet.h> file, but PF_PACKET is defined if
-  * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
-  * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of
-  * the PACKET_xxx stuff.
-  *
-  * So we check whether PACKET_HOST is defined, and assume that we have
-  * PF_PACKET sockets only if it is defined.
-  */
-# ifdef PACKET_HOST
-#  define HAVE_PF_PACKET_SOCKETS
-#  ifdef PACKET_AUXDATA
-#   define HAVE_PACKET_AUXDATA
-#  endif /* PACKET_AUXDATA */
-# endif /* PACKET_HOST */
+/* check for memory mapped access avaibility. We assume every needed
+ * struct is defined if the macro TPACKET_HDRLEN is defined, because it
+ * uses many ring related structs and macros */
+#ifdef TPACKET3_HDRLEN
+# define HAVE_TPACKET3
+#endif /* TPACKET3_HDRLEN */
 
+#define packet_mmap_acquire(pkt) \
+	(__atomic_load_n(&pkt->tp_status, __ATOMIC_ACQUIRE) != TP_STATUS_KERNEL)
+#define packet_mmap_release(pkt) \
+	(__atomic_store_n(&pkt->tp_status, TP_STATUS_KERNEL, __ATOMIC_RELEASE))
+#define packet_mmap_v3_acquire(pkt) \
+	(__atomic_load_n(&pkt->hdr.bh1.block_status, __ATOMIC_ACQUIRE) != TP_STATUS_KERNEL)
+#define packet_mmap_v3_release(pkt) \
+	(__atomic_store_n(&pkt->hdr.bh1.block_status, TP_STATUS_KERNEL, __ATOMIC_RELEASE))
 
- /* check for memory mapped access avaibility. We assume every needed
-  * struct is defined if the macro TPACKET_HDRLEN is defined, because it
-  * uses many ring related structs and macros */
-# ifdef PCAP_SUPPORT_PACKET_RING
-# ifdef TPACKET_HDRLEN
-#  define HAVE_PACKET_RING
-#  ifdef TPACKET3_HDRLEN
-#   define HAVE_TPACKET3
-#  endif /* TPACKET3_HDRLEN */
-#  ifdef TPACKET2_HDRLEN
-#   define HAVE_TPACKET2
-#  else  /* TPACKET2_HDRLEN */
-#   define TPACKET_V1	0    /* Old kernel with only V1, so no TPACKET_Vn defined */
-#  endif /* TPACKET2_HDRLEN */
-# endif /* TPACKET_HDRLEN */
-# endif /* PCAP_SUPPORT_PACKET_RING */
-#endif /* PF_PACKET */
-
-#ifdef SO_ATTACH_FILTER
 #include <linux/types.h>
 #include <linux/filter.h>
-#endif
 
 #ifdef HAVE_LINUX_NET_TSTAMP_H
 #include <linux/net_tstamp.h>
 #endif
 
-#ifdef HAVE_LINUX_SOCKIOS_H
-#include <linux/sockios.h>
-#endif
-
-#ifdef HAVE_LINUX_IF_BONDING_H
+/*
+ * For checking whether a device is a bonding device.
+ */
 #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?
- */
-#ifdef HAVE_LINUX_WIRELESS_H
-#include <linux/wireless.h>
-#endif /* HAVE_LINUX_WIRELESS_H */
-
-/*
  * Got libnl?
  */
 #ifdef HAVE_LIBNL
@@ -252,39 +151,10 @@
 #include <netlink/attr.h>
 #endif /* HAVE_LIBNL */
 
-/*
- * Got ethtool support?
- */
-#ifdef HAVE_LINUX_ETHTOOL_H
-#include <linux/ethtool.h>
-#endif
-
 #ifndef HAVE_SOCKLEN_T
 typedef int		socklen_t;
 #endif
 
-#ifndef MSG_TRUNC
-/*
- * This is being compiled on a system that lacks MSG_TRUNC; define it
- * with the value it has in the 2.2 and later kernels, so that, on
- * those kernels, when we pass it in the flags argument to "recvfrom()"
- * we're passing the right value and thus get the MSG_TRUNC behavior
- * we want.  (We don't get that behavior on 2.0[.x] kernels, because
- * they didn't support MSG_TRUNC.)
- */
-#define MSG_TRUNC	0x20
-#endif
-
-#ifndef SOL_PACKET
-/*
- * This is being compiled on a system that lacks SOL_PACKET; define it
- * with the value it has in the 2.2 and later kernels, so that we can
- * set promiscuous mode in the good modern way rather than the old
- * 2.0-kernel crappy way.
- */
-#define SOL_PACKET	263
-#endif
-
 #define MAX_LINKHEADER_SIZE	256
 
 /*
@@ -295,11 +165,10 @@
 #define BIGGER_THAN_ALL_MTUS	(64*1024)
 
 /*
- * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets.
+ * Private data for capturing on Linux PF_PACKET sockets.
  */
 struct pcap_linux {
-	u_int	packets_read;	/* count of packets read with recvfrom() */
-	long	proc_dropped;	/* packets reported dropped by /proc/net/dev */
+	long long sysfs_dropped; /* packets reported dropped by /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors */
 	struct pcap_stat stat;
 
 	char	*device;	/* device name */
@@ -307,10 +176,10 @@
 	int	blocks_to_filter_in_userland;
 	int	must_do_on_close; /* stuff we must do when we close */
 	int	timeout;	/* timeout for buffering */
-	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 */
+	int	netdown;	/* we got an ENETDOWN and haven't resolved it */
 	bpf_u_int32 oldmode;	/* mode to restore when turning monitor mode off */
 	char	*mondevice;	/* mac80211 monitor device we created */
 	u_char	*mmapbuf;	/* memory-mapped region pointer */
@@ -324,93 +193,54 @@
 	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. */
 #endif
+	int poll_breakloop_fd; /* fd to an eventfd to break from blocking operations */
 };
 
 /*
  * Stuff to do when we close.
  */
-#define MUST_CLEAR_PROMISC	0x00000001	/* clear promiscuous mode */
-#define MUST_CLEAR_RFMON	0x00000002	/* clear rfmon (monitor) mode */
-#define MUST_DELETE_MONIF	0x00000004	/* delete monitor-mode interface */
+#define MUST_CLEAR_RFMON	0x00000001	/* clear rfmon (monitor) mode */
+#define MUST_DELETE_MONIF	0x00000002	/* delete monitor-mode interface */
 
 /*
  * Prototypes for internal functions and methods.
  */
 static int get_if_flags(const char *, bpf_u_int32 *, char *);
-static int is_wifi(int, const char *);
-static void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int);
-#ifdef HAVE_PF_PACKET_SOCKETS
-static short int map_packet_type_to_sll_type(short int);
-#endif
+static int is_wifi(const char *);
+static void map_arphrd_to_dlt(pcap_t *, int, const char *, int);
 static int pcap_activate_linux(pcap_t *);
-static int activate_old(pcap_t *);
-static int activate_new(pcap_t *);
-static int activate_mmap(pcap_t *, int *);
+static int activate_pf_packet(pcap_t *, int);
+static int setup_mmapped(pcap_t *, int *);
 static int pcap_can_set_rfmon_linux(pcap_t *);
-static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
-static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
-static int pcap_inject_linux(pcap_t *, const void *, size_t);
+static int pcap_inject_linux(pcap_t *, const void *, int);
 static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
 static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
 static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
 static int pcap_set_datalink_linux(pcap_t *, int);
 static void pcap_cleanup_linux(pcap_t *);
 
-/*
- * This is what the header structure looks like in a 64-bit kernel;
- * we use this, rather than struct tpacket_hdr, if we're using
- * TPACKET_V1 in 32-bit code running on a 64-bit kernel.
- */
-struct tpacket_hdr_64 {
-	uint64_t	tp_status;
-	unsigned int	tp_len;
-	unsigned int	tp_snaplen;
-	unsigned short	tp_mac;
-	unsigned short	tp_net;
-	unsigned int	tp_sec;
-	unsigned int	tp_usec;
-};
-
-/*
- * We use this internally as the tpacket version for TPACKET_V1 in
- * 32-bit code on a 64-bit kernel.
- */
-#define TPACKET_V1_64 99
-
 union thdr {
-	struct tpacket_hdr		*h1;
-	struct tpacket_hdr_64		*h1_64;
-#ifdef HAVE_TPACKET2
 	struct tpacket2_hdr		*h2;
-#endif
 #ifdef HAVE_TPACKET3
 	struct tpacket_block_desc	*h3;
 #endif
-	void				*raw;
+	u_char				*raw;
 };
 
-#ifdef HAVE_PACKET_RING
-#define RING_GET_FRAME_AT(h, offset) (((union thdr **)h->buffer)[(offset)])
+#define RING_GET_FRAME_AT(h, offset) (((u_char **)h->buffer)[(offset)])
 #define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset)
 
 static void destroy_ring(pcap_t *handle);
 static int create_ring(pcap_t *handle, int *status);
 static int prepare_tpacket_socket(pcap_t *handle);
-static void pcap_cleanup_linux_mmap(pcap_t *);
-static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *);
-static int pcap_read_linux_mmap_v1_64(pcap_t *, int, pcap_handler , u_char *);
-#ifdef HAVE_TPACKET2
 static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
-#endif
 #ifdef HAVE_TPACKET3
 static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
 #endif
-static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
-static int pcap_setnonblock_mmap(pcap_t *p, int nonblock);
-static int pcap_getnonblock_mmap(pcap_t *p);
-static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+static int pcap_setnonblock_linux(pcap_t *p, int nonblock);
+static int pcap_getnonblock_linux(pcap_t *p);
+static void pcap_oneshot_linux(u_char *user, const struct pcap_pkthdr *h,
     const u_char *bytes);
-#endif
 
 /*
  * In pre-3.0 kernels, the tp_vlan_tci field is set to whatever the
@@ -459,34 +289,30 @@
 #endif
 
 /*
+ * Required select timeout if we're polling for an "interface disappeared"
+ * indication - 1 millisecond.
+ */
+static const struct timeval netdown_timeout = {
+	0, 1000		/* 1000 microseconds = 1 millisecond */
+};
+
+/*
  * Wrap some ioctl calls
  */
-#ifdef HAVE_PF_PACKET_SOCKETS
 static int	iface_get_id(int fd, const char *device, char *ebuf);
-#endif /* HAVE_PF_PACKET_SOCKETS */
 static int	iface_get_mtu(int fd, const char *device, char *ebuf);
 static int 	iface_get_arptype(int fd, const char *device, char *ebuf);
-#ifdef HAVE_PF_PACKET_SOCKETS
 static int 	iface_bind(int fd, int ifindex, char *ebuf, int protocol);
-#ifdef IW_MODE_MONITOR
-static int	has_wext(int sock_fd, const char *device, char *ebuf);
-#endif /* IW_MODE_MONITOR */
 static int	enter_rfmon_mode(pcap_t *handle, int sock_fd,
     const char *device);
-#endif /* HAVE_PF_PACKET_SOCKETS */
 #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
 static int	iface_ethtool_get_ts_info(const char *device, pcap_t *handle,
     char *ebuf);
 #endif
-#ifdef HAVE_PACKET_RING
 static int	iface_get_offload(pcap_t *handle);
-#endif
-static int 	iface_bind_old(int fd, const char *device, char *ebuf);
 
-#ifdef SO_ATTACH_FILTER
-static int	fix_program(pcap_t *handle, struct sock_fprog *fcode,
-    int is_mapped);
-static int	fix_offset(struct bpf_insn *p);
+static int	fix_program(pcap_t *handle, struct sock_fprog *fcode);
+static int	fix_offset(pcap_t *handle, struct bpf_insn *p);
 static int	set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode);
 static int	reset_kernel_filter(pcap_t *handle);
 
@@ -494,14 +320,15 @@
 	= BPF_STMT(BPF_RET | BPF_K, 0);
 static struct sock_fprog	total_fcode
 	= { 1, &total_insn };
-#endif /* SO_ATTACH_FILTER */
+
+static int	iface_dsa_get_proto_info(const char *device, pcap_t *handle);
 
 pcap_t *
 pcap_create_interface(const char *device, char *ebuf)
 {
 	pcap_t *handle;
 
-	handle = pcap_create_common(ebuf, sizeof (struct pcap_linux));
+	handle = PCAP_CREATE_COMMON(ebuf, struct pcap_linux);
 	if (handle == NULL)
 		return NULL;
 
@@ -518,7 +345,6 @@
 	}
 #endif
 
-#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
 	/*
 	 * We claim that we support microsecond and nanosecond time
 	 * stamps.
@@ -527,7 +353,6 @@
 	 * microsecond or nanosecond time stamps on arbitrary
 	 * adapters?
 	 */
-	handle->tstamp_precision_count = 2;
 	handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (handle->tstamp_precision_list == NULL) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
@@ -537,16 +362,19 @@
 	}
 	handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
 	handle->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
-#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
+	handle->tstamp_precision_count = 2;
+
+	struct pcap_linux *handlep = handle->priv;
+	handlep->poll_breakloop_fd = eventfd(0, EFD_NONBLOCK);
 
 	return handle;
 }
 
 #ifdef HAVE_LIBNL
 /*
- * If interface {if} is a mac80211 driver, the file
- * /sys/class/net/{if}/phy80211 is a symlink to
- * /sys/class/ieee80211/{phydev}, for some {phydev}.
+ * If interface {if_name} is a mac80211 driver, the file
+ * /sys/class/net/{if_name}/phy80211 is a symlink to
+ * /sys/class/ieee80211/{phydev_name}, for some {phydev_name}.
  *
  * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
  * least, has a "wmaster0" device and a "wlan0" device; the
@@ -557,24 +385,30 @@
  * airmon-ng searches through /sys/class/net for devices named
  * monN, starting with mon0; as soon as one *doesn't* exist,
  * it chooses that as the monitor device name.  If the "iw"
- * command exists, it does "iw dev {if} interface add {monif}
- * type monitor", where {monif} is the monitor device.  It
- * then (sigh) sleeps .1 second, and then configures the
- * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
- * is a file, it writes {mondev}, without a newline, to that file,
- * and again (sigh) sleeps .1 second, and then iwconfig's that
- * device into monitor mode and configures it up.  Otherwise,
- * you can't do monitor mode.
+ * command exists, it does
+ *
+ *    iw dev {if_name} interface add {monif_name} type monitor
+ *
+ * where {monif_name} is the monitor device.  It then (sigh) sleeps
+ * .1 second, and then configures the device up.  Otherwise, if
+ * /sys/class/ieee80211/{phydev_name}/add_iface is a file, it writes
+ * {mondev_name}, without a newline, to that file, and again (sigh)
+ * sleeps .1 second, and then iwconfig's that device into monitor
+ * mode and configures it up.  Otherwise, you can't do monitor mode.
  *
  * All these devices are "glued" together by having the
- * /sys/class/net/{device}/phy80211 links pointing to the same
+ * /sys/class/net/{if_name}/phy80211 links pointing to the same
  * place, so, given a wmaster, wlan, or mon device, you can
  * find the other devices by looking for devices with
  * the same phy80211 link.
  *
  * To turn monitor mode off, delete the monitor interface,
- * either with "iw dev {monif} interface del" or by sending
- * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+ * either with
+ *
+ *    iw dev {monif_name} interface del
+ *
+ * or by sending {monif_name}, with no NL, down
+ * /sys/class/ieee80211/{phydev_name}/remove_iface
  *
  * Note: if you try to create a monitor device named "monN", and
  * there's already a "monN" device, it fails, as least with
@@ -602,7 +436,7 @@
 	 * Generate the path string for the symlink to the physical device.
 	 */
 	if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't generate path name string for /sys/class/net device",
 		    device);
 		return PCAP_ERROR;
@@ -627,39 +461,6 @@
 	return 1;
 }
 
-#ifdef HAVE_LIBNL_SOCKETS
-#define get_nl_errmsg	nl_geterror
-#else
-/* libnl 2.x compatibility code */
-
-#define nl_sock nl_handle
-
-static inline struct nl_handle *
-nl_socket_alloc(void)
-{
-	return nl_handle_alloc();
-}
-
-static inline void
-nl_socket_free(struct nl_handle *h)
-{
-	nl_handle_destroy(h);
-}
-
-#define get_nl_errmsg	strerror
-
-static inline int
-__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache)
-{
-	struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
-	if (!tmp)
-		return -ENOMEM;
-	*cache = tmp;
-	return 0;
-}
-#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
-#endif /* !HAVE_LIBNL_SOCKETS */
-
 struct nl80211_state {
 	struct nl_sock *nl_sock;
 	struct nl_cache *nl_cache;
@@ -673,28 +474,28 @@
 
 	state->nl_sock = nl_socket_alloc();
 	if (!state->nl_sock) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink handle", device);
 		return PCAP_ERROR;
 	}
 
 	if (genl_connect(state->nl_sock)) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate generic netlink cache: %s",
-		    device, get_nl_errmsg(-err));
+		    device, nl_geterror(-err));
 		goto out_handle_destroy;
 	}
 
 	state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
 	if (!state->nl80211) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl80211 not found", device);
 		goto out_cache_free;
 	}
@@ -735,7 +536,7 @@
 
 	msg = nlmsg_alloc();
 	if (!msg) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink msg", device);
 		return PCAP_ERROR;
 	}
@@ -743,16 +544,14 @@
 	genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
 		    0, NL80211_CMD_NEW_INTERFACE, 0);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+DIAG_OFF_NARROWING
 	NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
+DIAG_ON_NARROWING
 	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
 
 	err = nl_send_auto_complete(state->nl_sock, msg);
 	if (err < 0) {
-#if defined HAVE_LIBNL_NLE
 		if (err == -NLE_FAILURE) {
-#else
-		if (err == -ENFILE) {
-#endif
 			/*
 			 * Device not available; our caller should just
 			 * keep trying.  (libnl 2.x maps ENFILE to
@@ -767,20 +566,16 @@
 			 * Real failure, not just "that device is not
 			 * available.
 			 */
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: nl_send_auto_complete failed adding %s interface: %s",
-			    device, mondevice, get_nl_errmsg(-err));
+			    device, mondevice, nl_geterror(-err));
 			nlmsg_free(msg);
 			return PCAP_ERROR;
 		}
 	}
 	err = nl_wait_for_ack(state->nl_sock);
 	if (err < 0) {
-#if defined HAVE_LIBNL_NLE
 		if (err == -NLE_FAILURE) {
-#else
-		if (err == -ENFILE) {
-#endif
 			/*
 			 * Device not available; our caller should just
 			 * keep trying.  (libnl 2.x maps ENFILE to
@@ -795,9 +590,9 @@
 			 * Real failure, not just "that device is not
 			 * available.
 			 */
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: nl_wait_for_ack failed adding %s interface: %s",
-			    device, mondevice, get_nl_errmsg(-err));
+			    device, mondevice, nl_geterror(-err));
 			nlmsg_free(msg);
 			return PCAP_ERROR;
 		}
@@ -824,7 +619,7 @@
 	return 1;
 
 nla_put_failure:
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "%s: nl_put failed adding %s interface",
 	    device, mondevice);
 	nlmsg_free(msg);
@@ -845,7 +640,7 @@
 
 	msg = nlmsg_alloc();
 	if (!msg) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink msg", device);
 		return PCAP_ERROR;
 	}
@@ -856,17 +651,17 @@
 
 	err = nl_send_auto_complete(state->nl_sock, msg);
 	if (err < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl_send_auto_complete failed deleting %s interface: %s",
-		    device, mondevice, get_nl_errmsg(-err));
+		    device, mondevice, nl_geterror(-err));
 		nlmsg_free(msg);
 		return PCAP_ERROR;
 	}
 	err = nl_wait_for_ack(state->nl_sock);
 	if (err < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl_wait_for_ack failed adding %s interface: %s",
-		    device, mondevice, get_nl_errmsg(-err));
+		    device, mondevice, nl_geterror(-err));
 		nlmsg_free(msg);
 		return PCAP_ERROR;
 	}
@@ -878,177 +673,14 @@
 	return 1;
 
 nla_put_failure:
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "%s: nl_put failed deleting %s interface",
 	    device, mondevice);
 	nlmsg_free(msg);
 	return PCAP_ERROR;
 }
-
-static int
-enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
-{
-	struct pcap_linux *handlep = handle->priv;
-	int ret;
-	char phydev_path[PATH_MAX+1];
-	struct nl80211_state nlstate;
-	struct ifreq ifr;
-	u_int n;
-
-	/*
-	 * Is this a mac80211 device?
-	 */
-	ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
-	if (ret < 0)
-		return ret;	/* error */
-	if (ret == 0)
-		return 0;	/* no error, but not mac80211 device */
-
-	/*
-	 * XXX - is this already a monN device?
-	 * If so, we're done.
-	 * Is that determined by old Wireless Extensions ioctls?
-	 */
-
-	/*
-	 * OK, it's apparently a mac80211 device.
-	 * Try to find an unused monN device for it.
-	 */
-	ret = nl80211_init(handle, &nlstate, device);
-	if (ret != 0)
-		return ret;
-	for (n = 0; n < UINT_MAX; n++) {
-		/*
-		 * Try mon{n}.
-		 */
-		char mondevice[3+10+1];	/* mon{UINT_MAX}\0 */
-
-		pcap_snprintf(mondevice, sizeof mondevice, "mon%u", n);
-		ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
-		if (ret == 1) {
-			/*
-			 * Success.  We don't clean up the libnl state
-			 * yet, as we'll be using it later.
-			 */
-			goto added;
-		}
-		if (ret < 0) {
-			/*
-			 * Hard failure.  Just return ret; handle->errbuf
-			 * has already been set.
-			 */
-			nl80211_cleanup(&nlstate);
-			return ret;
-		}
-	}
-
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-	    "%s: No free monN interfaces", device);
-	nl80211_cleanup(&nlstate);
-	return PCAP_ERROR;
-
-added:
-
-#if 0
-	/*
-	 * Sleep for .1 seconds.
-	 */
-	delay.tv_sec = 0;
-	delay.tv_nsec = 500000000;
-	nanosleep(&delay, NULL);
-#endif
-
-	/*
-	 * If we haven't already done so, arrange to have
-	 * "pcap_close_all()" called when we exit.
-	 */
-	if (!pcap_do_addexit(handle)) {
-		/*
-		 * "atexit()" failed; don't put the interface
-		 * in rfmon mode, just give up.
-		 */
-		del_mon_if(handle, sock_fd, &nlstate, device,
-		    handlep->mondevice);
-		nl80211_cleanup(&nlstate);
-		return PCAP_ERROR;
-	}
-
-	/*
-	 * Now configure the monitor interface up.
-	 */
-	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
-	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "%s: Can't get flags for %s", device,
-		    handlep->mondevice);
-		del_mon_if(handle, sock_fd, &nlstate, device,
-		    handlep->mondevice);
-		nl80211_cleanup(&nlstate);
-		return PCAP_ERROR;
-	}
-	ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
-	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "%s: Can't set flags for %s", device,
-		    handlep->mondevice);
-		del_mon_if(handle, sock_fd, &nlstate, device,
-		    handlep->mondevice);
-		nl80211_cleanup(&nlstate);
-		return PCAP_ERROR;
-	}
-
-	/*
-	 * Success.  Clean up the libnl state.
-	 */
-	nl80211_cleanup(&nlstate);
-
-	/*
-	 * Note that we have to delete the monitor device when we close
-	 * the handle.
-	 */
-	handlep->must_do_on_close |= MUST_DELETE_MONIF;
-
-	/*
-	 * Add this to the list of pcaps to close when we exit.
-	 */
-	pcap_add_to_pcaps_to_close(handle);
-
-	return 1;
-}
 #endif /* HAVE_LIBNL */
 
-#ifdef IW_MODE_MONITOR
-/*
- * Bonding devices mishandle unknown ioctls; they fail with ENODEV
- * rather than ENOTSUP, EOPNOTSUPP, or ENOTTY, so Wireless Extensions
- * will fail with ENODEV if we try to do them on a bonding device,
- * making us return a "no such device" indication rather than just
- * saying "no Wireless Extensions".
- *
- * So we check for bonding devices, if we can, before trying those
- * ioctls, by trying a bonding device information query ioctl to see
- * whether it succeeds.
- */
-static int
-is_bonding_device(int fd, const char *device)
-{
-#ifdef BOND_INFO_QUERY_IOCTL
-	struct ifreq ifr;
-	ifbond ifb;
-
-	memset(&ifr, 0, sizeof ifr);
-	strlcpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
-	memset(&ifb, 0, sizeof ifb);
-	ifr.ifr_data = (caddr_t)&ifb;
-	if (ioctl(fd, BOND_INFO_QUERY_IOCTL, &ifr) == 0)
-		return 1;	/* success, so it's a bonding device */
-#endif /* BOND_INFO_QUERY_IOCTL */
-
-	return 0;	/* no, it's not a bonding device */
-}
-#endif /* IW_MODE_MONITOR */
-
 static int pcap_protocol(pcap_t *handle)
 {
 	int protocol;
@@ -1067,10 +699,6 @@
 	char phydev_path[PATH_MAX+1];
 	int ret;
 #endif
-#ifdef IW_MODE_MONITOR
-	int sock_fd;
-	struct iwreq ireq;
-#endif
 
 	if (strcmp(handle->opt.device, "any") == 0) {
 		/*
@@ -1086,11 +714,6 @@
 	 * we'll just check whether the device appears to be a
 	 * mac80211 device and, if so, assume the device supports
 	 * monitor mode.
-	 *
-	 * wmaster devices don't appear to support the Wireless
-	 * Extensions, but we can create a mon device for a
-	 * wmaster device, so we don't bother checking whether
-	 * a mac80211 device supports the Wireless Extensions.
 	 */
 	ret = get_mac80211_phydev(handle, handle->opt.device, phydev_path,
 	    PATH_MAX);
@@ -1100,184 +723,69 @@
 		return 1;	/* mac80211 device */
 #endif
 
-#ifdef IW_MODE_MONITOR
-	/*
-	 * Bleah.  There doesn't appear to be an ioctl to use to ask
-	 * whether a device supports monitor mode; we'll just do
-	 * SIOCGIWMODE and, if it succeeds, assume the device supports
-	 * monitor mode.
-	 *
-	 * Open a socket on which to attempt to get the mode.
-	 * (We assume that if we have Wireless Extensions support
-	 * we also have PF_PACKET support.)
-	 */
-	sock_fd = socket(PF_PACKET, SOCK_RAW, pcap_protocol(handle));
-	if (sock_fd == -1) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "socket");
-		return PCAP_ERROR;
-	}
-
-	if (is_bonding_device(sock_fd, handle->opt.device)) {
-		/* It's a bonding device, so don't even try. */
-		close(sock_fd);
-		return 0;
-	}
-
-	/*
-	 * Attempt to get the current mode.
-	 */
-	strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device,
-	    sizeof ireq.ifr_ifrn.ifrn_name);
-	if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
-		/*
-		 * Well, we got the mode; assume we can set it.
-		 */
-		close(sock_fd);
-		return 1;
-	}
-	if (errno == ENODEV) {
-		/* The device doesn't even exist. */
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "SIOCGIWMODE failed");
-		close(sock_fd);
-		return PCAP_ERROR_NO_SUCH_DEVICE;
-	}
-	close(sock_fd);
-#endif
 	return 0;
 }
 
 /*
- * Grabs the number of dropped packets by the interface from /proc/net/dev.
+ * Grabs the number of missed packets by the interface from
+ * /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors.
  *
- * XXX - what about /sys/class/net/{interface name}/rx_*?  There are
- * individual devices giving, in ASCII, various rx_ and tx_ statistics.
- *
- * Or can we get them in binary form from netlink?
+ * Compared to /proc/net/dev this avoids counting software drops,
+ * but may be unimplemented and just return 0.
+ * The author has found no straigthforward way to check for support.
  */
-static long int
-linux_if_drops(const char * if_name)
-{
-	char buffer[512];
-	char * bufptr;
-	FILE * file;
-	int field_to_convert = 3, if_name_sz = strlen(if_name);
-	long int dropped_pkts = 0;
+static long long int
+linux_get_stat(const char * if_name, const char * stat) {
+	ssize_t bytes_read;
+	int fd;
+	char buffer[PATH_MAX];
 
-	file = fopen("/proc/net/dev", "r");
-	if (!file)
+	snprintf(buffer, sizeof(buffer), "/sys/class/net/%s/statistics/%s", if_name, stat);
+	fd = open(buffer, O_RDONLY);
+	if (fd == -1)
 		return 0;
 
-	while (!dropped_pkts && fgets( buffer, sizeof(buffer), file ))
-	{
-		/* 	search for 'bytes' -- if its in there, then
-			that means we need to grab the fourth field. otherwise
-			grab the third field. */
-		if (field_to_convert != 4 && strstr(buffer, "bytes"))
-		{
-			field_to_convert = 4;
-			continue;
-		}
+	bytes_read = read(fd, buffer, sizeof(buffer) - 1);
+	close(fd);
+	if (bytes_read == -1)
+		return 0;
+	buffer[bytes_read] = '\0';
 
-		/* find iface and make sure it actually matches -- space before the name and : after it */
-		if ((bufptr = strstr(buffer, if_name)) &&
-			(bufptr == buffer || *(bufptr-1) == ' ') &&
-			*(bufptr + if_name_sz) == ':')
-		{
-			bufptr = bufptr + if_name_sz + 1;
+	return strtoll(buffer, NULL, 10);
+}
 
-			/* grab the nth field from it */
-			while( --field_to_convert && *bufptr != '\0')
-			{
-				while (*bufptr != '\0' && *(bufptr++) == ' ');
-				while (*bufptr != '\0' && *(bufptr++) != ' ');
-			}
-
-			/* get rid of any final spaces */
-			while (*bufptr != '\0' && *bufptr == ' ') bufptr++;
-
-			if (*bufptr != '\0')
-				dropped_pkts = strtol(bufptr, NULL, 10);
-
-			break;
-		}
-	}
-
-	fclose(file);
-	return dropped_pkts;
+static long long int
+linux_if_drops(const char * if_name)
+{
+	long long int missed = linux_get_stat(if_name, "rx_missed_errors");
+	long long int fifo = linux_get_stat(if_name, "rx_fifo_errors");
+	return missed + fifo;
 }
 
 
 /*
- * With older kernels promiscuous mode is kind of interesting because we
- * have to reset the interface before exiting. The problem can't really
- * be solved without some daemon taking care of managing usage counts.
- * If we put the interface into promiscuous mode, we set a flag indicating
- * that we must take it out of that mode when the interface is closed,
- * and, when closing the interface, if that flag is set we take it out
- * of promiscuous mode.
- *
- * Even with newer kernels, we have the same issue with rfmon mode.
+ * Monitor mode is kind of interesting because we have to reset the
+ * interface before exiting. The problem can't really be solved without
+ * some daemon taking care of managing usage counts.  If we put the
+ * interface into monitor mode, we set a flag indicating that we must
+ * take it out of that mode when the interface is closed, and, when
+ * closing the interface, if that flag is set we take it out of monitor
+ * mode.
  */
 
 static void	pcap_cleanup_linux( pcap_t *handle )
 {
 	struct pcap_linux *handlep = handle->priv;
-	struct ifreq	ifr;
 #ifdef HAVE_LIBNL
 	struct nl80211_state nlstate;
 	int ret;
 #endif /* HAVE_LIBNL */
-#ifdef IW_MODE_MONITOR
-	int oldflags;
-	struct iwreq ireq;
-#endif /* IW_MODE_MONITOR */
 
 	if (handlep->must_do_on_close != 0) {
 		/*
 		 * There's something we have to do when closing this
 		 * pcap_t.
 		 */
-		if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) {
-			/*
-			 * We put the interface into promiscuous mode;
-			 * take it out of promiscuous mode.
-			 *
-			 * XXX - if somebody else wants it in promiscuous
-			 * mode, this code cannot know that, so it'll take
-			 * it out of promiscuous mode.  That's not fixable
-			 * in 2.0[.x] kernels.
-			 */
-			memset(&ifr, 0, sizeof(ifr));
-			strlcpy(ifr.ifr_name, handlep->device,
-			    sizeof(ifr.ifr_name));
-			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
-				fprintf(stderr,
-				    "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n"
-				    "Please adjust manually.\n"
-				    "Hint: This can't happen with Linux >= 2.2.0.\n",
-				    handlep->device, strerror(errno));
-			} else {
-				if (ifr.ifr_flags & IFF_PROMISC) {
-					/*
-					 * Promiscuous mode is currently on;
-					 * turn it off.
-					 */
-					ifr.ifr_flags &= ~IFF_PROMISC;
-					if (ioctl(handle->fd, SIOCSIFFLAGS,
-					    &ifr) == -1) {
-						fprintf(stderr,
-						    "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n"
-						    "Please adjust manually.\n"
-						    "Hint: This can't happen with Linux >= 2.2.0.\n",
-						    handlep->device,
-						    strerror(errno));
-					}
-				}
-			}
-		}
-
 #ifdef HAVE_LIBNL
 		if (handlep->must_do_on_close & MUST_DELETE_MONIF) {
 			ret = nl80211_init(handle, &nlstate, handlep->device);
@@ -1295,68 +803,6 @@
 		}
 #endif /* HAVE_LIBNL */
 
-#ifdef IW_MODE_MONITOR
-		if (handlep->must_do_on_close & MUST_CLEAR_RFMON) {
-			/*
-			 * We put the interface into rfmon mode;
-			 * take it out of rfmon mode.
-			 *
-			 * XXX - if somebody else wants it in rfmon
-			 * mode, this code cannot know that, so it'll take
-			 * it out of rfmon mode.
-			 */
-
-			/*
-			 * First, take the interface down if it's up;
-			 * otherwise, we might get EBUSY.
-			 * If we get errors, just drive on and print
-			 * a warning if we can't restore the mode.
-			 */
-			oldflags = 0;
-			memset(&ifr, 0, sizeof(ifr));
-			strlcpy(ifr.ifr_name, handlep->device,
-			    sizeof(ifr.ifr_name));
-			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
-				if (ifr.ifr_flags & IFF_UP) {
-					oldflags = ifr.ifr_flags;
-					ifr.ifr_flags &= ~IFF_UP;
-					if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1)
-						oldflags = 0;	/* didn't set, don't restore */
-				}
-			}
-
-			/*
-			 * Now restore the mode.
-			 */
-			strlcpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
-			    sizeof ireq.ifr_ifrn.ifrn_name);
-			ireq.u.mode = handlep->oldmode;
-			if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
-				/*
-				 * Scientist, you've failed.
-				 */
-				fprintf(stderr,
-				    "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n"
-				    "Please adjust manually.\n",
-				    handlep->device, strerror(errno));
-			}
-
-			/*
-			 * Now bring the interface back up if we brought
-			 * it down.
-			 */
-			if (oldflags != 0) {
-				ifr.ifr_flags = oldflags;
-				if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
-					fprintf(stderr,
-					    "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n"
-					    "Please adjust manually.\n",
-					    handlep->device, strerror(errno));
-				}
-			}
-		}
-#endif /* IW_MODE_MONITOR */
-
 		/*
 		 * Take this pcap out of the list of pcaps for which we
 		 * have to take the interface out of some mode.
@@ -1364,6 +810,19 @@
 		pcap_remove_from_pcaps_to_close(handle);
 	}
 
+	if (handle->fd != -1) {
+		/*
+		 * Destroy the ring buffer (assuming we've set it up),
+		 * and unmap it if it's mapped.
+		 */
+		destroy_ring(handle);
+	}
+
+	if (handlep->oneshot_buffer != NULL) {
+		free(handlep->oneshot_buffer);
+		handlep->oneshot_buffer = NULL;
+	}
+
 	if (handlep->mondevice != NULL) {
 		free(handlep->mondevice);
 		handlep->mondevice = NULL;
@@ -1372,9 +831,49 @@
 		free(handlep->device);
 		handlep->device = NULL;
 	}
+
+	close(handlep->poll_breakloop_fd);
 	pcap_cleanup_live_common(handle);
 }
 
+#ifdef HAVE_TPACKET3
+/*
+ * Some versions of TPACKET_V3 have annoying bugs/misfeatures
+ * around which we have to work.  Determine if we have those
+ * problems or not.
+ * 3.19 is the first release with a fixed version of
+ * TPACKET_V3.  We treat anything before that as
+ * not having a fixed version; that may really mean
+ * it has *no* version.
+ */
+static int has_broken_tpacket_v3(void)
+{
+	struct utsname utsname;
+	const char *release;
+	long major, minor;
+	int matches, verlen;
+
+	/* No version information, assume broken. */
+	if (uname(&utsname) == -1)
+		return 1;
+	release = utsname.release;
+
+	/* A malformed version, ditto. */
+	matches = sscanf(release, "%ld.%ld%n", &major, &minor, &verlen);
+	if (matches != 2)
+		return 1;
+	if (release[verlen] != '.' && release[verlen] != '\0')
+		return 1;
+
+	/* OK, a fixed version. */
+	if (major > 3 || (major == 3 && minor >= 19))
+		return 0;
+
+	/* Too old :( */
+	return 1;
+}
+#endif
+
 /*
  * Set the timeout to be used in poll() with memory-mapped packet capture.
  */
@@ -1382,45 +881,7 @@
 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;
-				}
-			}
-		}
-	}
+	int broken_tpacket_v3 = has_broken_tpacket_v3();
 #endif
 	if (handlep->timeout == 0) {
 #ifdef HAVE_TPACKET3
@@ -1463,11 +924,21 @@
 	}
 }
 
+static void pcap_breakloop_linux(pcap_t *handle)
+{
+	pcap_breakloop_common(handle);
+	struct pcap_linux *handlep = handle->priv;
+
+	uint64_t value = 1;
+	/* XXX - what if this fails? */
+	(void)write(handlep->poll_breakloop_fd, &value, sizeof(value));
+}
+
 /*
  *  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
- *  will be set to promiscous mode (XXX: I think this usage should
+ *  will be set to promiscuous mode (XXX: I think this usage should
  *  be deprecated and functions be added to select that later allow
  *  modification of that values -- Torsten).
  */
@@ -1476,8 +947,10 @@
 {
 	struct pcap_linux *handlep = handle->priv;
 	const char	*device;
+	int		is_any_device;
 	struct ifreq	ifr;
 	int		status = 0;
+	int		status2 = 0;
 	int		ret;
 
 	device = handle->opt.device;
@@ -1509,151 +982,109 @@
 	if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
 		handle->snapshot = MAXIMUM_SNAPLEN;
 
-	handle->inject_op = pcap_inject_linux;
-	handle->setfilter_op = pcap_setfilter_linux;
-	handle->setdirection_op = pcap_setdirection_linux;
-	handle->set_datalink_op = pcap_set_datalink_linux;
-	handle->getnonblock_op = pcap_getnonblock_fd;
-	handle->setnonblock_op = pcap_setnonblock_fd;
-	handle->cleanup_op = pcap_cleanup_linux;
-	handle->read_op = pcap_read_linux;
-	handle->stats_op = pcap_stats_linux;
+	handlep->device	= strdup(device);
+	if (handlep->device == NULL) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "strdup");
+		status = PCAP_ERROR;
+		goto fail;
+	}
 
 	/*
 	 * The "any" device is a special device which causes us not
 	 * to bind to a particular device and thus to look at all
 	 * devices.
 	 */
-	if (strcmp(device, "any") == 0) {
+	is_any_device = (strcmp(device, "any") == 0);
+	if (is_any_device) {
 		if (handle->opt.promisc) {
 			handle->opt.promisc = 0;
 			/* Just a warning. */
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "Promiscuous mode not supported on the \"any\" device");
 			status = PCAP_WARNING_PROMISC_NOTSUP;
 		}
 	}
 
-	handlep->device	= strdup(device);
-	if (handlep->device == NULL) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "strdup");
-		return PCAP_ERROR;
-	}
-
 	/* copy timeout value */
 	handlep->timeout = handle->opt.timeout;
 
 	/*
 	 * If we're in promiscuous mode, then we probably want
 	 * to see when the interface drops packets too, so get an
-	 * initial count from /proc/net/dev
+	 * initial count from
+	 * /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors
 	 */
 	if (handle->opt.promisc)
-		handlep->proc_dropped = linux_if_drops(handlep->device);
+		handlep->sysfs_dropped = linux_if_drops(handlep->device);
 
 	/*
-	 * Current Linux kernels use the protocol family PF_PACKET to
-	 * allow direct access to all packets on the network while
-	 * older kernels had a special socket type SOCK_PACKET to
-	 * implement this feature.
-	 * While this old implementation is kind of obsolete we need
-	 * to be compatible with older kernels for a while so we are
-	 * trying both methods with the newer method preferred.
+	 * If the "any" device is specified, try to open a SOCK_DGRAM.
+	 * Otherwise, open a SOCK_RAW.
 	 */
-	ret = activate_new(handle);
+	ret = activate_pf_packet(handle, is_any_device);
 	if (ret < 0) {
 		/*
-		 * Fatal error with the new way; just fail.
-		 * ret has the error return; if it's PCAP_ERROR,
-		 * handle->errbuf has been set appropriately.
+		 * Fatal error; the return value is the error code,
+		 * and handle->errbuf has been set to an appropriate
+		 * error message.
 		 */
 		status = ret;
 		goto fail;
 	}
-	if (ret == 1) {
-		/*
-		 * Success.
-		 * Try to use memory-mapped access.
-		 */
-		switch (activate_mmap(handle, &status)) {
-
-		case 1:
-			/*
-			 * We succeeded.  status has been
-			 * 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:
-			/*
-			 * Kernel doesn't support it - just continue
-			 * with non-memory-mapped access.
-			 */
-			break;
-
-		case -1:
-			/*
-			 * We failed to set up to use it, or the kernel
-			 * supports it, but we failed to enable it.
-			 * ret has been set to the error status to
-			 * return and, if it's PCAP_ERROR, handle->errbuf
-			 * contains the error message.
-			 */
-			status = ret;
-			goto fail;
-		}
-	}
-	else if (ret == 0) {
-		/* Non-fatal error; try old way */
-		if ((ret = activate_old(handle)) != 1) {
-			/*
-			 * Both methods to open the packet socket failed.
-			 * Tidy up and report our failure (handle->errbuf
-			 * is expected to be set by the functions above).
-			 */
-			status = ret;
-			goto fail;
-		}
-	}
-
 	/*
-	 * We set up the socket, but not with memory-mapped access.
+	 * Success.
+	 * Try to set up memory-mapped access.
 	 */
-	if (handle->opt.buffer_size != 0) {
+	ret = setup_mmapped(handle, &status);
+	if (ret == -1) {
 		/*
-		 * Set the socket buffer size to the specified value.
+		 * We failed to set up to use it, or the
+		 * kernel supports it, but we failed to
+		 * enable it.  status has been set to the
+		 * error status to return and, if it's
+		 * PCAP_ERROR, handle->errbuf contains
+		 * the error message.
 		 */
-		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
-		    &handle->opt.buffer_size,
-		    sizeof(handle->opt.buffer_size)) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
-			status = PCAP_ERROR;
-			goto fail;
-		}
-	}
-
-	/* Allocate the buffer */
-
-	handle->buffer	 = malloc(handle->bufsize + handle->offset);
-	if (!handle->buffer) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "malloc");
-		status = PCAP_ERROR;
 		goto fail;
 	}
 
 	/*
-	 * "handle->fd" is a socket, so "select()" and "poll()"
-	 * should work on it.
+	 * We succeeded.  status has been set to the status to return,
+	 * which might be 0, or might be a PCAP_WARNING_ value.
 	 */
+	/*
+	 * Now that we have activated the mmap ring, we can
+	 * set the correct protocol.
+	 */
+	if ((status2 = iface_bind(handle->fd, handlep->ifindex,
+	    handle->errbuf, pcap_protocol(handle))) != 0) {
+		status = status2;
+		goto fail;
+	}
+
+	handle->inject_op = pcap_inject_linux;
+	handle->setfilter_op = pcap_setfilter_linux;
+	handle->setdirection_op = pcap_setdirection_linux;
+	handle->set_datalink_op = pcap_set_datalink_linux;
+	handle->setnonblock_op = pcap_setnonblock_linux;
+	handle->getnonblock_op = pcap_getnonblock_linux;
+	handle->cleanup_op = pcap_cleanup_linux;
+	handle->stats_op = pcap_stats_linux;
+	handle->breakloop_op = pcap_breakloop_linux;
+
+	switch (handlep->tp_version) {
+
+	case TPACKET_V2:
+		handle->read_op = pcap_read_linux_mmap_v2;
+		break;
+#ifdef HAVE_TPACKET3
+	case TPACKET_V3:
+		handle->read_op = pcap_read_linux_mmap_v3;
+		break;
+#endif
+	}
+	handle->oneshot_callback = pcap_oneshot_linux;
 	handle->selectable_fd = handle->fd;
 
 	return status;
@@ -1663,21 +1094,6 @@
 	return status;
 }
 
-/*
- *  Read at most max_packets from the capture stream and call the callback
- *  for each of them. Returns the number of packets handled or -1 if an
- *  error occured.
- */
-static int
-pcap_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
-{
-	/*
-	 * Currently, on Linux only one packet is delivered per read,
-	 * so we don't loop.
-	 */
-	return pcap_read_packet(handle, callback, user);
-}
-
 static int
 pcap_set_datalink_linux(pcap_t *handle, int dlt)
 {
@@ -1738,412 +1154,83 @@
 }
 
 /*
- *  Read a packet from the socket calling the handler provided by
- *  the user. Returns the number of packets received or -1 if an
- *  error occured.
+ * Check whether the device to which the pcap_t is bound still exists.
+ * We do so by asking what address the socket is bound to, and checking
+ * whether the ifindex in the address is -1, meaning "that device is gone",
+ * or some other value, meaning "that device still exists".
  */
 static int
-pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
+device_still_exists(pcap_t *handle)
 {
-	struct pcap_linux	*handlep = handle->priv;
-	u_char			*bp;
-	int			offset;
-#ifdef HAVE_PF_PACKET_SOCKETS
-	struct sockaddr_ll	from;
-	struct sll_header	*hdrp;
-#else
-	struct sockaddr		from;
-#endif
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
-	struct iovec		iov;
-	struct msghdr		msg;
-	struct cmsghdr		*cmsg;
-	union {
-		struct cmsghdr	cmsg;
-		char		buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
-	} cmsg_buf;
-#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-	socklen_t		fromlen;
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-	int			packet_len, caplen;
-	struct pcap_pkthdr	pcap_header;
-
-        struct bpf_aux_data     aux_data;
-#ifdef HAVE_PF_PACKET_SOCKETS
-	/*
-	 * If this is a cooked device, leave extra room for a
-	 * fake packet header.
-	 */
-	if (handlep->cooked)
-		offset = SLL_HDR_LEN;
-	else
-		offset = 0;
-#else
-	/*
-	 * This system doesn't have PF_PACKET sockets, so it doesn't
-	 * support cooked devices.
-	 */
-	offset = 0;
-#endif
+	struct pcap_linux *handlep = handle->priv;
+	struct sockaddr_ll addr;
+	socklen_t addr_len;
 
 	/*
-	 * Receive a single packet from the kernel.
-	 * We ignore EINTR, as that might just be due to a signal
-	 * being delivered - if the signal should interrupt the
-	 * loop, the signal handler should call pcap_breakloop()
-	 * to set handle->break_loop (we ignore it on other
-	 * platforms as well).
-	 * We also ignore ENETDOWN, so that we can continue to
-	 * capture traffic if the interface goes down and comes
-	 * back up again; comments in the kernel indicate that
-	 * we'll just block waiting for packets if we try to
-	 * receive from a socket that delivered ENETDOWN, and,
-	 * if we're using a memory-mapped buffer, we won't even
-	 * get notified of "network down" events.
+	 * If handlep->ifindex is -1, the socket isn't bound, meaning
+	 * we're capturing on the "any" device; that device never
+	 * disappears.  (It should also never be configured down, so
+	 * we shouldn't even get here, but let's make sure.)
 	 */
-	bp = (u_char *)handle->buffer + handle->offset;
+	if (handlep->ifindex == -1)
+		return (1);	/* it's still here */
 
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
-	msg.msg_name		= &from;
-	msg.msg_namelen		= sizeof(from);
-	msg.msg_iov		= &iov;
-	msg.msg_iovlen		= 1;
-	msg.msg_control		= &cmsg_buf;
-	msg.msg_controllen	= sizeof(cmsg_buf);
-	msg.msg_flags		= 0;
-
-	iov.iov_len		= handle->bufsize - offset;
-	iov.iov_base		= bp + offset;
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-
-	do {
+	/*
+	 * OK, now try to get the address for the socket.
+	 */
+	addr_len = sizeof (addr);
+	if (getsockname(handle->fd, (struct sockaddr *) &addr, &addr_len) == -1) {
 		/*
-		 * Has "pcap_breakloop()" been called?
+		 * Error - report an error and return -1.
 		 */
-		if (handle->break_loop) {
-			/*
-			 * Yes - clear the flag that indicates that it has,
-			 * and return PCAP_ERROR_BREAK as an indication that
-			 * we were told to break out of the loop.
-			 */
-			handle->break_loop = 0;
-			return PCAP_ERROR_BREAK;
-		}
-
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
-		packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
-#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-		fromlen = sizeof(from);
-		packet_len = recvfrom(
-			handle->fd, bp + offset,
-			handle->bufsize - offset, MSG_TRUNC,
-			(struct sockaddr *) &from, &fromlen);
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-	} while (packet_len == -1 && errno == EINTR);
-
-	/* Check if an error occured */
-
-	if (packet_len == -1) {
-		switch (errno) {
-
-		case EAGAIN:
-			return 0;	/* no packet there */
-
-		case 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.
-			 */
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				"The interface went down");
-			return PCAP_ERROR;
-
-		default:
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "recvfrom");
-			return PCAP_ERROR;
-		}
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "getsockname failed");
+		return (-1);
 	}
-
-#ifdef HAVE_PF_PACKET_SOCKETS
-	if (!handlep->sock_packet) {
+	if (addr.sll_ifindex == -1) {
 		/*
-		 * Unfortunately, there is a window between socket() and
-		 * bind() where the kernel may queue packets from any
-		 * interface.  If we're bound to a particular interface,
-		 * discard packets not from that interface.
-		 *
-		 * (If socket filters are supported, we could do the
-		 * same thing we do when changing the filter; however,
-		 * that won't handle packet sockets without socket
-		 * filter support, and it's a bit more complicated.
-		 * It would save some instructions per packet, however.)
+		 * This means the device went away.
 		 */
-		if (handlep->ifindex != -1 &&
-		    from.sll_ifindex != handlep->ifindex)
-			return 0;
-
-		/*
-		 * Do checks based on packet direction.
-		 * We can only do this if we're using PF_PACKET; the
-		 * address returned for SOCK_PACKET is a "sockaddr_pkt"
-		 * which lacks the relevant packet type information.
-		 */
-		if (!linux_check_direction(handle, &from))
-			return 0;
-	}
-#endif
-
-#ifdef HAVE_PF_PACKET_SOCKETS
-	/*
-	 * If this is a cooked device, fill in the fake packet header.
-	 */
-	if (handlep->cooked) {
-		/*
-		 * Add the length of the fake header to the length
-		 * of packet data we read.
-		 */
-		packet_len += SLL_HDR_LEN;
-
-		hdrp = (struct sll_header *)bp;
-		hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype);
-		hdrp->sll_hatype = htons(from.sll_hatype);
-		hdrp->sll_halen = htons(from.sll_halen);
-		memcpy(hdrp->sll_addr, from.sll_addr,
-		    (from.sll_halen > SLL_ADDRLEN) ?
-		      SLL_ADDRLEN :
-		      from.sll_halen);
-		hdrp->sll_protocol = from.sll_protocol;
+		return (0);
 	}
 
 	/*
-	 * Start out with no VLAN information.
+	 * The device presumably just went down.
 	 */
-	aux_data.vlan_tag_present = 0;
-	aux_data.vlan_tag = 0;
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
-	if (handlep->vlan_offset != -1) {
-		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-			struct tpacket_auxdata *aux;
-			unsigned int len;
-			struct vlan_tag *tag;
-
-			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
-			    cmsg->cmsg_level != SOL_PACKET ||
-			    cmsg->cmsg_type != PACKET_AUXDATA) {
-				/*
-				 * This isn't a PACKET_AUXDATA auxiliary
-				 * data item.
-				 */
-				continue;
-			}
-
-			aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
-			if (!VLAN_VALID(aux, aux)) {
-				/*
-				 * There is no VLAN information in the
-				 * auxiliary data.
-				 */
-				continue;
-			}
-
-			len = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len;
-			if (len < (u_int)handlep->vlan_offset)
-				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);
-
-			/*
-			 * Save a flag indicating that we have a VLAN tag,
-			 * and the VLAN TCI, to bpf_aux_data struct for
-			 * use by the BPF filter if we're doing the
-			 * filtering in userland.
-			 */
-			aux_data.vlan_tag_present = 1;
-			aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
-
-			/*
-			 * Add the tag to the packet lengths.
-			 */
-			packet_len += VLAN_TAG_LEN;
-		}
-	}
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
-#endif /* HAVE_PF_PACKET_SOCKETS */
-
-	/*
-	 * XXX: According to the kernel source we should get the real
-	 * packet len if calling recvfrom with MSG_TRUNC set. It does
-	 * not seem to work here :(, but it is supported by this code
-	 * anyway.
-	 * To be honest the code RELIES on that feature so this is really
-	 * broken with 2.2.x kernels.
-	 * I spend a day to figure out what's going on and I found out
-	 * that the following is happening:
-	 *
-	 * The packet comes from a random interface and the packet_rcv
-	 * hook is called with a clone of the packet. That code inserts
-	 * the packet into the receive queue of the packet socket.
-	 * If a filter is attached to that socket that filter is run
-	 * first - and there lies the problem. The default filter always
-	 * cuts the packet at the snaplen:
-	 *
-	 * # tcpdump -d
-	 * (000) ret      #68
-	 *
-	 * So the packet filter cuts down the packet. The recvfrom call
-	 * says "hey, it's only 68 bytes, it fits into the buffer" with
-	 * the result that we don't get the real packet length. This
-	 * is valid at least until kernel 2.2.17pre6.
-	 *
-	 * We currently handle this by making a copy of the filter
-	 * program, fixing all "ret" instructions with non-zero
-	 * operands to have an operand of MAXIMUM_SNAPLEN so that the
-	 * filter doesn't truncate the packet, and supplying that modified
-	 * filter to the kernel.
-	 */
-
-	caplen = packet_len;
-	if (caplen > handle->snapshot)
-		caplen = handle->snapshot;
-
-	/* Run the packet filter if not using kernel filter */
-	if (handlep->filter_in_userland && handle->fcode.bf_insns) {
-		if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp,
-		    packet_len, caplen, &aux_data) == 0) {
-			/* rejected by filter */
-			return 0;
-		}
-	}
-
-	/* Fill in our own header data */
-
-	/* get timestamp for this packet */
-#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
-	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
-		if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMPNS");
-			return PCAP_ERROR;
-		}
-        } else
-#endif
-	{
-		if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMP");
-			return PCAP_ERROR;
-		}
-        }
-
-	pcap_header.caplen	= caplen;
-	pcap_header.len		= packet_len;
-
-	/*
-	 * Count the packet.
-	 *
-	 * Arguably, we should count them before we check the filter,
-	 * as on many other platforms "ps_recv" counts packets
-	 * handed to the filter rather than packets that passed
-	 * the filter, but if filtering is done in the kernel, we
-	 * can't get a count of packets that passed the filter,
-	 * and that would mean the meaning of "ps_recv" wouldn't
-	 * be the same on all Linux systems.
-	 *
-	 * XXX - it's not the same on all systems in any case;
-	 * ideally, we should have a "get the statistics" call
-	 * that supplies more counts and indicates which of them
-	 * it supplies, so that we supply a count of packets
-	 * handed to the filter only on platforms where that
-	 * information is available.
-	 *
-	 * We count them here even if we can get the packet count
-	 * from the kernel, as we can only determine at run time
-	 * whether we'll be able to get it from the kernel (if
-	 * HAVE_STRUCT_TPACKET_STATS isn't defined, we can't get it from
-	 * the kernel, but if it is defined, the library might
-	 * have been built with a 2.4 or later kernel, but we
-	 * might be running on a 2.2[.x] kernel without Alexey
-	 * Kuznetzov's turbopacket patches, and thus the kernel
-	 * might not be able to supply those statistics).  We
-	 * could, I guess, try, when opening the socket, to get
-	 * the statistics, and if we can not increment the count
-	 * here, but it's not clear that always incrementing
-	 * the count is more expensive than always testing a flag
-	 * in memory.
-	 *
-	 * We keep the count in "handlep->packets_read", and use that
-	 * for "ps_recv" if we can't get the statistics from the kernel.
-	 * We do that because, if we *can* get the statistics from
-	 * the kernel, we use "handlep->stat.ps_recv" and
-	 * "handlep->stat.ps_drop" as running counts, as reading the
-	 * statistics from the kernel resets the kernel statistics,
-	 * and if we directly increment "handlep->stat.ps_recv" here,
-	 * that means it will count packets *twice* on systems where
-	 * we can get kernel statistics - once here, and once in
-	 * pcap_stats_linux().
-	 */
-	handlep->packets_read++;
-
-	/* Call the user supplied callback function */
-	callback(userdata, &pcap_header, bp);
-
-	return 1;
+	return (1);
 }
 
 static int
-pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
+pcap_inject_linux(pcap_t *handle, const void *buf, int size)
 {
 	struct pcap_linux *handlep = handle->priv;
 	int ret;
 
-#ifdef HAVE_PF_PACKET_SOCKETS
-	if (!handlep->sock_packet) {
-		/* PF_PACKET socket */
-		if (handlep->ifindex == -1) {
-			/*
-			 * We don't support sending on the "any" device.
-			 */
-			strlcpy(handle->errbuf,
-			    "Sending packets isn't supported on the \"any\" device",
-			    PCAP_ERRBUF_SIZE);
-			return (-1);
-		}
-
-		if (handlep->cooked) {
-			/*
-			 * We don't support sending on the "any" device.
-			 *
-			 * XXX - how do you send on a bound cooked-mode
-			 * socket?
-			 * Is a "sendto()" required there?
-			 */
-			strlcpy(handle->errbuf,
-			    "Sending packets isn't supported in cooked mode",
-			    PCAP_ERRBUF_SIZE);
-			return (-1);
-		}
+	if (handlep->ifindex == -1) {
+		/*
+		 * We don't support sending on the "any" device.
+		 */
+		pcap_strlcpy(handle->errbuf,
+		    "Sending packets isn't supported on the \"any\" device",
+		    PCAP_ERRBUF_SIZE);
+		return (-1);
 	}
-#endif
 
-	ret = send(handle->fd, buf, size, 0);
+	if (handlep->cooked) {
+		/*
+		 * We don't support sending on cooked-mode sockets.
+		 *
+		 * XXX - how do you send on a bound cooked-mode
+		 * socket?
+		 * Is a "sendto()" required there?
+		 */
+		pcap_strlcpy(handle->errbuf,
+		    "Sending packets isn't supported in cooked mode",
+		    PCAP_ERRBUF_SIZE);
+		return (-1);
+	}
+
+	ret = (int)send(handle->fd, buf, size, 0);
 	if (ret == -1) {
 		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "send");
@@ -2154,27 +1241,20 @@
 
 /*
  *  Get the statistics for the given packet capture handle.
- *  Reports the number of dropped packets iff the kernel supports
- *  the PACKET_STATISTICS "getsockopt()" argument (2.4 and later
- *  kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket
- *  patches); otherwise, that information isn't available, and we lie
- *  and report 0 as the count of dropped packets.
  */
 static int
 pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
 {
 	struct pcap_linux *handlep = handle->priv;
-#ifdef HAVE_STRUCT_TPACKET_STATS
 #ifdef HAVE_TPACKET3
 	/*
-	 * For sockets using TPACKET_V1 or TPACKET_V2, the extra
-	 * stuff at the end of a struct tpacket_stats_v3 will not
-	 * be filled in, and we don't look at it so this is OK even
-	 * for those sockets.  In addition, the PF_PACKET socket
-	 * code in the kernel only uses the length parameter to
-	 * compute how much data to copy out and to indicate how
-	 * much data was copied out, so it's OK to base it on the
-	 * size of a struct tpacket_stats.
+	 * For sockets using TPACKET_V2, the extra stuff at the end
+	 * of a struct tpacket_stats_v3 will not be filled in, and
+	 * we don't look at it so this is OK even for those sockets.
+	 * In addition, the PF_PACKET socket code in the kernel only
+	 * uses the length parameter to compute how much data to
+	 * copy out and to indicate how much data was copied out, so
+	 * it's OK to base it on the size of a struct tpacket_stats.
 	 *
 	 * XXX - it's probably OK, in fact, to just use a
 	 * struct tpacket_stats for V3 sockets, as we don't
@@ -2185,52 +1265,77 @@
 	struct tpacket_stats kstats;
 #endif /* HAVE_TPACKET3 */
 	socklen_t len = sizeof (struct tpacket_stats);
-#endif /* HAVE_STRUCT_TPACKET_STATS */
 
-	long if_dropped = 0;
+	long long if_dropped = 0;
 
 	/*
-	 *	To fill in ps_ifdrop, we parse /proc/net/dev for the number
+	 * To fill in ps_ifdrop, we parse
+	 * /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors
+	 * for the numbers
 	 */
 	if (handle->opt.promisc)
 	{
-		if_dropped = handlep->proc_dropped;
-		handlep->proc_dropped = linux_if_drops(handlep->device);
-		handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped);
+		/*
+		 * XXX - is there any reason to do this by remembering
+		 * the last counts value, subtracting it from the
+		 * current counts value, and adding that to stat.ps_ifdrop,
+		 * maintaining stat.ps_ifdrop as a count, rather than just
+		 * saving the *initial* counts value and setting
+		 * stat.ps_ifdrop to the difference between the current
+		 * value and the initial value?
+		 *
+		 * One reason might be to handle the count wrapping
+		 * around, on platforms where the count is 32 bits
+		 * and where you might get more than 2^32 dropped
+		 * packets; is there any other reason?
+		 *
+		 * (We maintain the count as a long long int so that,
+		 * if the kernel maintains the counts as 64-bit even
+		 * on 32-bit platforms, we can handle the real count.
+		 *
+		 * Unfortunately, we can't report 64-bit counts; we
+		 * need a better API for reporting statistics, such as
+		 * one that reports them in a style similar to the
+		 * pcapng Interface Statistics Block, so that 1) the
+		 * counts are 64-bit, 2) it's easier to add new statistics
+		 * without breaking the ABI, and 3) it's easier to
+		 * indicate to a caller that wants one particular
+		 * statistic that it's not available by just not supplying
+		 * it.)
+		 */
+		if_dropped = handlep->sysfs_dropped;
+		handlep->sysfs_dropped = linux_if_drops(handlep->device);
+		handlep->stat.ps_ifdrop += (u_int)(handlep->sysfs_dropped - if_dropped);
 	}
 
-#ifdef HAVE_STRUCT_TPACKET_STATS
 	/*
 	 * Try to get the packet counts from the kernel.
 	 */
 	if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
 			&kstats, &len) > -1) {
 		/*
-		 * On systems where the PACKET_STATISTICS "getsockopt()"
-		 * argument is supported on PF_PACKET sockets:
+		 * "ps_recv" counts only packets that *passed* the
+		 * filter, not packets that didn't pass the filter.
+		 * This includes packets later dropped because we
+		 * ran out of buffer space.
 		 *
-		 *	"ps_recv" counts only packets that *passed* the
-		 *	filter, not packets that didn't pass the filter.
-		 *	This includes packets later dropped because we
-		 *	ran out of buffer space.
+		 * "ps_drop" counts packets dropped because we ran
+		 * out of buffer space.  It doesn't count packets
+		 * dropped by the interface driver.  It counts only
+		 * packets that passed the filter.
 		 *
-		 *	"ps_drop" counts packets dropped because we ran
-		 *	out of buffer space.  It doesn't count packets
-		 *	dropped by the interface driver.  It counts only
-		 *	packets that passed the filter.
+		 * See above for ps_ifdrop.
 		 *
-		 *	See above for ps_ifdrop.
+		 * Both statistics include packets not yet read from
+		 * the kernel by libpcap, and thus not yet seen by
+		 * the application.
 		 *
-		 *	Both statistics include packets not yet read from
-		 *	the kernel by libpcap, and thus not yet seen by
-		 *	the application.
-		 *
-		 * In "linux/net/packet/af_packet.c", at least in the
-		 * 2.4.9 kernel, "tp_packets" is incremented for every
-		 * packet that passes the packet filter *and* is
-		 * successfully queued on the socket; "tp_drops" is
+		 * In "linux/net/packet/af_packet.c", at least in 2.6.27
+		 * through 5.6 kernels, "tp_packets" is incremented for
+		 * every packet that passes the packet filter *and* is
+		 * successfully copied to the ring buffer; "tp_drops" is
 		 * incremented for every packet dropped because there's
-		 * not enough free space in the socket buffer.
+		 * not enough free space in the ring buffer.
 		 *
 		 * When the statistics are returned for a PACKET_STATISTICS
 		 * "getsockopt()" call, "tp_drops" is added to "tp_packets",
@@ -2257,336 +1362,10 @@
 		*stats = handlep->stat;
 		return 0;
 	}
-	else
-	{
-		/*
-		 * If the error was EOPNOTSUPP, fall through, so that
-		 * if you build the library on a system with
-		 * "struct tpacket_stats" and run it on a system
-		 * that doesn't, it works as it does if the library
-		 * is built on a system without "struct tpacket_stats".
-		 */
-		if (errno != EOPNOTSUPP) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "pcap_stats");
-			return -1;
-		}
-	}
-#endif
-	/*
-	 * On systems where the PACKET_STATISTICS "getsockopt()" argument
-	 * is not supported on PF_PACKET sockets:
-	 *
-	 *	"ps_recv" counts only packets that *passed* the filter,
-	 *	not packets that didn't pass the filter.  It does not
-	 *	count packets dropped because we ran out of buffer
-	 *	space.
-	 *
-	 *	"ps_drop" is not supported.
-	 *
-	 *	"ps_ifdrop" is supported. It will return the number
-	 *	of drops the interface reports in /proc/net/dev,
-	 *	if that is available.
-	 *
-	 *	"ps_recv" doesn't include packets not yet read from
-	 *	the kernel by libpcap.
-	 *
-	 * We maintain the count of packets processed by libpcap in
-	 * "handlep->packets_read", for reasons described in the comment
-	 * at the end of pcap_read_packet().  We have no idea how many
-	 * packets were dropped by the kernel buffers -- but we know
-	 * how many the interface dropped, so we can return that.
-	 */
 
-	stats->ps_recv = handlep->packets_read;
-	stats->ps_drop = 0;
-	stats->ps_ifdrop = handlep->stat.ps_ifdrop;
-	return 0;
-}
-
-static int
-add_linux_if(pcap_if_list_t *devlistp, const char *ifname, int fd, char *errbuf)
-{
-	const char *p;
-	char name[512];	/* XXX - pick a size */
-	char *q, *saveq;
-	struct ifreq ifrflags;
-
-	/*
-	 * Get the interface name.
-	 */
-	p = ifname;
-	q = &name[0];
-	while (*p != '\0' && isascii(*p) && !isspace(*p)) {
-		if (*p == ':') {
-			/*
-			 * This could be the separator between a
-			 * name and an alias number, or it could be
-			 * the separator between a name with no
-			 * alias number and the next field.
-			 *
-			 * If there's a colon after digits, it
-			 * separates the name and the alias number,
-			 * otherwise it separates the name and the
-			 * next field.
-			 */
-			saveq = q;
-			while (isascii(*p) && isdigit(*p))
-				*q++ = *p++;
-			if (*p != ':') {
-				/*
-				 * That was the next field,
-				 * not the alias number.
-				 */
-				q = saveq;
-			}
-			break;
-		} else
-			*q++ = *p++;
-	}
-	*q = '\0';
-
-	/*
-	 * Get the flags for this interface.
-	 */
-	strlcpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
-	if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
-		if (errno == ENXIO || errno == ENODEV)
-			return (0);	/* device doesn't actually exist - ignore it */
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "SIOCGIFFLAGS: %.*s",
-		    (int)sizeof(ifrflags.ifr_name),
-		    ifrflags.ifr_name);
-		return (-1);
-	}
-
-	/*
-	 * Add an entry for this interface, with no addresses, if it's
-	 * not already in the list.
-	 */
-	if (find_or_add_if(devlistp, name, ifrflags.ifr_flags,
-	    get_if_flags, errbuf) == NULL) {
-		/*
-		 * Failure.
-		 */
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*
- * Get from "/sys/class/net" all interfaces listed there; if they're
- * already in the list of interfaces we have, that won't add another
- * instance, but if they're not, that'll add them.
- *
- * We don't bother getting any addresses for them; it appears you can't
- * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
- * although some other types of addresses can be fetched with SIOCGIFADDR,
- * we don't bother with them for now.
- *
- * We also don't fail if we couldn't open "/sys/class/net"; we just leave
- * the list of interfaces as is, and return 0, so that we can try
- * scanning /proc/net/dev.
- *
- * Otherwise, we return 1 if we don't get an error and -1 if we do.
- */
-static int
-scan_sys_class_net(pcap_if_list_t *devlistp, char *errbuf)
-{
-	DIR *sys_class_net_d;
-	int fd;
-	struct dirent *ent;
-	char subsystem_path[PATH_MAX+1];
-	struct stat statb;
-	int ret = 1;
-
-	sys_class_net_d = opendir("/sys/class/net");
-	if (sys_class_net_d == NULL) {
-		/*
-		 * Don't fail if it doesn't exist at all.
-		 */
-		if (errno == ENOENT)
-			return (0);
-
-		/*
-		 * Fail if we got some other error.
-		 */
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "Can't open /sys/class/net");
-		return (-1);
-	}
-
-	/*
-	 * Create a socket from which to fetch interface information.
-	 */
-	fd = socket(PF_UNIX, SOCK_RAW, 0);
-	if (fd < 0) {
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "socket");
-		(void)closedir(sys_class_net_d);
-		return (-1);
-	}
-
-	for (;;) {
-		errno = 0;
-		ent = readdir(sys_class_net_d);
-		if (ent == NULL) {
-			/*
-			 * Error or EOF; if errno != 0, it's an error.
-			 */
-			break;
-		}
-
-		/*
-		 * Ignore "." and "..".
-		 */
-		if (strcmp(ent->d_name, ".") == 0 ||
-		    strcmp(ent->d_name, "..") == 0)
-			continue;
-
-		/*
-		 * Ignore plain files; they do not have subdirectories
-		 * and thus have no attributes.
-		 */
-		if (ent->d_type == DT_REG)
-			continue;
-
-		/*
-		 * Is there an "ifindex" file under that name?
-		 * (We don't care whether it's a directory or
-		 * a symlink; older kernels have directories
-		 * for devices, newer kernels have symlinks to
-		 * directories.)
-		 */
-		pcap_snprintf(subsystem_path, sizeof subsystem_path,
-		    "/sys/class/net/%s/ifindex", ent->d_name);
-		if (lstat(subsystem_path, &statb) != 0) {
-			/*
-			 * Stat failed.  Either there was an error
-			 * other than ENOENT, and we don't know if
-			 * this is an interface, or it's ENOENT,
-			 * and either some part of "/sys/class/net/{if}"
-			 * disappeared, in which case it probably means
-			 * the interface disappeared, or there's no
-			 * "ifindex" file, which means it's not a
-			 * network interface.
-			 */
-			continue;
-		}
-
-		/*
-		 * Attempt to add the interface.
-		 */
-		if (add_linux_if(devlistp, &ent->d_name[0], fd, errbuf) == -1) {
-			/* Fail. */
-			ret = -1;
-			break;
-		}
-	}
-	if (ret != -1) {
-		/*
-		 * Well, we didn't fail for any other reason; did we
-		 * fail due to an error reading the directory?
-		 */
-		if (errno != 0) {
-			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "Error reading /sys/class/net");
-			ret = -1;
-		}
-	}
-
-	(void)close(fd);
-	(void)closedir(sys_class_net_d);
-	return (ret);
-}
-
-/*
- * Get from "/proc/net/dev" all interfaces listed there; if they're
- * already in the list of interfaces we have, that won't add another
- * instance, but if they're not, that'll add them.
- *
- * See comments from scan_sys_class_net().
- */
-static int
-scan_proc_net_dev(pcap_if_list_t *devlistp, char *errbuf)
-{
-	FILE *proc_net_f;
-	int fd;
-	char linebuf[512];
-	int linenum;
-	char *p;
-	int ret = 0;
-
-	proc_net_f = fopen("/proc/net/dev", "r");
-	if (proc_net_f == NULL) {
-		/*
-		 * Don't fail if it doesn't exist at all.
-		 */
-		if (errno == ENOENT)
-			return (0);
-
-		/*
-		 * Fail if we got some other error.
-		 */
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "Can't open /proc/net/dev");
-		return (-1);
-	}
-
-	/*
-	 * Create a socket from which to fetch interface information.
-	 */
-	fd = socket(PF_UNIX, SOCK_RAW, 0);
-	if (fd < 0) {
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "socket");
-		(void)fclose(proc_net_f);
-		return (-1);
-	}
-
-	for (linenum = 1;
-	    fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
-		/*
-		 * Skip the first two lines - they're headers.
-		 */
-		if (linenum <= 2)
-			continue;
-
-		p = &linebuf[0];
-
-		/*
-		 * Skip leading white space.
-		 */
-		while (*p != '\0' && isascii(*p) && isspace(*p))
-			p++;
-		if (*p == '\0' || *p == '\n')
-			continue;	/* blank line */
-
-		/*
-		 * Attempt to add the interface.
-		 */
-		if (add_linux_if(devlistp, p, fd, errbuf) == -1) {
-			/* Fail. */
-			ret = -1;
-			break;
-		}
-	}
-	if (ret != -1) {
-		/*
-		 * Well, we didn't fail for any other reason; did we
-		 * fail due to an error reading the file?
-		 */
-		if (ferror(proc_net_f)) {
-			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-			    errno, "Error reading /proc/net/dev");
-			ret = -1;
-		}
-	}
-
-	(void)close(fd);
-	(void)fclose(proc_net_f);
-	return (ret);
+	pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno,
+	    "failed to get statistics from socket");
+	return -1;
 }
 
 /*
@@ -2595,7 +1374,7 @@
 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.
+ * A PF_PACKET socket can be bound to any network interface.
  */
 static int
 can_be_bound(const char *name _U_)
@@ -2604,6 +1383,126 @@
 }
 
 /*
+ * Get a socket to use with various interface ioctls.
+ */
+static int
+get_if_ioctl_socket(void)
+{
+	int fd;
+
+	/*
+	 * This is a bit ugly.
+	 *
+	 * There isn't a socket type that's guaranteed to work.
+	 *
+	 * AF_NETLINK will work *if* you have Netlink configured into the
+	 * kernel (can it be configured out if you have any networking
+	 * support at all?) *and* if you're running a sufficiently recent
+	 * kernel, but not all the kernels we support are sufficiently
+	 * recent - that feature was introduced in Linux 4.6.
+	 *
+	 * AF_UNIX will work *if* you have UNIX-domain sockets configured
+	 * into the kernel and *if* you're not on a system that doesn't
+	 * allow them - some SELinux systems don't allow you create them.
+	 * Most systems probably have them configured in, but not all systems
+	 * have them configured in and allow them to be created.
+	 *
+	 * AF_INET will work *if* you have IPv4 configured into the kernel,
+	 * but, apparently, some systems have network adapters but have
+	 * kernels without IPv4 support.
+	 *
+	 * AF_INET6 will work *if* you have IPv6 configured into the
+	 * kernel, but if you don't have AF_INET, you might not have
+	 * AF_INET6, either (that is, independently on its own grounds).
+	 *
+	 * AF_PACKET would work, except that some of these calls should
+	 * work even if you *don't* have capture permission (you should be
+	 * able to enumerate interfaces and get information about them
+	 * without capture permission; you shouldn't get a failure until
+	 * you try pcap_activate()).  (If you don't allow programs to
+	 * get as much information as possible about interfaces if you
+	 * don't have permission to capture, you run the risk of users
+	 * asking "why isn't it showing XXX" - or, worse, if you don't
+	 * show interfaces *at all* if you don't have permission to
+	 * capture on them, "why do no interfaces show up?" - when the
+	 * real problem is a permissions problem.  Error reports of that
+	 * type require a lot more back-and-forth to debug, as evidenced
+	 * by many Wireshark bugs/mailing list questions/Q&A questoins.)
+	 *
+	 * So:
+	 *
+	 * we first try an AF_NETLINK socket, where "try" includes
+	 * "try to do a device ioctl on it", as, in the future, once
+	 * pre-4.6 kernels are sufficiently rare, that will probably
+	 * be the mechanism most likely to work;
+	 *
+	 * if that fails, we try an AF_UNIX socket, as that's less
+	 * likely to be configured out on a networking-capable system
+	 * than is IP;
+	 *
+	 * if that fails, we try an AF_INET6 socket;
+	 *
+	 * if that fails, we try an AF_INET socket.
+	 */
+	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+	if (fd != -1) {
+		/*
+		 * OK, let's make sure we can do an SIOCGIFNAME
+		 * ioctl.
+		 */
+		struct ifreq ifr;
+
+		memset(&ifr, 0, sizeof(ifr));
+		if (ioctl(fd, SIOCGIFNAME, &ifr) == 0 ||
+		    errno != EOPNOTSUPP) {
+			/*
+			 * It succeeded, or failed for some reason
+			 * other than "netlink sockets don't support
+			 * device ioctls".  Go with the AF_NETLINK
+			 * socket.
+			 */
+			return (fd);
+		}
+
+		/*
+		 * OK, that didn't work, so it's as bad as "netlink
+		 * sockets aren't available".  Close the socket and
+		 * drive on.
+		 */
+		close(fd);
+	}
+
+	/*
+	 * Now try an AF_UNIX socket.
+	 */
+	fd = socket(AF_UNIX, SOCK_RAW, 0);
+	if (fd != -1) {
+		/*
+		 * OK, we got it!
+		 */
+		return (fd);
+	}
+
+	/*
+	 * Now try an AF_INET6 socket.
+	 */
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (fd != -1) {
+		return (fd);
+	}
+
+	/*
+	 * Now try an AF_INET socket.
+	 *
+	 * XXX - if that fails, is there anything else we should try?
+	 * AF_CAN, for embedded systems in vehicles, in case they're
+	 * built without Internet protocol support?  Any other socket
+	 * types popular in non-Internet embedded systems?
+	 */
+	return (socket(AF_INET, SOCK_DGRAM, 0));
+}
+
+/*
  * Get additional flags for a device, using SIOCGIFMEDIA.
  */
 static int
@@ -2624,7 +1523,7 @@
 		return 0;
 	}
 
-	sock = socket(AF_INET, SOCK_DGRAM, 0);
+	sock = get_if_ioctl_socket();
 	if (sock == -1) {
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
 		    "Can't create socket to get ethtool information for %s",
@@ -2636,14 +1535,14 @@
 	 * OK, what type of network is this?
 	 * In particular, is it wired or wireless?
 	 */
-	if (is_wifi(sock, name)) {
+	if (is_wifi(name)) {
 		/*
 		 * Wi-Fi, hence wireless.
 		 */
 		*flags |= PCAP_IF_WIRELESS;
 	} else {
 		/*
-		 * OK, what does /sys/class/net/{if}/type contain?
+		 * OK, what does /sys/class/net/{if_name}/type contain?
 		 * (We don't use that for Wi-Fi, as it'll report
 		 * "Ethernet", i.e. ARPHRD_ETHER, for non-monitor-
 		 * mode devices.)
@@ -2651,7 +1550,7 @@
 		char *pathstr;
 
 		if (asprintf(&pathstr, "/sys/class/net/%s/type", name) == -1) {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: Can't generate path name string for /sys/class/net device",
 			    name);
 			close(sock);
@@ -2665,7 +1564,6 @@
 				 */
 				switch (arptype) {
 
-#ifdef ARPHRD_LOOPBACK
 				case ARPHRD_LOOPBACK:
 					/*
 					 * These are types to which
@@ -2679,7 +1577,6 @@
 					fclose(fh);
 					free(pathstr);
 					return 0;
-#endif
 
 				case ARPHRD_IRDA:
 				case ARPHRD_IEEE80211:
@@ -2708,8 +1605,19 @@
 
 #ifdef ETHTOOL_GLINK
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 	info.cmd = ETHTOOL_GLINK;
+	/*
+	 * XXX - while Valgrind handles SIOCETHTOOL and knows that
+	 * the ETHTOOL_GLINK command sets the .data member of the
+	 * structure, Memory Sanitizer doesn't yet do so:
+	 *
+	 *    https://bugs.llvm.org/show_bug.cgi?id=45814
+	 *
+	 * For now, we zero it out to squelch warnings; if the bug
+	 * in question is fixed, we can remove this.
+	 */
+	info.data = 0;
 	ifr.ifr_data = (caddr_t)&info;
 	if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) {
 		int save_errno = errno;
@@ -2777,8 +1685,6 @@
 int
 pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
-	int ret;
-
 	/*
 	 * Get the list of regular interfaces first.
 	 */
@@ -2787,25 +1693,6 @@
 		return (-1);	/* failure */
 
 	/*
-	 * Read "/sys/class/net", and add to the list of interfaces all
-	 * interfaces listed there that we don't already have, because,
-	 * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
-	 * and even getifaddrs() won't return information about
-	 * interfaces with no addresses, so you need to read "/sys/class/net"
-	 * to get the names of the rest of the interfaces.
-	 */
-	ret = scan_sys_class_net(devlistp, errbuf);
-	if (ret == -1)
-		return (-1);	/* failed */
-	if (ret == 0) {
-		/*
-		 * No /sys/class/net; try reading /proc/net/dev instead.
-		 */
-		if (scan_proc_net_dev(devlistp, errbuf) == -1)
-			return (-1);
-	}
-
-	/*
 	 * Add the "any" device.
 	 * As it refers to all network devices, not to any particular
 	 * network device, the notion of "connected" vs. "disconnected"
@@ -2820,258 +1707,25 @@
 }
 
 /*
- *  Attach the given BPF code to the packet capture device.
- */
-static int
-pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
-    int is_mmapped)
-{
-	struct pcap_linux *handlep;
-#ifdef SO_ATTACH_FILTER
-	struct sock_fprog	fcode;
-	int			can_filter_in_kernel;
-	int			err = 0;
-#endif
-
-	if (!handle)
-		return -1;
-	if (!filter) {
-	        strlcpy(handle->errbuf, "setfilter: No filter specified",
-			PCAP_ERRBUF_SIZE);
-		return -1;
-	}
-
-	handlep = handle->priv;
-
-	/* Make our private copy of the filter */
-
-	if (install_bpf_program(handle, filter) < 0)
-		/* install_bpf_program() filled in errbuf */
-		return -1;
-
-	/*
-	 * Run user level packet filter by default. Will be overriden if
-	 * installing a kernel filter succeeds.
-	 */
-	handlep->filter_in_userland = 1;
-
-	/* Install kernel level filter if possible */
-
-#ifdef SO_ATTACH_FILTER
-#ifdef USHRT_MAX
-	if (handle->fcode.bf_len > USHRT_MAX) {
-		/*
-		 * fcode.len is an unsigned short for current kernel.
-		 * I have yet to see BPF-Code with that much
-		 * instructions but still it is possible. So for the
-		 * sake of correctness I added this check.
-		 */
-		fprintf(stderr, "Warning: Filter too complex for kernel\n");
-		fcode.len = 0;
-		fcode.filter = NULL;
-		can_filter_in_kernel = 0;
-	} else
-#endif /* USHRT_MAX */
-	{
-		/*
-		 * Oh joy, the Linux kernel uses struct sock_fprog instead
-		 * of struct bpf_program and of course the length field is
-		 * of different size. Pointed out by Sebastian
-		 *
-		 * Oh, and we also need to fix it up so that all "ret"
-		 * instructions with non-zero operands have MAXIMUM_SNAPLEN
-		 * as the operand if we're not capturing in memory-mapped
-		 * mode, and so that, if we're in cooked mode, all memory-
-		 * reference instructions use special magic offsets in
-		 * references to the link-layer header and assume that the
-		 * link-layer payload begins at 0; "fix_program()" will do
-		 * that.
-		 */
-		switch (fix_program(handle, &fcode, is_mmapped)) {
-
-		case -1:
-		default:
-			/*
-			 * Fatal error; just quit.
-			 * (The "default" case shouldn't happen; we
-			 * return -1 for that reason.)
-			 */
-			return -1;
-
-		case 0:
-			/*
-			 * The program performed checks that we can't make
-			 * work in the kernel.
-			 */
-			can_filter_in_kernel = 0;
-			break;
-
-		case 1:
-			/*
-			 * We have a filter that'll work in the kernel.
-			 */
-			can_filter_in_kernel = 1;
-			break;
-		}
-	}
-
-	/*
-	 * NOTE: at this point, we've set both the "len" and "filter"
-	 * fields of "fcode".  As of the 2.6.32.4 kernel, at least,
-	 * those are the only members of the "sock_fprog" structure,
-	 * so we initialize every member of that structure.
-	 *
-	 * If there is anything in "fcode" that is not initialized,
-	 * it is either a field added in a later kernel, or it's
-	 * padding.
-	 *
-	 * If a new field is added, this code needs to be updated
-	 * to set it correctly.
-	 *
-	 * If there are no other fields, then:
-	 *
-	 *	if the Linux kernel looks at the padding, it's
-	 *	buggy;
-	 *
-	 *	if the Linux kernel doesn't look at the padding,
-	 *	then if some tool complains that we're passing
-	 *	uninitialized data to the kernel, then the tool
-	 *	is buggy and needs to understand that it's just
-	 *	padding.
-	 */
-	if (can_filter_in_kernel) {
-		if ((err = set_kernel_filter(handle, &fcode)) == 0)
-		{
-			/*
-			 * Installation succeded - using kernel filter,
-			 * so userland filtering not needed.
-			 */
-			handlep->filter_in_userland = 0;
-		}
-		else if (err == -1)	/* Non-fatal error */
-		{
-			/*
-			 * Print a warning if we weren't able to install
-			 * the filter for a reason other than "this kernel
-			 * isn't configured to support socket filters.
-			 */
-			if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
-				fprintf(stderr,
-				    "Warning: Kernel filter failed: %s\n",
-					pcap_strerror(errno));
-			}
-		}
-	}
-
-	/*
-	 * If we're not using the kernel filter, get rid of any kernel
-	 * filter that might've been there before, e.g. because the
-	 * previous filter could work in the kernel, or because some other
-	 * code attached a filter to the socket by some means other than
-	 * calling "pcap_setfilter()".  Otherwise, the kernel filter may
-	 * filter out packets that would pass the new userland filter.
-	 */
-	if (handlep->filter_in_userland) {
-		if (reset_kernel_filter(handle) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno,
-			    "can't remove kernel filter");
-			err = -2;	/* fatal error */
-		}
-	}
-
-	/*
-	 * Free up the copy of the filter that was made by "fix_program()".
-	 */
-	if (fcode.filter != NULL)
-		free(fcode.filter);
-
-	if (err == -2)
-		/* Fatal error */
-		return -1;
-#endif /* SO_ATTACH_FILTER */
-
-	return 0;
-}
-
-static int
-pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
-{
-	return pcap_setfilter_linux_common(handle, filter, 0);
-}
-
-
-/*
  * Set direction flag: Which packets do we accept on a forwarding
  * single device? IN, OUT or both?
  */
 static int
 pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
 {
-#ifdef HAVE_PF_PACKET_SOCKETS
-	struct pcap_linux *handlep = handle->priv;
-
-	if (!handlep->sock_packet) {
-		handle->direction = d;
-		return 0;
-	}
-#endif
 	/*
-	 * We're not using PF_PACKET sockets, so we can't determine
-	 * the direction of the packet.
+	 * It's guaranteed, at this point, that d is a valid
+	 * direction value.
 	 */
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-	    "Setting direction is not supported on SOCK_PACKET sockets");
-	return -1;
+	handle->direction = d;
+	return 0;
 }
 
-#ifdef HAVE_PF_PACKET_SOCKETS
-/*
- * Map the PACKET_ value to a LINUX_SLL_ value; we
- * want the same numerical value to be used in
- * the link-layer header even if the numerical values
- * for the PACKET_ #defines change, so that programs
- * that look at the packet type field will always be
- * able to handle DLT_LINUX_SLL captures.
- */
-static short int
-map_packet_type_to_sll_type(short int sll_pkttype)
-{
-	switch (sll_pkttype) {
-
-	case PACKET_HOST:
-		return htons(LINUX_SLL_HOST);
-
-	case PACKET_BROADCAST:
-		return htons(LINUX_SLL_BROADCAST);
-
-	case PACKET_MULTICAST:
-		return  htons(LINUX_SLL_MULTICAST);
-
-	case PACKET_OTHERHOST:
-		return htons(LINUX_SLL_OTHERHOST);
-
-	case PACKET_OUTGOING:
-		return htons(LINUX_SLL_OUTGOING);
-
-	default:
-		return -1;
-	}
-}
-#endif
-
 static int
-is_wifi(int sock_fd
-#ifndef IW_MODE_MONITOR
-_U_
-#endif
-, const char *device)
+is_wifi(const char *device)
 {
 	char *pathstr;
 	struct stat statb;
-#ifdef IW_MODE_MONITOR
-	char errbuf[PCAP_ERRBUF_SIZE];
-#endif
 
 	/*
 	 * See if there's a sysfs wireless directory for it.
@@ -3089,19 +1743,6 @@
 	}
 	free(pathstr);
 
-#ifdef IW_MODE_MONITOR
-	/*
-	 * OK, maybe it's not wireless, or maybe this kernel doesn't
-	 * support sysfs.  Try the wireless extensions.
-	 */
-	if (has_wext(sock_fd, device, errbuf) == 1) {
-		/*
-		 * It supports the wireless extensions, so it's a Wi-Fi
-		 * device.
-		 */
-		return 1;
-	}
-#endif
 	return 0;
 }
 
@@ -3123,7 +1764,7 @@
  *
  *  Sets the link type to -1 if unable to map the type.
  */
-static void map_arphrd_to_dlt(pcap_t *handle, int sock_fd, int arptype,
+static void map_arphrd_to_dlt(pcap_t *handle, int arptype,
 			      const char *device, int cooked_ok)
 {
 	static const char cdma_rmnet[] = "cdma_rmnet";
@@ -3161,12 +1802,33 @@
 		 * XXX - are there any other sorts of "fake Ethernet" that
 		 * have ARPHRD_ETHER but that shouldn't offer DLT_DOCSIS as
 		 * a Cisco CMTS won't put traffic onto it or get traffic
-		 * bridged onto it?  ISDN is handled in "activate_new()",
+		 * bridged onto it?  ISDN is handled in "activate_pf_packet()",
 		 * as we fall back on cooked mode there, and we use
 		 * is_wifi() to check for 802.11 devices; are there any
 		 * others?
 		 */
-		if (!is_wifi(sock_fd, device)) {
+		if (!is_wifi(device)) {
+			int ret;
+
+			/*
+			 * This is not a Wi-Fi device but it could be
+			 * a DSA master/management network device.
+			 */
+			ret = iface_dsa_get_proto_info(device, handle);
+			if (ret < 0)
+				return;
+
+			if (ret == 1) {
+				/*
+				 * This is a DSA master/management network
+				 * device linktype is already set by
+				 * iface_dsa_get_proto_info() set an
+				 * appropriate offset here.
+				 */
+				handle->offset = 2;
+				break;
+			}
+
 			/*
 			 * It's not a Wi-Fi device; offer DOCSIS.
 			 */
@@ -3432,7 +2094,7 @@
 		 * Back in 2002, Donald Lee at Cray wanted a DLT_ for
 		 * IP-over-FC:
 		 *
-		 *	http://www.mail-archive.com/tcpdump-workers@sandelman.ottawa.on.ca/msg01043.html
+		 *	https://www.mail-archive.com/tcpdump-workers@sandelman.ottawa.on.ca/msg01043.html
 		 *
 		 * and one was assigned.
 		 *
@@ -3496,7 +2158,7 @@
 		/* We need to save packet direction for IrDA decoding,
 		 * so let's use "Linux-cooked" mode. Jean II
 		 *
-		 * XXX - this is handled in activate_new(). */
+		 * XXX - this is handled in activate_pf_packet(). */
 		/* handlep->cooked = 1; */
 		break;
 
@@ -3538,7 +2200,7 @@
 		 * pick up the netlink protocol type such as NETLINK_ROUTE,
 		 * NETLINK_GENERIC, NETLINK_FIB_LOOKUP, etc.
 		 *
-		 * XXX - this is handled in activate_new().
+		 * XXX - this is handled in activate_pf_packet().
 		 */
 		/* handlep->cooked = 1; */
 		break;
@@ -3556,24 +2218,56 @@
 	}
 }
 
-/* ===== Functions to interface to the newer kernels ================== */
+#ifdef PACKET_RESERVE
+static void
+set_dlt_list_cooked(pcap_t *handle, int sock_fd)
+{
+	socklen_t		len;
+	unsigned int		tp_reserve;
+
+	/*
+	 * If we can't do PACKET_RESERVE, we can't reserve extra space
+	 * for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+	 */
+	len = sizeof(tp_reserve);
+	if (getsockopt(sock_fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve,
+	    &len) == 0) {
+		/*
+		 * Yes, we can do DLL_LINUX_SLL2.
+		 */
+		handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+		/*
+		 * If that fails, just leave the list empty.
+		 */
+		if (handle->dlt_list != NULL) {
+			handle->dlt_list[0] = DLT_LINUX_SLL;
+			handle->dlt_list[1] = DLT_LINUX_SLL2;
+			handle->dlt_count = 2;
+		}
+	}
+}
+#else/* PACKET_RESERVE */
+/*
+ * The build environment doesn't define PACKET_RESERVE, so we can't reserve
+ * extra space for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+ */
+static void
+set_dlt_list_cooked(pcap_t *handle _U_, int sock_fd _U_)
+{
+}
+#endif /* PACKET_RESERVE */
 
 /*
- * Try to open a packet socket using the new kernel PF_PACKET interface.
- * Returns 1 on success, 0 on an error that means the new interface isn't
- * present (so the old SOCK_PACKET interface should be tried), and a
- * PCAP_ERROR_ value on an error that means that the old mechanism won't
- * work either (so it shouldn't be tried).
+ * Try to set up a PF_PACKET socket.
+ * Returns 0 on success and a PCAP_ERROR_ value on failure.
  */
 static int
-activate_new(pcap_t *handle)
+activate_pf_packet(pcap_t *handle, int is_any_device)
 {
-#ifdef HAVE_PF_PACKET_SOCKETS
 	struct pcap_linux *handlep = handle->priv;
 	const char		*device = handle->opt.device;
-	int			is_any_device = (strcmp(device, "any") == 0);
-	int			protocol = pcap_protocol(handle);
-	int			sock_fd = -1, arptype;
+	int			status = 0;
+	int			sock_fd, arptype;
 #ifdef HAVE_PACKET_AUXDATA
 	int			val;
 #endif
@@ -3585,43 +2279,37 @@
 #endif
 
 	/*
-	 * Open a socket with protocol family packet. If the
-	 * "any" device was specified, we open a SOCK_DGRAM
-	 * socket for the cooked interface, otherwise we first
-	 * try a SOCK_RAW socket for the raw interface.
+	 * Open a socket with protocol family packet. If cooked is true,
+	 * we open a SOCK_DGRAM socket for the cooked interface, otherwise
+	 * we open a SOCK_RAW socket for the raw interface.
+	 *
+	 * The protocol is set to 0.  This means we will receive no
+	 * packets until we "bind" the socket with a non-zero
+	 * protocol.  This allows us to setup the ring buffers without
+	 * dropping any packets.
 	 */
 	sock_fd = is_any_device ?
-		socket(PF_PACKET, SOCK_DGRAM, protocol) :
-		socket(PF_PACKET, SOCK_RAW, protocol);
+		socket(PF_PACKET, SOCK_DGRAM, 0) :
+		socket(PF_PACKET, SOCK_RAW, 0);
 
 	if (sock_fd == -1) {
-		if (errno == EINVAL || errno == EAFNOSUPPORT) {
-			/*
-			 * We don't support PF_PACKET/SOCK_whatever
-			 * sockets; try the old mechanism.
-			 */
-			return 0;
-		}
-
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "socket");
 		if (errno == EPERM || errno == EACCES) {
 			/*
 			 * You don't have permission to open the
 			 * socket.
 			 */
-			return PCAP_ERROR_PERM_DENIED;
+			status = PCAP_ERROR_PERM_DENIED;
 		} else {
 			/*
 			 * Other error.
 			 */
-			return PCAP_ERROR;
+			status = PCAP_ERROR;
 		}
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "socket");
+		return status;
 	}
 
-	/* It seems the kernel supports the new interface. */
-	handlep->sock_packet = 0;
-
 	/*
 	 * Get the interface index of the loopback device.
 	 * If the attempt fails, don't fail, just set the
@@ -3686,7 +2374,7 @@
 			close(sock_fd);
 			return arptype;
 		}
-		map_arphrd_to_dlt(handle, sock_fd, arptype, device, 1);
+		map_arphrd_to_dlt(handle, arptype, device, 1);
 		if (handle->linktype == -1 ||
 		    handle->linktype == DLT_LINUX_SLL ||
 		    handle->linktype == DLT_LINUX_IRDA ||
@@ -3703,28 +2391,29 @@
 			 * type we can only determine by using
 			 * APIs that may be different on different
 			 * kernels) - reopen in cooked mode.
+			 *
+			 * If the type is unknown, return a warning;
+			 * map_arphrd_to_dlt() has already set the
+			 * warning message.
 			 */
 			if (close(sock_fd) == -1) {
 				pcap_fmt_errmsg_for_errno(handle->errbuf,
 				    PCAP_ERRBUF_SIZE, errno, "close");
 				return PCAP_ERROR;
 			}
-			sock_fd = socket(PF_PACKET, SOCK_DGRAM, protocol);
-			if (sock_fd == -1) {
+			sock_fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+			if (sock_fd < 0) {
+				/*
+				 * Fatal error.  We treat this as
+				 * a generic error; we already know
+				 * that we were able to open a
+				 * PF_PACKET/SOCK_RAW socket, so
+				 * any failure is a "this shouldn't
+				 * happen" case.
+				 */
 				pcap_fmt_errmsg_for_errno(handle->errbuf,
 				    PCAP_ERRBUF_SIZE, errno, "socket");
-				if (errno == EPERM || errno == EACCES) {
-					/*
-					 * You don't have permission to
-					 * open the socket.
-					 */
-					return PCAP_ERROR_PERM_DENIED;
-				} else {
-					/*
-					 * Other error.
-					 */
-					return PCAP_ERROR;
-				}
+				return PCAP_ERROR;
 			}
 			handlep->cooked = 1;
 
@@ -3737,6 +2426,7 @@
 				free(handle->dlt_list);
 				handle->dlt_list = NULL;
 				handle->dlt_count = 0;
+				set_dlt_list_cooked(handle, sock_fd);
 			}
 
 			if (handle->linktype == -1) {
@@ -3746,7 +2436,7 @@
 				 * update "map_arphrd_to_dlt()"
 				 * to handle the new type.
 				 */
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"arptype %d not "
 					"supported by libpcap - "
 					"falling back to cooked "
@@ -3763,6 +2453,12 @@
 			    handle->linktype != DLT_LINUX_LAPD &&
 			    handle->linktype != DLT_NETLINK)
 				handle->linktype = DLT_LINUX_SLL;
+			if (handle->linktype == -1) {
+				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				    "unknown arptype %d, defaulting to cooked mode",
+				    arptype);
+				status = PCAP_WARNING;
+			}
 		}
 
 		handlep->ifindex = iface_get_id(sock_fd, device,
@@ -3773,12 +2469,9 @@
 		}
 
 		if ((err = iface_bind(sock_fd, handlep->ifindex,
-		    handle->errbuf, protocol)) != 1) {
-		    	close(sock_fd);
-			if (err < 0)
-				return err;
-			else
-				return 0;	/* try old mechanism */
+		    handle->errbuf, 0)) != 0) {
+			close(sock_fd);
+			return err;
 		}
 	} else {
 		/*
@@ -3797,6 +2490,9 @@
 		 */
 		handlep->cooked = 1;
 		handle->linktype = DLT_LINUX_SLL;
+		handle->dlt_list = NULL;
+		handle->dlt_count = 0;
+		set_dlt_list_cooked(handle, sock_fd);
 
 		/*
 		 * We're not bound to a device.
@@ -3837,20 +2533,20 @@
 		if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
 		    &mr, sizeof(mr)) == -1) {
 			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "setsockopt");
+			    PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)");
 			close(sock_fd);
 			return PCAP_ERROR;
 		}
 	}
 
-	/* Enable auxillary data if supported and reserve room for
+	/* Enable auxiliary data if supported and reserve room for
 	 * reconstructing VLAN headers. */
 #ifdef HAVE_PACKET_AUXDATA
 	val = 1;
 	if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
 		       sizeof(val)) == -1 && errno != ENOPROTOOPT) {
 		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "setsockopt");
+		    errno, "setsockopt (PACKET_AUXDATA)");
 		close(sock_fd);
 		return PCAP_ERROR;
 	}
@@ -3858,22 +2554,18 @@
 #endif /* HAVE_PACKET_AUXDATA */
 
 	/*
-	 * This is a 2.2[.x] or later kernel (we know that
-	 * because we're not using a SOCK_PACKET socket -
-	 * PF_PACKET is supported only in 2.2 and later
-	 * kernels).
-	 *
-	 * We can safely pass "recvfrom()" a byte count
-	 * based on the snapshot length.
-	 *
 	 * If we're in cooked mode, make the snapshot length
 	 * large enough to hold a "cooked mode" header plus
 	 * 1 byte of packet data (so we don't pass a byte
 	 * count of 0 to "recvfrom()").
+	 * XXX - we don't know whether this will be DLT_LINUX_SLL
+	 * or DLT_LINUX_SLL2, so make sure it's big enough for
+	 * a DLT_LINUX_SLL2 "cooked mode" header; a snapshot length
+	 * that small is silly anyway.
 	 */
 	if (handlep->cooked) {
-		if (handle->snapshot < SLL_HDR_LEN + 1)
-			handle->snapshot = SLL_HDR_LEN + 1;
+		if (handle->snapshot < SLL2_HDR_LEN + 1)
+			handle->snapshot = SLL2_HDR_LEN + 1;
 	}
 	handle->bufsize = handle->snapshot;
 
@@ -3904,17 +2596,15 @@
 		break;
 	}
 
-#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
 	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
 		int nsec_tstamps = 1;
 
 		if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
 			close(sock_fd);
 			return PCAP_ERROR;
 		}
 	}
-#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
 
 	/*
 	 * We've succeeded. Save the socket FD in the pcap structure.
@@ -3938,30 +2628,20 @@
 	}
 #endif /* defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) */
 
-	return 1;
-#else /* HAVE_PF_PACKET_SOCKETS */
-	strlcpy(ebuf,
-		"New packet capturing interface not supported by build "
-		"environment", PCAP_ERRBUF_SIZE);
-	return 0;
-#endif /* HAVE_PF_PACKET_SOCKETS */
+	return status;
 }
 
-#ifdef HAVE_PACKET_RING
 /*
- * Attempt to activate with memory-mapped access.
+ * Attempt to setup memory-mapped access.
  *
  * On success, returns 1, and sets *status to 0 if there are no warnings
  * or to a PCAP_WARNING_ code if there is a warning.
  *
- * On failure due to lack of support for memory-mapped capture, returns
- * 0.
- *
  * On error, returns -1, and sets *status to the appropriate error code;
  * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
  */
 static int
-activate_mmap(pcap_t *handle, int *status)
+setup_mmapped(pcap_t *handle, int *status)
 {
 	struct pcap_linux *handlep = handle->priv;
 	int ret;
@@ -3989,14 +2669,6 @@
 		return ret;
 	}
 	ret = create_ring(handle, status);
-	if (ret == 0) {
-		/*
-		 * We don't support memory-mapped capture; our caller
-		 * will fall back on reading from the socket.
-		 */
-		free(handlep->oneshot_buffer);
-		return 0;
-	}
 	if (ret == -1) {
 		/*
 		 * Error attempting to enable memory-mapped capture;
@@ -4010,49 +2682,18 @@
 	 * Success.  *status has been set either to 0 if there are no
 	 * warnings or to a PCAP_WARNING_ value if there is a warning.
 	 *
-	 * Override some defaults and inherit the other fields from
-	 * activate_new.
 	 * handle->offset is used to get the current position into the rx ring.
 	 * handle->cc is used to store the ring size.
 	 */
 
-	switch (handlep->tp_version) {
-	case TPACKET_V1:
-		handle->read_op = pcap_read_linux_mmap_v1;
-		break;
-	case TPACKET_V1_64:
-		handle->read_op = pcap_read_linux_mmap_v1_64;
-		break;
-#ifdef HAVE_TPACKET2
-	case TPACKET_V2:
-		handle->read_op = pcap_read_linux_mmap_v2;
-		break;
-#endif
-#ifdef HAVE_TPACKET3
-	case TPACKET_V3:
-		handle->read_op = pcap_read_linux_mmap_v3;
-		break;
-#endif
-	}
-	handle->cleanup_op = pcap_cleanup_linux_mmap;
-	handle->setfilter_op = pcap_setfilter_linux_mmap;
-	handle->setnonblock_op = pcap_setnonblock_mmap;
-	handle->getnonblock_op = pcap_getnonblock_mmap;
-	handle->oneshot_callback = pcap_oneshot_mmap;
-	handle->selectable_fd = handle->fd;
+	/*
+	 * Set the timeout to use in poll() before returning.
+	 */
+	set_poll_timeout(handlep);
+
 	return 1;
 }
-#else /* HAVE_PACKET_RING */
-static int
-activate_mmap(pcap_t *handle _U_, int *status _U_)
-{
-	return 0;
-}
-#endif /* HAVE_PACKET_RING */
 
-#ifdef HAVE_PACKET_RING
-
-#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
 /*
  * Attempt to set the socket to the specified version of the memory-mapped
  * header.
@@ -4070,15 +2711,41 @@
 	/*
 	 * Probe whether kernel supports the specified TPACKET version;
 	 * this also gets the length of the header for that version.
+	 *
+	 * This socket option was introduced in 2.6.27, which was
+	 * also the first release with TPACKET_V2 support.
 	 */
 	if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
-		if (errno == ENOPROTOOPT || errno == EINVAL)
-			return 1;	/* no */
+		if (errno == EINVAL) {
+			/*
+			 * EINVAL means this specific version of TPACKET
+			 * is not supported. Tell the caller they can try
+			 * with a different one; if they've run out of
+			 * others to try, let them set the error message
+			 * appropriately.
+			 */
+			return 1;
+		}
 
-		/* Failed to even find out; this is a fatal error. */
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "can't get %s header len on packet socket",
-		    version_str);
+		/*
+		 * All other errors are fatal.
+		 */
+		if (errno == ENOPROTOOPT) {
+			/*
+			 * PACKET_HDRLEN isn't supported, which means
+			 * that memory-mapped capture isn't supported.
+			 * Indicate that in the message.
+			 */
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			    "Kernel doesn't support memory-mapped capture; a 2.6.27 or later 2.x kernel is required, with CONFIG_PACKET_MMAP specified for 2.x kernels");
+		} else {
+			/*
+			 * Some unexpected error.
+			 */
+			pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "can't get %s header len on packet socket",
+			    version_str);
+		}
 		return -1;
 	}
 	handlep->tp_hdrlen = val;
@@ -4092,65 +2759,20 @@
 	}
 	handlep->tp_version = version;
 
-	/* Reserve space for VLAN tag reconstruction */
-	val = VLAN_TAG_LEN;
-	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
-			   sizeof(val)) < 0) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "can't set up reserve on packet socket");
-		return -1;
-	}
-
 	return 0;
 }
-#endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */
-
-/*
- * If the instruction set for which we're compiling has both 32-bit
- * and 64-bit versions, and Linux support for the 64-bit version
- * predates TPACKET_V2, define ISA_64_BIT as the .machine value
- * you get from uname() for the 64-bit version.  Otherwise, leave
- * it undefined.  (This includes ARM, which has a 64-bit version,
- * but Linux support for it appeared well after TPACKET_V2 support
- * did, so there should never be a case where 32-bit ARM code is
- * running o a 64-bit kernel that only supports TPACKET_V1.)
- *
- * If we've omitted your favorite such architecture, please contribute
- * a patch.  (No patch is needed for architectures that are 32-bit-only
- * or for which Linux has no support for 32-bit userland - or for which,
- * as noted, 64-bit support appeared in Linux after TPACKET_V2 support
- * did.)
- */
-#if defined(__i386__)
-#define ISA_64_BIT	"x86_64"
-#elif defined(__ppc__)
-#define ISA_64_BIT	"ppc64"
-#elif defined(__sparc__)
-#define ISA_64_BIT	"sparc64"
-#elif defined(__s390__)
-#define ISA_64_BIT	"s390x"
-#elif defined(__mips__)
-#define ISA_64_BIT	"mips64"
-#elif defined(__hppa__)
-#define ISA_64_BIT	"parisc64"
-#endif
 
 /*
  * Attempt to set the socket to version 3 of the memory-mapped header and,
  * if that fails because version 3 isn't supported, attempt to fall
- * back to version 2.  If version 2 isn't supported, just leave it at
- * version 1.
+ * back to version 2.  If version 2 isn't supported, just fail.
  *
- * Return 1 if we succeed or if we fail because neither version 2 nor 3 is
- * supported; return -1 on any other error, and set handle->errbuf.
+ * Return 0 if we succeed and -1 on any other error, and set handle->errbuf.
  */
 static int
 prepare_tpacket_socket(pcap_t *handle)
 {
-	struct pcap_linux *handlep = handle->priv;
-#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
 	int ret;
-#endif
 
 #ifdef HAVE_TPACKET3
 	/*
@@ -4170,7 +2792,7 @@
 			/*
 			 * Success.
 			 */
-			return 1;
+			return 0;
 		}
 		if (ret == -1) {
 			/*
@@ -4179,10 +2801,14 @@
 			 */
 			return -1;
 		}
+
+		/*
+		 * This means it returned 1, which means "the kernel
+		 * doesn't support TPACKET_V3"; try TPACKET_V2.
+		 */
 	}
 #endif /* HAVE_TPACKET3 */
 
-#ifdef HAVE_TPACKET2
 	/*
 	 * Try setting the version to TPACKET_V2.
 	 */
@@ -4191,62 +2817,22 @@
 		/*
 		 * Success.
 		 */
-		return 1;
+		return 0;
 	}
-	if (ret == -1) {
+
+	if (ret == 1) {
 		/*
-		 * We failed for some reason other than "the
-		 * kernel doesn't support TPACKET_V2".
+		 * OK, the kernel supports memory-mapped capture, but
+		 * not TPACKET_V2.  Set the error message appropriately.
 		 */
-		return -1;
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    "Kernel doesn't support TPACKET_V2; a 2.6.27 or later kernel is required");
 	}
-#endif /* HAVE_TPACKET2 */
 
 	/*
-	 * OK, we're using TPACKET_V1, as that's all the kernel supports.
+	 * We failed.
 	 */
-	handlep->tp_version = TPACKET_V1;
-	handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
-
-#ifdef ISA_64_BIT
-	/*
-	 * 32-bit userspace + 64-bit kernel + TPACKET_V1 are not compatible with
-	 * each other due to platform-dependent data type size differences.
-	 *
-	 * If we have a 32-bit userland and a 64-bit kernel, use an
-	 * internally-defined TPACKET_V1_64, with which we use a 64-bit
-	 * version of the data structures.
-	 */
-	if (sizeof(long) == 4) {
-		/*
-		 * This is 32-bit code.
-		 */
-		struct utsname utsname;
-
-		if (uname(&utsname) == -1) {
-			/*
-			 * Failed.
-			 */
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "uname failed");
-			return -1;
-		}
-		if (strcmp(utsname.machine, ISA_64_BIT) == 0) {
-			/*
-			 * uname() tells us the machine is 64-bit,
-			 * so we presumably have a 64-bit kernel.
-			 *
-			 * XXX - this presumes that uname() won't lie
-			 * in 32-bit code and claim that the machine
-			 * has the 32-bit version of the ISA.
-			 */
-			handlep->tp_version = TPACKET_V1_64;
-			handlep->tp_hdrlen = sizeof(struct tpacket_hdr_64);
-		}
-	}
-#endif
-
-	return 1;
+	return -1;
 }
 
 #define MAX(a,b) ((a)>(b)?(a):(b))
@@ -4257,9 +2843,6 @@
  * On success, returns 1, and sets *status to 0 if there are no warnings
  * or to a PCAP_WARNING_ code if there is a warning.
  *
- * On failure due to lack of support for memory-mapped capture, returns
- * 0.
- *
  * On error, returns -1, and sets *status to the appropriate error code;
  * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
  */
@@ -4270,9 +2853,9 @@
 	unsigned i, j, frames_per_block;
 #ifdef HAVE_TPACKET3
 	/*
-	 * For sockets using TPACKET_V1 or TPACKET_V2, the extra
-	 * stuff at the end of a struct tpacket_req3 will be
-	 * ignored, so this is OK even for those sockets.
+	 * For sockets using TPACKET_V2, the extra stuff at the end of a
+	 * struct tpacket_req3 will be ignored, so this is OK even for
+	 * those sockets.
 	 */
 	struct tpacket_req3 req;
 #else
@@ -4287,13 +2870,56 @@
 	 */
 	*status = 0;
 
+	/*
+	 * Reserve space for VLAN tag reconstruction.
+	 */
+	tp_reserve = VLAN_TAG_LEN;
+
+	/*
+	 * If we're using DLT_LINUX_SLL2, reserve space for a
+	 * DLT_LINUX_SLL2 header.
+	 *
+	 * XXX - we assume that the kernel is still adding
+	 * 16 bytes of extra space; that happens to
+	 * correspond to SLL_HDR_LEN (whether intentionally
+	 * or not - the kernel code has a raw "16" in
+	 * the expression), so we subtract SLL_HDR_LEN
+	 * from SLL2_HDR_LEN to get the additional space
+	 * needed.  That also means we don't bother reserving
+	 * any additional space if we're using DLT_LINUX_SLL.
+	 *
+	 * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)?
+	 */
+	if (handle->linktype == DLT_LINUX_SLL2)
+		tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN;
+
+	/*
+	 * Try to request that amount of reserve space.
+	 * This must be done before creating the ring buffer.
+	 * If PACKET_RESERVE is supported, creating the ring
+	 * buffer should be, although if creating the ring
+	 * buffer fails, the PACKET_RESERVE call has no effect,
+	 * so falling back on read-from-the-socket capturing
+	 * won't be affected.
+	 */
+	len = sizeof(tp_reserve);
+	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+	    &tp_reserve, len) < 0) {
+		/*
+		 * We treat ENOPROTOOPT as an error, as we
+		 * already determined that we support
+		 * TPACKET_V2 and later; see above.
+		 */
+		pcap_fmt_errmsg_for_errno(handle->errbuf,
+		    PCAP_ERRBUF_SIZE, errno,
+		    "setsockopt (PACKET_RESERVE)");
+		*status = PCAP_ERROR;
+		return -1;
+	}
+
 	switch (handlep->tp_version) {
 
-	case TPACKET_V1:
-	case TPACKET_V1_64:
-#ifdef HAVE_TPACKET2
 	case TPACKET_V2:
-#endif
 		/* Note that with large snapshot length (say 256K, which is
 		 * the default for recent versions of tcpdump, Wireshark,
 		 * TShark, dumpcap or 64K, the value that "-s 0" has given for
@@ -4359,30 +2985,10 @@
 		if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
 		    &len) < 0) {
 			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "getsockopt");
+			    PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_TYPE)");
 			*status = PCAP_ERROR;
 			return -1;
 		}
-#ifdef PACKET_RESERVE
-		len = sizeof(tp_reserve);
-		if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
-		    &tp_reserve, &len) < 0) {
-			if (errno != ENOPROTOOPT) {
-				/*
-				 * ENOPROTOOPT means "kernel doesn't support
-				 * PACKET_RESERVE", in which case we fall back
-				 * as best we can.
-				 */
-				pcap_fmt_errmsg_for_errno(handle->errbuf,
-				    PCAP_ERRBUF_SIZE, errno, "getsockopt");
-				*status = PCAP_ERROR;
-				return -1;
-			}
-			tp_reserve = 0;	/* older kernel, reserve not supported */
-		}
-#else
-		tp_reserve = 0;	/* older kernel, reserve not supported */
-#endif
 		maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
 			/* XXX: in the kernel maclen is calculated from
 			 * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
@@ -4443,14 +3049,14 @@
 		break;
 #endif
 	default:
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Internal error: unknown TPACKET_ value %u",
 		    handlep->tp_version);
 		*status = PCAP_ERROR;
 		return -1;
 	}
 
-	/* compute the minumum block size that will handle this frame.
+	/* compute the minimum block size that will handle this frame.
 	 * The block has to be page size aligned.
 	 * The max block size allowed by the kernel is arch-dependent and
 	 * it's not explicitly checked here. */
@@ -4496,7 +3102,7 @@
 		hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
 
 		memset(&ifr, 0, sizeof(ifr));
-		strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
+		pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
 		ifr.ifr_data = (void *)&hwconfig;
 
 		if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
@@ -4580,7 +3186,26 @@
 
 #ifdef HAVE_TPACKET3
 	/* timeout value to retire block - use the configured buffering timeout, or default if <0. */
-	req.tp_retire_blk_tov = (handlep->timeout>=0)?handlep->timeout:0;
+	if (handlep->timeout > 0) {
+		/* Use the user specified timeout as the block timeout */
+		req.tp_retire_blk_tov = handlep->timeout;
+	} else if (handlep->timeout == 0) {
+		/*
+		 * In pcap, this means "infinite timeout"; TPACKET_V3
+		 * doesn't support that, so just set it to UINT_MAX
+		 * milliseconds.  In the TPACKET_V3 loop, if the
+		 * timeout is 0, and we haven't yet seen any packets,
+		 * and we block and still don't have any packets, we
+		 * keep blocking until we do.
+		 */
+		req.tp_retire_blk_tov = UINT_MAX;
+	} else {
+		/*
+		 * XXX - this is not valid; use 0, meaning "have the
+		 * kernel pick a default", for now.
+		 */
+		req.tp_retire_blk_tov = 0;
+	}
 	/* private data not used */
 	req.tp_sizeof_priv = 0;
 	/* Rx ring - feature request bits - none (rxhash will not be filled) */
@@ -4605,12 +3230,6 @@
 				req.tp_frame_nr -= req.tp_frame_nr/20;
 			goto retry;
 		}
-		if (errno == ENOPROTOOPT) {
-			/*
-			 * We don't have ring buffer support in this kernel.
-			 */
-			return 0;
-		}
 		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "can't create rx ring on packet socket");
 		*status = PCAP_ERROR;
@@ -4646,7 +3265,7 @@
 	/* fill the header ring with proper frame ptr*/
 	handle->offset = 0;
 	for (i=0; i<req.tp_block_nr; ++i) {
-		void *base = &handlep->mmapbuf[i*req.tp_block_size];
+		u_char *base = &handlep->mmapbuf[i*req.tp_block_size];
 		for (j=0; j<frames_per_block; ++j, ++handle->offset) {
 			RING_GET_CURRENT_FRAME(handle) = base;
 			base += req.tp_frame_size;
@@ -4664,10 +3283,14 @@
 {
 	struct pcap_linux *handlep = handle->priv;
 
-	/* tell the kernel to destroy the ring*/
+	/*
+	 * Tell the kernel to destroy the ring.
+	 * We don't check for setsockopt failure, as 1) we can't recover
+	 * from an error and 2) we might not yet have set it up in the
+	 * first place.
+	 */
 	struct tpacket_req req;
 	memset(&req, 0, sizeof(req));
-	/* do not test for setsockopt failure, as we can't recover from any error */
 	(void)setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
 				(void *) &req, sizeof(req));
 
@@ -4697,7 +3320,7 @@
  * pcap_next() or pcap_next_ex().
  */
 static void
-pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+pcap_oneshot_linux(u_char *user, const struct pcap_pkthdr *h,
     const u_char *bytes)
 {
 	struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
@@ -4709,22 +3332,8 @@
 	*sp->pkt = handlep->oneshot_buffer;
 }
 
-static void
-pcap_cleanup_linux_mmap( pcap_t *handle )
-{
-	struct pcap_linux *handlep = handle->priv;
-
-	destroy_ring(handle);
-	if (handlep->oneshot_buffer != NULL) {
-		free(handlep->oneshot_buffer);
-		handlep->oneshot_buffer = NULL;
-	}
-	pcap_cleanup_linux(handle);
-}
-
-
 static int
-pcap_getnonblock_mmap(pcap_t *handle)
+pcap_getnonblock_linux(pcap_t *handle)
 {
 	struct pcap_linux *handlep = handle->priv;
 
@@ -4733,7 +3342,7 @@
 }
 
 static int
-pcap_setnonblock_mmap(pcap_t *handle, int nonblock)
+pcap_setnonblock_linux(pcap_t *handle, int nonblock)
 {
 	struct pcap_linux *handlep = handle->priv;
 
@@ -4769,7 +3378,7 @@
 /*
  * Get the status field of the ring buffer frame at a specified offset.
  */
-static inline int
+static inline u_int
 pcap_get_ring_frame_status(pcap_t *handle, int offset)
 {
 	struct pcap_linux *handlep = handle->priv;
@@ -4777,20 +3386,12 @@
 
 	h.raw = RING_GET_FRAME_AT(handle, offset);
 	switch (handlep->tp_version) {
-	case TPACKET_V1:
-		return (h.h1->tp_status);
-		break;
-	case TPACKET_V1_64:
-		return (h.h1_64->tp_status);
-		break;
-#ifdef HAVE_TPACKET2
 	case TPACKET_V2:
-		return (h.h2->tp_status);
+		return __atomic_load_n(&h.h2->tp_status, __ATOMIC_ACQUIRE);
 		break;
-#endif
 #ifdef HAVE_TPACKET3
 	case TPACKET_V3:
-		return (h.h3->hdr.bh1.block_status);
+		return __atomic_load_n(&h.h3->hdr.bh1.block_status, __ATOMIC_ACQUIRE);
 		break;
 #endif
 	}
@@ -4798,25 +3399,62 @@
 	return 0;
 }
 
-#ifndef POLLRDHUP
-#define POLLRDHUP 0
-#endif
-
 /*
  * Block waiting for frames to be available.
  */
 static int pcap_wait_for_frames_mmap(pcap_t *handle)
 {
 	struct pcap_linux *handlep = handle->priv;
-	char c;
-	struct pollfd pollinfo;
+	int timeout;
+	struct ifreq ifr;
 	int ret;
+	struct pollfd pollinfo[2];
+	pollinfo[0].fd = handle->fd;
+	pollinfo[0].events = POLLIN;
+	pollinfo[1].fd = handlep->poll_breakloop_fd;
+	pollinfo[1].events = POLLIN;
 
-	pollinfo.fd = handle->fd;
-	pollinfo.events = POLLIN;
-
-	do {
-		/*
+	/*
+	 * Keep polling until we either get some packets to read, see
+	 * that we got told to break out of the loop, get a fatal error,
+	 * or discover that the device went away.
+	 *
+	 * In non-blocking mode, we must still do one poll() to catch
+	 * any pending error indications, but the poll() has a timeout
+	 * of 0, so that it doesn't block, and we quit after that one
+	 * poll().
+	 *
+	 * If we've seen an ENETDOWN, it might be the first indication
+	 * that the device went away, or it might just be that it was
+	 * configured down.  Unfortunately, there's no guarantee that
+	 * the device has actually been removed as an interface, because:
+	 *
+	 * 1) if, as appears to be the case at least some of the time,
+	 * the PF_PACKET socket code first gets a NETDEV_DOWN indication
+	 * for the device and then gets a NETDEV_UNREGISTER indication
+	 * for it, the first indication will cause a wakeup with ENETDOWN
+	 * but won't set the packet socket's field for the interface index
+	 * to -1, and the second indication won't cause a wakeup (because
+	 * the first indication also caused the protocol hook to be
+	 * unregistered) but will set the packet socket's field for the
+	 * interface index to -1;
+	 *
+	 * 2) even if just a NETDEV_UNREGISTER indication is registered,
+	 * the packet socket's field for the interface index only gets
+	 * set to -1 after the wakeup, so there's a small but non-zero
+	 * risk that a thread blocked waiting for the wakeup will get
+	 * to the "fetch the socket name" code before the interface index
+	 * gets set to -1, so it'll get the old interface index.
+	 *
+	 * Therefore, if we got an ENETDOWN and haven't seen a packet
+	 * since then, we assume that we might be waiting for the interface
+	 * to disappear, and poll with a timeout to try again in a short
+	 * period of time.  If we *do* see a packet, the interface has
+	 * come back up again, and is *definitely* still there, so we
+	 * don't need to poll.
+	 */
+	for (;;) {
+	 	/*
 		 * Yes, we do this even in non-blocking mode, as it's
 		 * the only way to get error indications from a
 		 * tpacket socket.
@@ -4824,67 +3462,281 @@
 		 * The timeout is 0 in non-blocking mode, so poll()
 		 * returns immediately.
 		 */
-		ret = poll(&pollinfo, 1, handlep->poll_timeout);
-		if (ret < 0 && errno != EINTR) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno,
-			    "can't poll on packet socket");
-			return PCAP_ERROR;
-		} else if (ret > 0 &&
-			(pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
+		timeout = handlep->poll_timeout;
+
+		/*
+		 * If we got an ENETDOWN and haven't gotten an indication
+		 * that the device has gone away or that the device is up,
+		 * we don't yet know for certain whether the device has
+		 * gone away or not, do a poll() with a 1-millisecond timeout,
+		 * as we have to poll indefinitely for "device went away"
+		 * indications until we either get one or see that the
+		 * device is up.
+		 */
+		if (handlep->netdown) {
+			if (timeout != 0)
+				timeout = 1;
+		}
+		ret = poll(pollinfo, 2, timeout);
+		if (ret < 0) {
 			/*
-			 * There's some indication other than
-			 * "you can read on this descriptor" on
-			 * the descriptor.
+			 * Error.  If it's not EINTR, report it.
 			 */
-			if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
-				pcap_snprintf(handle->errbuf,
-					PCAP_ERRBUF_SIZE,
-					"Hangup on packet socket");
+			if (errno != EINTR) {
+				pcap_fmt_errmsg_for_errno(handle->errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "can't poll on packet socket");
 				return PCAP_ERROR;
 			}
-			if (pollinfo.revents & POLLERR) {
+
+			/*
+			 * It's EINTR; if we were told to break out of
+			 * the loop, do so.
+			 */
+			if (handle->break_loop) {
+				handle->break_loop = 0;
+				return PCAP_ERROR_BREAK;
+			}
+		} else if (ret > 0) {
+			/*
+			 * OK, some descriptor is ready.
+			 * Check the socket descriptor first.
+			 *
+			 * As I read the Linux man page, pollinfo[0].revents
+			 * will either be POLLIN, POLLERR, POLLHUP, or POLLNVAL.
+			 */
+			if (pollinfo[0].revents == POLLIN) {
 				/*
-				 * A recv() will give us the actual error code.
-				 *
-				 * XXX - make the socket non-blocking?
+				 * OK, we may have packets to
+				 * read.
 				 */
-				if (recv(handle->fd, &c, sizeof c,
-					MSG_PEEK) != -1)
-					continue;	/* what, no error? */
-				if (errno == ENETDOWN) {
+				break;
+			}
+			if (pollinfo[0].revents != 0) {
+				/*
+				 * There's some indication other than
+				 * "you can read on this descriptor" on
+				 * the descriptor.
+				 */
+				if (pollinfo[0].revents & POLLNVAL) {
+					snprintf(handle->errbuf,
+					    PCAP_ERRBUF_SIZE,
+					    "Invalid polling request on packet socket");
+					return PCAP_ERROR;
+				}
+				if (pollinfo[0].revents & (POLLHUP | POLLRDHUP)) {
+					snprintf(handle->errbuf,
+					    PCAP_ERRBUF_SIZE,
+					    "Hangup on packet socket");
+					return PCAP_ERROR;
+				}
+				if (pollinfo[0].revents & POLLERR) {
 					/*
-					 * 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.
+					 * Get the error.
 					 */
-					pcap_snprintf(handle->errbuf,
-						PCAP_ERRBUF_SIZE,
-						"The interface went down");
+					int err;
+					socklen_t errlen;
+
+					errlen = sizeof(err);
+					if (getsockopt(handle->fd, SOL_SOCKET,
+					    SO_ERROR, &err, &errlen) == -1) {
+						/*
+						 * The call *itself* returned
+						 * an error; make *that*
+						 * the error.
+						 */
+						err = errno;
+					}
+
+					/*
+					 * OK, we have the error.
+					 */
+					if (err == ENETDOWN) {
+						/*
+						 * The device on which we're
+						 * capturing went away or the
+						 * interface was taken down.
+						 *
+						 * We don't know for certain
+						 * which happened, and the
+						 * next poll() may indicate
+						 * that there are packets
+						 * to be read, so just set
+						 * a flag to get us to do
+						 * checks later, and set
+						 * the required select
+						 * timeout to 1 millisecond
+						 * so that event loops that
+						 * check our socket descriptor
+						 * also time out so that
+						 * they can call us and we
+						 * can do the checks.
+						 */
+						handlep->netdown = 1;
+						handle->required_select_timeout = &netdown_timeout;
+					} else if (err == 0) {
+						/*
+						 * This shouldn't happen, so
+						 * report a special indication
+						 * that it did.
+						 */
+						snprintf(handle->errbuf,
+						    PCAP_ERRBUF_SIZE,
+						    "Error condition on packet socket: Reported error was 0");
+						return PCAP_ERROR;
+					} else {
+						pcap_fmt_errmsg_for_errno(handle->errbuf,
+						    PCAP_ERRBUF_SIZE,
+						    err,
+						    "Error condition on packet socket");
+						return PCAP_ERROR;
+					}
+				}
+			}
+			/*
+			 * Now check the event device.
+			 */
+			if (pollinfo[1].revents & POLLIN) {
+				ssize_t nread;
+				uint64_t value;
+
+				/*
+				 * This should never fail, but, just
+				 * in case....
+				 */
+				nread = read(handlep->poll_breakloop_fd, &value,
+				    sizeof(value));
+				if (nread == -1) {
+					pcap_fmt_errmsg_for_errno(handle->errbuf,
+					    PCAP_ERRBUF_SIZE,
+					    errno,
+					    "Error reading from event FD");
+					return PCAP_ERROR;
+				}
+
+				/*
+				 * According to the Linux read(2) man
+				 * page, read() will transfer at most
+				 * 2^31-1 bytes, so the return value is
+				 * either -1 or a value between 0
+				 * and 2^31-1, so it's non-negative.
+				 *
+				 * Cast it to size_t to squelch
+				 * warnings from the compiler; add this
+				 * comment to squelch warnings from
+				 * humans reading the code. :-)
+				 *
+				 * Don't treat an EOF as an error, but
+				 * *do* treat a short read as an error;
+				 * that "shouldn't happen", but....
+				 */
+				if (nread != 0 &&
+				    (size_t)nread < sizeof(value)) {
+					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					    "Short read from event FD: expected %zu, got %zd",
+					    sizeof(value), nread);
+					return PCAP_ERROR;
+				}
+
+				/*
+				 * This event gets signaled by a
+				 * pcap_breakloop() call; if we were told
+				 * to break out of the loop, do so.
+				 */
+				if (handle->break_loop) {
+					handle->break_loop = 0;
+					return PCAP_ERROR_BREAK;
+				}
+			}
+		}
+
+		/*
+		 * Either:
+		 *
+		 *   1) we got neither an error from poll() nor any
+		 *      readable descriptors, in which case there
+		 *      are no packets waiting to read
+		 *
+		 * or
+		 *
+		 *   2) We got readable descriptors but the PF_PACKET
+		 *      socket wasn't one of them, in which case there
+		 *      are no packets waiting to read
+		 *
+		 * so, if we got an ENETDOWN, we've drained whatever
+		 * packets were available to read at the point of the
+		 * ENETDOWN.
+		 *
+		 * So, if we got an ENETDOWN and haven't gotten an indication
+		 * that the device has gone away or that the device is up,
+		 * we don't yet know for certain whether the device has
+		 * gone away or not, check whether the device exists and is
+		 * up.
+		 */
+		if (handlep->netdown) {
+			if (!device_still_exists(handle)) {
+				/*
+				 * The device doesn't exist any more;
+				 * report that.
+				 *
+				 * XXX - we should really return an
+				 * appropriate error for that, but
+				 * pcap_dispatch() etc. aren't documented
+				 * as having error returns other than
+				 * PCAP_ERROR or PCAP_ERROR_BREAK.
+				 */
+				snprintf(handle->errbuf,  PCAP_ERRBUF_SIZE,
+				    "The interface disappeared");
+				return PCAP_ERROR;
+			}
+
+			/*
+			 * The device still exists; try to see if it's up.
+			 */
+			memset(&ifr, 0, sizeof(ifr));
+			pcap_strlcpy(ifr.ifr_name, handlep->device,
+			    sizeof(ifr.ifr_name));
+			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+				if (errno == ENXIO || errno == ENODEV) {
+					/*
+					 * OK, *now* it's gone.
+					 *
+					 * XXX - see above comment.
+					 */
+					snprintf(handle->errbuf,
+					    PCAP_ERRBUF_SIZE,
+					    "The interface disappeared");
+					return PCAP_ERROR;
 				} else {
 					pcap_fmt_errmsg_for_errno(handle->errbuf,
 					    PCAP_ERRBUF_SIZE, errno,
-					    "Error condition on packet socket");
+					    "%s: Can't get flags",
+					    handlep->device);
+					return PCAP_ERROR;
 				}
-				return PCAP_ERROR;
 			}
-			if (pollinfo.revents & POLLNVAL) {
-				pcap_snprintf(handle->errbuf,
-					PCAP_ERRBUF_SIZE,
-					"Invalid polling request on packet socket");
-				return PCAP_ERROR;
+			if (ifr.ifr_flags & IFF_UP) {
+				/*
+				 * It's up, so it definitely still exists.
+				 * Cancel the ENETDOWN indication - we
+				 * presumably got it due to the interface
+				 * going down rather than the device going
+				 * away - and revert to "no required select
+				 * timeout.
+				 */
+				handlep->netdown = 0;
+				handle->required_select_timeout = NULL;
 			}
 		}
-		/* check for break loop condition on interrupted syscall*/
-		if (handle->break_loop) {
-			handle->break_loop = 0;
-			return PCAP_ERROR_BREAK;
-		}
-	} while (ret < 0);
+
+		/*
+		 * If we're in non-blocking mode, just quit now, rather
+		 * than spinning in a loop doing poll()s that immediately
+		 * time out if there's no indication on any descriptor.
+		 */
+		if (handlep->poll_timeout == 0)
+			break;
+	}
 	return 0;
 }
 
@@ -4908,13 +3760,27 @@
 	struct sockaddr_ll *sll;
 	struct pcap_pkthdr pcaphdr;
 	unsigned int snaplen = tp_snaplen;
+	struct utsname utsname;
 
 	/* perform sanity check on internal offset. */
 	if (tp_mac + tp_snaplen > handle->bufsize) {
-		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);
+		/*
+		 * Report some system information as a debugging aid.
+		 */
+		if (uname(&utsname) != -1) {
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				"corrupted frame on kernel ring mac "
+				"offset %u + caplen %u > frame len %d "
+				"(kernel %.32s version %s, machine %.16s)",
+				tp_mac, tp_snaplen, handle->bufsize,
+				utsname.release, utsname.version,
+				utsname.machine);
+		} else {
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				"corrupted frame on kernel ring mac "
+				"offset %u + caplen %u > frame len %d",
+				tp_mac, tp_snaplen, handle->bufsize);
+		}
 		return -1;
 	}
 
@@ -4930,46 +3796,87 @@
 	bp = frame + tp_mac;
 
 	/* if required build in place the sll header*/
-	sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
+	sll = (void *)(frame + TPACKET_ALIGN(handlep->tp_hdrlen));
 	if (handlep->cooked) {
-		struct sll_header *hdrp;
+		if (handle->linktype == DLT_LINUX_SLL2) {
+			struct sll2_header *hdrp;
 
-		/*
-		 * The kernel should have left us with enough
-		 * space for an sll header; back up the packet
-		 * data pointer into that space, as that'll be
-		 * the beginning of the packet we pass to the
-		 * callback.
-		 */
-		bp -= SLL_HDR_LEN;
+			/*
+			 * The kernel should have left us with enough
+			 * space for an sll header; back up the packet
+			 * data pointer into that space, as that'll be
+			 * the beginning of the packet we pass to the
+			 * callback.
+			 */
+			bp -= SLL2_HDR_LEN;
 
-		/*
-		 * Let's make sure that's past the end of
-		 * the tpacket header, i.e. >=
-		 * ((u_char *)thdr + TPACKET_HDRLEN), so we
-		 * don't step on the header when we construct
-		 * the sll header.
-		 */
-		if (bp < (u_char *)frame +
-				   TPACKET_ALIGN(handlep->tp_hdrlen) +
-				   sizeof(struct sockaddr_ll)) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				"cooked-mode frame doesn't have room for sll header");
-			return -1;
+			/*
+			 * Let's make sure that's past the end of
+			 * the tpacket header, i.e. >=
+			 * ((u_char *)thdr + TPACKET_HDRLEN), so we
+			 * don't step on the header when we construct
+			 * the sll header.
+			 */
+			if (bp < (u_char *)frame +
+					   TPACKET_ALIGN(handlep->tp_hdrlen) +
+					   sizeof(struct sockaddr_ll)) {
+				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					"cooked-mode frame doesn't have room for sll header");
+				return -1;
+			}
+
+			/*
+			 * OK, that worked; construct the sll header.
+			 */
+			hdrp = (struct sll2_header *)bp;
+			hdrp->sll2_protocol = sll->sll_protocol;
+			hdrp->sll2_reserved_mbz = 0;
+			hdrp->sll2_if_index = htonl(sll->sll_ifindex);
+			hdrp->sll2_hatype = htons(sll->sll_hatype);
+			hdrp->sll2_pkttype = sll->sll_pkttype;
+			hdrp->sll2_halen = sll->sll_halen;
+			memcpy(hdrp->sll2_addr, sll->sll_addr, SLL_ADDRLEN);
+
+			snaplen += sizeof(struct sll2_header);
+		} else {
+			struct sll_header *hdrp;
+
+			/*
+			 * The kernel should have left us with enough
+			 * space for an sll header; back up the packet
+			 * data pointer into that space, as that'll be
+			 * the beginning of the packet we pass to the
+			 * callback.
+			 */
+			bp -= SLL_HDR_LEN;
+
+			/*
+			 * Let's make sure that's past the end of
+			 * the tpacket header, i.e. >=
+			 * ((u_char *)thdr + TPACKET_HDRLEN), so we
+			 * don't step on the header when we construct
+			 * the sll header.
+			 */
+			if (bp < (u_char *)frame +
+					   TPACKET_ALIGN(handlep->tp_hdrlen) +
+					   sizeof(struct sockaddr_ll)) {
+				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					"cooked-mode frame doesn't have room for sll header");
+				return -1;
+			}
+
+			/*
+			 * OK, that worked; construct the sll header.
+			 */
+			hdrp = (struct sll_header *)bp;
+			hdrp->sll_pkttype = htons(sll->sll_pkttype);
+			hdrp->sll_hatype = htons(sll->sll_hatype);
+			hdrp->sll_halen = htons(sll->sll_halen);
+			memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
+			hdrp->sll_protocol = sll->sll_protocol;
+
+			snaplen += sizeof(struct sll_header);
 		}
-
-		/*
-		 * OK, that worked; construct the sll header.
-		 */
-		hdrp = (struct sll_header *)bp;
-		hdrp->sll_pkttype = map_packet_type_to_sll_type(
-						sll->sll_pkttype);
-		hdrp->sll_hatype = htons(sll->sll_hatype);
-		hdrp->sll_halen = htons(sll->sll_halen);
-		memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
-		hdrp->sll_protocol = sll->sll_protocol;
-
-		snaplen += sizeof(struct sll_header);
 	}
 
 	if (handlep->filter_in_userland && handle->fcode.bf_insns) {
@@ -4978,11 +3885,11 @@
 		aux_data.vlan_tag_present = tp_vlan_tci_valid;
 		aux_data.vlan_tag = tp_vlan_tci & 0x0fff;
 
-		if (bpf_filter_with_aux_data(handle->fcode.bf_insns,
-					     bp,
-					     tp_len,
-					     snaplen,
-					     &aux_data) == 0)
+		if (pcap_filter_with_aux_data(handle->fcode.bf_insns,
+					      bp,
+					      tp_len,
+					      snaplen,
+					      &aux_data) == 0)
 			return 0;
 	}
 
@@ -4998,11 +3905,15 @@
 	/* if required build in place the sll header*/
 	if (handlep->cooked) {
 		/* update packet len */
-		pcaphdr.caplen += SLL_HDR_LEN;
-		pcaphdr.len += SLL_HDR_LEN;
+		if (handle->linktype == DLT_LINUX_SLL2) {
+			pcaphdr.caplen += SLL2_HDR_LEN;
+			pcaphdr.len += SLL2_HDR_LEN;
+		} else {
+			pcaphdr.caplen += SLL_HDR_LEN;
+			pcaphdr.len += SLL_HDR_LEN;
+		}
 	}
 
-#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
 	if (tp_vlan_tci_valid &&
 		handlep->vlan_offset != -1 &&
 		tp_snaplen >= (unsigned int) handlep->vlan_offset)
@@ -5030,7 +3941,6 @@
 		pcaphdr.caplen += VLAN_TAG_LEN;
 		pcaphdr.len += VLAN_TAG_LEN;
 	}
-#endif
 
 	/*
 	 * The only way to tell the kernel to cut off the
@@ -5040,6 +3950,13 @@
 	 *
 	 * Trim the snapshot length to be no longer than the
 	 * specified snapshot length.
+	 *
+	 * XXX - an alternative is to put a filter, consisting
+	 * of a "ret <snaplen>" instruction, on the socket
+	 * in the activate routine, so that the truncation is
+	 * done in the kernel even if nobody specified a filter;
+	 * that means that less buffer space is consumed in
+	 * the memory-mapped buffer.
 	 */
 	if (pcaphdr.caplen > (bpf_u_int32)handle->snapshot)
 		pcaphdr.caplen = handle->snapshot;
@@ -5051,175 +3968,6 @@
 }
 
 static int
-pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
-		u_char *user)
-{
-	struct pcap_linux *handlep = handle->priv;
-	union thdr h;
-	int pkts = 0;
-	int ret;
-
-	/* wait for frames availability.*/
-	h.raw = RING_GET_CURRENT_FRAME(handle);
-	if (h.h1->tp_status == TP_STATUS_KERNEL) {
-		/*
-		 * The current frame is owned by the kernel; wait for
-		 * a frame to be handed to us.
-		 */
-		ret = pcap_wait_for_frames_mmap(handle);
-		if (ret) {
-			return ret;
-		}
-	}
-
-	/* non-positive values of max_packets are used to require all
-	 * packets currently available in the ring */
-	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
-		/*
-		 * Get the current ring buffer frame, and break if
-		 * it's still owned by the kernel.
-		 */
-		h.raw = RING_GET_CURRENT_FRAME(handle);
-		if (h.h1->tp_status == TP_STATUS_KERNEL)
-			break;
-
-		ret = pcap_handle_packet_mmap(
-				handle,
-				callback,
-				user,
-				h.raw,
-				h.h1->tp_len,
-				h.h1->tp_mac,
-				h.h1->tp_snaplen,
-				h.h1->tp_sec,
-				h.h1->tp_usec,
-				0,
-				0,
-				0);
-		if (ret == 1) {
-			pkts++;
-			handlep->packets_read++;
-		} else if (ret < 0) {
-			return ret;
-		}
-
-		/*
-		 * Hand this block back to the kernel, and, if we're
-		 * counting blocks that need to be filtered in userland
-		 * after having been filtered by the kernel, count
-		 * the one we've just processed.
-		 */
-		h.h1->tp_status = TP_STATUS_KERNEL;
-		if (handlep->blocks_to_filter_in_userland > 0) {
-			handlep->blocks_to_filter_in_userland--;
-			if (handlep->blocks_to_filter_in_userland == 0) {
-				/*
-				 * No more blocks need to be filtered
-				 * in userland.
-				 */
-				handlep->filter_in_userland = 0;
-			}
-		}
-
-		/* next block */
-		if (++handle->offset >= handle->cc)
-			handle->offset = 0;
-
-		/* check for break loop condition*/
-		if (handle->break_loop) {
-			handle->break_loop = 0;
-			return PCAP_ERROR_BREAK;
-		}
-	}
-	return pkts;
-}
-
-static int
-pcap_read_linux_mmap_v1_64(pcap_t *handle, int max_packets, pcap_handler callback,
-		u_char *user)
-{
-	struct pcap_linux *handlep = handle->priv;
-	union thdr h;
-	int pkts = 0;
-	int ret;
-
-	/* wait for frames availability.*/
-	h.raw = RING_GET_CURRENT_FRAME(handle);
-	if (h.h1_64->tp_status == TP_STATUS_KERNEL) {
-		/*
-		 * The current frame is owned by the kernel; wait for
-		 * a frame to be handed to us.
-		 */
-		ret = pcap_wait_for_frames_mmap(handle);
-		if (ret) {
-			return ret;
-		}
-	}
-
-	/* non-positive values of max_packets are used to require all
-	 * packets currently available in the ring */
-	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
-		/*
-		 * Get the current ring buffer frame, and break if
-		 * it's still owned by the kernel.
-		 */
-		h.raw = RING_GET_CURRENT_FRAME(handle);
-		if (h.h1_64->tp_status == TP_STATUS_KERNEL)
-			break;
-
-		ret = pcap_handle_packet_mmap(
-				handle,
-				callback,
-				user,
-				h.raw,
-				h.h1_64->tp_len,
-				h.h1_64->tp_mac,
-				h.h1_64->tp_snaplen,
-				h.h1_64->tp_sec,
-				h.h1_64->tp_usec,
-				0,
-				0,
-				0);
-		if (ret == 1) {
-			pkts++;
-			handlep->packets_read++;
-		} else if (ret < 0) {
-			return ret;
-		}
-
-		/*
-		 * Hand this block back to the kernel, and, if we're
-		 * counting blocks that need to be filtered in userland
-		 * after having been filtered by the kernel, count
-		 * the one we've just processed.
-		 */
-		h.h1_64->tp_status = TP_STATUS_KERNEL;
-		if (handlep->blocks_to_filter_in_userland > 0) {
-			handlep->blocks_to_filter_in_userland--;
-			if (handlep->blocks_to_filter_in_userland == 0) {
-				/*
-				 * No more blocks need to be filtered
-				 * in userland.
-				 */
-				handlep->filter_in_userland = 0;
-			}
-		}
-
-		/* next block */
-		if (++handle->offset >= handle->cc)
-			handle->offset = 0;
-
-		/* check for break loop condition*/
-		if (handle->break_loop) {
-			handle->break_loop = 0;
-			return PCAP_ERROR_BREAK;
-		}
-	}
-	return pkts;
-}
-
-#ifdef HAVE_TPACKET2
-static int
 pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
 		u_char *user)
 {
@@ -5230,7 +3978,7 @@
 
 	/* wait for frames availability.*/
 	h.raw = RING_GET_CURRENT_FRAME(handle);
-	if (h.h2->tp_status == TP_STATUS_KERNEL) {
+	if (!packet_mmap_acquire(h.h2)) {
 		/*
 		 * The current frame is owned by the kernel; wait for
 		 * a frame to be handed to us.
@@ -5249,7 +3997,7 @@
 		 * it's still owned by the kernel.
 		 */
 		h.raw = RING_GET_CURRENT_FRAME(handle);
-		if (h.h2->tp_status == TP_STATUS_KERNEL)
+		if (!packet_mmap_acquire(h.h2))
 			break;
 
 		ret = pcap_handle_packet_mmap(
@@ -5267,7 +4015,6 @@
 				VLAN_TPID(h.h2, h.h2));
 		if (ret == 1) {
 			pkts++;
-			handlep->packets_read++;
 		} else if (ret < 0) {
 			return ret;
 		}
@@ -5278,7 +4025,7 @@
 		 * after having been filtered by the kernel, count
 		 * the one we've just processed.
 		 */
-		h.h2->tp_status = TP_STATUS_KERNEL;
+		packet_mmap_release(h.h2);
 		if (handlep->blocks_to_filter_in_userland > 0) {
 			handlep->blocks_to_filter_in_userland--;
 			if (handlep->blocks_to_filter_in_userland == 0) {
@@ -5302,7 +4049,6 @@
 	}
 	return pkts;
 }
-#endif /* HAVE_TPACKET2 */
 
 #ifdef HAVE_TPACKET3
 static int
@@ -5318,7 +4064,7 @@
 	if (handlep->current_packet == NULL) {
 		/* wait for frames availability.*/
 		h.raw = RING_GET_CURRENT_FRAME(handle);
-		if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+		if (!packet_mmap_v3_acquire(h.h3)) {
 			/*
 			 * The current frame is owned by the kernel; wait
 			 * for a frame to be handed to us.
@@ -5330,7 +4076,7 @@
 		}
 	}
 	h.raw = RING_GET_CURRENT_FRAME(handle);
-	if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+	if (!packet_mmap_v3_acquire(h.h3)) {
 		if (pkts == 0 && handlep->timeout == 0) {
 			/* Block until we see a packet. */
 			goto again;
@@ -5345,7 +4091,7 @@
 
 		if (handlep->current_packet == NULL) {
 			h.raw = RING_GET_CURRENT_FRAME(handle);
-			if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL)
+			if (!packet_mmap_v3_acquire(h.h3))
 				break;
 
 			handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
@@ -5381,7 +4127,6 @@
 					VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
 			if (ret == 1) {
 				pkts++;
-				handlep->packets_read++;
 			} else if (ret < 0) {
 				handlep->current_packet = NULL;
 				return ret;
@@ -5398,7 +4143,7 @@
 			 * filtered by the kernel, count the one we've
 			 * just processed.
 			 */
-			h.h3->hdr.bh1.block_status = TP_STATUS_KERNEL;
+			packet_mmap_v3_release(h.h3);
 			if (handlep->blocks_to_filter_in_userland > 0) {
 				handlep->blocks_to_filter_in_userland--;
 				if (handlep->blocks_to_filter_in_userland == 0) {
@@ -5431,29 +4176,180 @@
 }
 #endif /* HAVE_TPACKET3 */
 
+/*
+ *  Attach the given BPF code to the packet capture device.
+ */
 static int
-pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
+pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
 {
-	struct pcap_linux *handlep = handle->priv;
-	int n, offset;
-	int ret;
+	struct pcap_linux *handlep;
+	struct sock_fprog	fcode;
+	int			can_filter_in_kernel;
+	int			err = 0;
+	int			n, offset;
+
+	if (!handle)
+		return -1;
+	if (!filter) {
+	        pcap_strlcpy(handle->errbuf, "setfilter: No filter specified",
+			PCAP_ERRBUF_SIZE);
+		return -1;
+	}
+
+	handlep = handle->priv;
+
+	/* Make our private copy of the filter */
+
+	if (install_bpf_program(handle, filter) < 0)
+		/* install_bpf_program() filled in errbuf */
+		return -1;
 
 	/*
-	 * Don't rewrite "ret" instructions; we don't need to, as
-	 * we're not reading packets with recvmsg(), and we don't
-	 * want to, as, by not rewriting them, the kernel can avoid
-	 * copying extra data.
+	 * Run user level packet filter by default. Will be overridden if
+	 * installing a kernel filter succeeds.
 	 */
-	ret = pcap_setfilter_linux_common(handle, filter, 1);
-	if (ret < 0)
-		return ret;
+	handlep->filter_in_userland = 1;
+
+	/* Install kernel level filter if possible */
+
+#ifdef USHRT_MAX
+	if (handle->fcode.bf_len > USHRT_MAX) {
+		/*
+		 * fcode.len is an unsigned short for current kernel.
+		 * I have yet to see BPF-Code with that much
+		 * instructions but still it is possible. So for the
+		 * sake of correctness I added this check.
+		 */
+		fprintf(stderr, "Warning: Filter too complex for kernel\n");
+		fcode.len = 0;
+		fcode.filter = NULL;
+		can_filter_in_kernel = 0;
+	} else
+#endif /* USHRT_MAX */
+	{
+		/*
+		 * Oh joy, the Linux kernel uses struct sock_fprog instead
+		 * of struct bpf_program and of course the length field is
+		 * of different size. Pointed out by Sebastian
+		 *
+		 * Oh, and we also need to fix it up so that all "ret"
+		 * instructions with non-zero operands have MAXIMUM_SNAPLEN
+		 * as the operand if we're not capturing in memory-mapped
+		 * mode, and so that, if we're in cooked mode, all memory-
+		 * reference instructions use special magic offsets in
+		 * references to the link-layer header and assume that the
+		 * link-layer payload begins at 0; "fix_program()" will do
+		 * that.
+		 */
+		switch (fix_program(handle, &fcode)) {
+
+		case -1:
+		default:
+			/*
+			 * Fatal error; just quit.
+			 * (The "default" case shouldn't happen; we
+			 * return -1 for that reason.)
+			 */
+			return -1;
+
+		case 0:
+			/*
+			 * The program performed checks that we can't make
+			 * work in the kernel.
+			 */
+			can_filter_in_kernel = 0;
+			break;
+
+		case 1:
+			/*
+			 * We have a filter that'll work in the kernel.
+			 */
+			can_filter_in_kernel = 1;
+			break;
+		}
+	}
+
+	/*
+	 * NOTE: at this point, we've set both the "len" and "filter"
+	 * fields of "fcode".  As of the 2.6.32.4 kernel, at least,
+	 * those are the only members of the "sock_fprog" structure,
+	 * so we initialize every member of that structure.
+	 *
+	 * If there is anything in "fcode" that is not initialized,
+	 * it is either a field added in a later kernel, or it's
+	 * padding.
+	 *
+	 * If a new field is added, this code needs to be updated
+	 * to set it correctly.
+	 *
+	 * If there are no other fields, then:
+	 *
+	 *	if the Linux kernel looks at the padding, it's
+	 *	buggy;
+	 *
+	 *	if the Linux kernel doesn't look at the padding,
+	 *	then if some tool complains that we're passing
+	 *	uninitialized data to the kernel, then the tool
+	 *	is buggy and needs to understand that it's just
+	 *	padding.
+	 */
+	if (can_filter_in_kernel) {
+		if ((err = set_kernel_filter(handle, &fcode)) == 0)
+		{
+			/*
+			 * Installation succeeded - using kernel filter,
+			 * so userland filtering not needed.
+			 */
+			handlep->filter_in_userland = 0;
+		}
+		else if (err == -1)	/* Non-fatal error */
+		{
+			/*
+			 * Print a warning if we weren't able to install
+			 * the filter for a reason other than "this kernel
+			 * isn't configured to support socket filters.
+			 */
+			if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
+				fprintf(stderr,
+				    "Warning: Kernel filter failed: %s\n",
+					pcap_strerror(errno));
+			}
+		}
+	}
+
+	/*
+	 * If we're not using the kernel filter, get rid of any kernel
+	 * filter that might've been there before, e.g. because the
+	 * previous filter could work in the kernel, or because some other
+	 * code attached a filter to the socket by some means other than
+	 * calling "pcap_setfilter()".  Otherwise, the kernel filter may
+	 * filter out packets that would pass the new userland filter.
+	 */
+	if (handlep->filter_in_userland) {
+		if (reset_kernel_filter(handle) == -1) {
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno,
+			    "can't remove kernel filter");
+			err = -2;	/* fatal error */
+		}
+	}
+
+	/*
+	 * Free up the copy of the filter that was made by "fix_program()".
+	 */
+	if (fcode.filter != NULL)
+		free(fcode.filter);
+
+	if (err == -2)
+		/* Fatal error */
+		return -1;
 
 	/*
 	 * If we're filtering in userland, there's nothing to do;
 	 * the new filter will be used for the next packet.
 	 */
 	if (handlep->filter_in_userland)
-		return ret;
+		return 0;
 
 	/*
 	 * We're filtering in the kernel; the packets present in
@@ -5504,13 +4400,10 @@
 	 */
 	handlep->blocks_to_filter_in_userland = handle->cc - n;
 	handlep->filter_in_userland = 1;
-	return ret;
+
+	return 0;
 }
 
-#endif /* HAVE_PACKET_RING */
-
-
-#ifdef HAVE_PF_PACKET_SOCKETS
 /*
  *  Return the index of the given device name. Fill ebuf and return
  *  -1 on failure.
@@ -5521,7 +4414,7 @@
 	struct ifreq	ifr;
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
@@ -5534,19 +4427,18 @@
 
 /*
  *  Bind the socket associated with FD to the given device.
- *  Return 1 on success, 0 if we should try a SOCK_PACKET socket,
- *  or a PCAP_ERROR_ value on a hard error.
+ *  Return 0 on success or a PCAP_ERROR_ value on a hard error.
  */
 static int
 iface_bind(int fd, int ifindex, char *ebuf, int protocol)
 {
 	struct sockaddr_ll	sll;
-	int			err;
+	int			ret, err;
 	socklen_t		errlen = sizeof(err);
 
 	memset(&sll, 0, sizeof(sll));
 	sll.sll_family		= AF_PACKET;
-	sll.sll_ifindex		= ifindex;
+	sll.sll_ifindex		= ifindex < 0 ? 0 : ifindex;
 	sll.sll_protocol	= protocol;
 
 	if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
@@ -5559,19 +4451,22 @@
 			 * libpcap developers.
 			 */
 			return PCAP_ERROR_IFACE_NOT_UP;
-		} else {
-			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-			    errno, "bind");
-			return PCAP_ERROR;
 		}
+		if (errno == ENODEV)
+			ret = PCAP_ERROR_NO_SUCH_DEVICE;
+		else
+			ret = PCAP_ERROR;
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "bind");
+		return ret;
 	}
 
 	/* Any pending errors, e.g., network is down? */
 
 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-		    errno, "getsockopt");
-		return 0;
+		    errno, "getsockopt (SO_ERROR)");
+		return PCAP_ERROR;
 	}
 
 	if (err == ENETDOWN) {
@@ -5586,388 +4481,89 @@
 	} else if (err > 0) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 		    err, "bind");
-		return 0;
+		return PCAP_ERROR;
 	}
 
-	return 1;
-}
-
-#ifdef IW_MODE_MONITOR
-/*
- * Check whether the device supports the Wireless Extensions.
- * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE
- * if the device doesn't even exist.
- */
-static int
-has_wext(int sock_fd, const char *device, char *ebuf)
-{
-	struct iwreq ireq;
-
-	if (is_bonding_device(sock_fd, device))
-		return 0;	/* bonding device, so don't even try */
-
-	strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-	    sizeof ireq.ifr_ifrn.ifrn_name);
-	if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
-		return 1;	/* yes */
-	pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
-	    "%s: SIOCGIWNAME", device);
-	if (errno == ENODEV)
-		return PCAP_ERROR_NO_SUCH_DEVICE;
 	return 0;
 }
 
 /*
- * Per me si va ne la citta dolente,
- * Per me si va ne l'etterno dolore,
- *	...
- * Lasciate ogne speranza, voi ch'intrate.
- *
- * XXX - airmon-ng does special stuff with the Orinoco driver and the
- * wlan-ng driver.
+ * Try to enter monitor mode.
+ * If we have libnl, try to create a new monitor-mode device and
+ * capture on that; otherwise, just say "not supported".
  */
-typedef enum {
-	MONITOR_WEXT,
-	MONITOR_HOSTAP,
-	MONITOR_PRISM,
-	MONITOR_PRISM54,
-	MONITOR_ACX100,
-	MONITOR_RT2500,
-	MONITOR_RT2570,
-	MONITOR_RT73,
-	MONITOR_RTL8XXX
-} monitor_type;
-
-/*
- * Use the Wireless Extensions, if we have them, to try to turn monitor mode
- * on if it's not already on.
- *
- * Returns 1 on success, 0 if we don't support the Wireless Extensions
- * on this device, or a PCAP_ERROR_ value if we do support them but
- * we weren't able to turn monitor mode on.
- */
+#ifdef HAVE_LIBNL
 static int
-enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
+enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
 {
-	/*
-	 * XXX - at least some adapters require non-Wireless Extensions
-	 * mechanisms to turn monitor mode on.
-	 *
-	 * Atheros cards might require that a separate "monitor virtual access
-	 * point" be created, with later versions of the madwifi driver.
-	 * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode
-	 * monitor -bssid", which apparently spits out a line "athN"
-	 * where "athN" is the monitor mode device.  To leave monitor
-	 * mode, it destroys the monitor mode device.
-	 *
-	 * Some Intel Centrino adapters might require private ioctls to get
-	 * radio headers; the ipw2200 and ipw3945 drivers allow you to
-	 * configure a separate "rtapN" interface to capture in monitor
-	 * mode without preventing the adapter from operating normally.
-	 * (airmon-ng doesn't appear to use that, though.)
-	 *
-	 * It would be Truly Wonderful if mac80211 and nl80211 cleaned this
-	 * up, and if all drivers were converted to mac80211 drivers.
-	 *
-	 * If interface {if} is a mac80211 driver, the file
-	 * /sys/class/net/{if}/phy80211 is a symlink to
-	 * /sys/class/ieee80211/{phydev}, for some {phydev}.
-	 *
-	 * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
-	 * least, has a "wmaster0" device and a "wlan0" device; the
-	 * latter is the one with the IP address.  Both show up in
-	 * "tcpdump -D" output.  Capturing on the wmaster0 device
-	 * captures with 802.11 headers.
-	 *
-	 * airmon-ng searches through /sys/class/net for devices named
-	 * monN, starting with mon0; as soon as one *doesn't* exist,
-	 * it chooses that as the monitor device name.  If the "iw"
-	 * command exists, it does "iw dev {if} interface add {monif}
-	 * type monitor", where {monif} is the monitor device.  It
-	 * then (sigh) sleeps .1 second, and then configures the
-	 * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
-	 * is a file, it writes {mondev}, without a newline, to that file,
-	 * and again (sigh) sleeps .1 second, and then iwconfig's that
-	 * device into monitor mode and configures it up.  Otherwise,
-	 * you can't do monitor mode.
-	 *
-	 * All these devices are "glued" together by having the
-	 * /sys/class/net/{device}/phy80211 links pointing to the same
-	 * place, so, given a wmaster, wlan, or mon device, you can
-	 * find the other devices by looking for devices with
-	 * the same phy80211 link.
-	 *
-	 * To turn monitor mode off, delete the monitor interface,
-	 * either with "iw dev {monif} interface del" or by sending
-	 * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
-	 *
-	 * Note: if you try to create a monitor device named "monN", and
-	 * there's already a "monN" device, it fails, as least with
-	 * the netlink interface (which is what iw uses), with a return
-	 * value of -ENFILE.  (Return values are negative errnos.)  We
-	 * could probably use that to find an unused device.
-	 */
 	struct pcap_linux *handlep = handle->priv;
-	int err;
-	struct iwreq ireq;
-	struct iw_priv_args *priv;
-	monitor_type montype;
-	int i;
-	__u32 cmd;
+	int ret;
+	char phydev_path[PATH_MAX+1];
+	struct nl80211_state nlstate;
 	struct ifreq ifr;
-	int oldflags;
-	int args[2];
-	int channel;
+	u_int n;
 
 	/*
-	 * Does this device *support* the Wireless Extensions?
+	 * Is this a mac80211 device?
 	 */
-	err = has_wext(sock_fd, device, handle->errbuf);
-	if (err <= 0)
-		return err;	/* either it doesn't or the device doesn't even exist */
-	/*
-	 * Start out assuming we have no private extensions to control
-	 * radio metadata.
-	 */
-	montype = MONITOR_WEXT;
-	cmd = 0;
+	ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
+	if (ret < 0)
+		return ret;	/* error */
+	if (ret == 0)
+		return 0;	/* no error, but not mac80211 device */
 
 	/*
-	 * Try to get all the Wireless Extensions private ioctls
-	 * supported by this device.
-	 *
-	 * First, get the size of the buffer we need, by supplying no
-	 * buffer and a length of 0.  If the device supports private
-	 * ioctls, it should return E2BIG, with ireq.u.data.length set
-	 * to the length we need.  If it doesn't support them, it should
-	 * return EOPNOTSUPP.
+	 * XXX - is this already a monN device?
+	 * If so, we're done.
 	 */
-	memset(&ireq, 0, sizeof ireq);
-	strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-	    sizeof ireq.ifr_ifrn.ifrn_name);
-	ireq.u.data.pointer = (void *)args;
-	ireq.u.data.length = 0;
-	ireq.u.data.flags = 0;
-	if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
-		    device);
-		return PCAP_ERROR;
-	}
-	if (errno != EOPNOTSUPP) {
+
+	/*
+	 * OK, it's apparently a mac80211 device.
+	 * Try to find an unused monN device for it.
+	 */
+	ret = nl80211_init(handle, &nlstate, device);
+	if (ret != 0)
+		return ret;
+	for (n = 0; n < UINT_MAX; n++) {
 		/*
-		 * OK, it's not as if there are no private ioctls.
+		 * Try mon{n}.
 		 */
-		if (errno != E2BIG) {
+		char mondevice[3+10+1];	/* mon{UINT_MAX}\0 */
+
+		snprintf(mondevice, sizeof mondevice, "mon%u", n);
+		ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
+		if (ret == 1) {
 			/*
-			 * Failed.
+			 * Success.  We don't clean up the libnl state
+			 * yet, as we'll be using it later.
 			 */
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
-			return PCAP_ERROR;
+			goto added;
 		}
-
-		/*
-		 * OK, try to get the list of private ioctls.
-		 */
-		priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
-		if (priv == NULL) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "malloc");
-			return PCAP_ERROR;
+		if (ret < 0) {
+			/*
+			 * Hard failure.  Just return ret; handle->errbuf
+			 * has already been set.
+			 */
+			nl80211_cleanup(&nlstate);
+			return ret;
 		}
-		ireq.u.data.pointer = (void *)priv;
-		if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
-			free(priv);
-			return PCAP_ERROR;
-		}
-
-		/*
-		 * Look for private ioctls to turn monitor mode on or, if
-		 * monitor mode is on, to set the header type.
-		 */
-		for (i = 0; i < ireq.u.data.length; i++) {
-			if (strcmp(priv[i].name, "monitor_type") == 0) {
-				/*
-				 * Hostap driver, use this one.
-				 * Set monitor mode first.
-				 * You can set it to 0 to get DLT_IEEE80211,
-				 * 1 to get DLT_PRISM, 2 to get
-				 * DLT_IEEE80211_RADIO_AVS, and, with more
-				 * recent versions of the driver, 3 to get
-				 * DLT_IEEE80211_RADIO.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
-					break;
-				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
-					break;
-				montype = MONITOR_HOSTAP;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "set_prismhdr") == 0) {
-				/*
-				 * Prism54 driver, use this one.
-				 * Set monitor mode first.
-				 * You can set it to 2 to get DLT_IEEE80211
-				 * or 3 or get DLT_PRISM.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
-					break;
-				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
-					break;
-				montype = MONITOR_PRISM54;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "forceprismheader") == 0) {
-				/*
-				 * RT2570 driver, use this one.
-				 * Do this after turning monitor mode on.
-				 * You can set it to 1 to get DLT_PRISM or 2
-				 * to get DLT_IEEE80211.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
-					break;
-				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
-					break;
-				montype = MONITOR_RT2570;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "forceprism") == 0) {
-				/*
-				 * RT73 driver, use this one.
-				 * Do this after turning monitor mode on.
-				 * Its argument is a *string*; you can
-				 * set it to "1" to get DLT_PRISM or "2"
-				 * to get DLT_IEEE80211.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
-					break;
-				if (priv[i].set_args & IW_PRIV_SIZE_FIXED)
-					break;
-				montype = MONITOR_RT73;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "prismhdr") == 0) {
-				/*
-				 * One of the RTL8xxx drivers, use this one.
-				 * It can only be done after monitor mode
-				 * has been turned on.  You can set it to 1
-				 * to get DLT_PRISM or 0 to get DLT_IEEE80211.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
-					break;
-				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
-					break;
-				montype = MONITOR_RTL8XXX;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "rfmontx") == 0) {
-				/*
-				 * RT2500 or RT61 driver, use this one.
-				 * It has one one-byte parameter; set
-				 * u.data.length to 1 and u.data.pointer to
-				 * point to the parameter.
-				 * It doesn't itself turn monitor mode on.
-				 * You can set it to 1 to allow transmitting
-				 * in monitor mode(?) and get DLT_IEEE80211,
-				 * or set it to 0 to disallow transmitting in
-				 * monitor mode(?) and get DLT_PRISM.
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2)
-					break;
-				montype = MONITOR_RT2500;
-				cmd = priv[i].cmd;
-				break;
-			}
-			if (strcmp(priv[i].name, "monitor") == 0) {
-				/*
-				 * Either ACX100 or hostap, use this one.
-				 * It turns monitor mode on.
-				 * If it takes two arguments, it's ACX100;
-				 * the first argument is 1 for DLT_PRISM
-				 * or 2 for DLT_IEEE80211, and the second
-				 * argument is the channel on which to
-				 * run.  If it takes one argument, it's
-				 * HostAP, and the argument is 2 for
-				 * DLT_IEEE80211 and 3 for DLT_PRISM.
-				 *
-				 * If we see this, we don't quit, as this
-				 * might be a version of the hostap driver
-				 * that also supports "monitor_type".
-				 */
-				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
-					break;
-				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
-					break;
-				switch (priv[i].set_args & IW_PRIV_SIZE_MASK) {
-
-				case 1:
-					montype = MONITOR_PRISM;
-					cmd = priv[i].cmd;
-					break;
-
-				case 2:
-					montype = MONITOR_ACX100;
-					cmd = priv[i].cmd;
-					break;
-
-				default:
-					break;
-				}
-			}
-		}
-		free(priv);
 	}
 
-	/*
-	 * XXX - ipw3945?  islism?
-	 */
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	    "%s: No free monN interfaces", device);
+	nl80211_cleanup(&nlstate);
+	return PCAP_ERROR;
 
-	/*
-	 * Get the old mode.
-	 */
-	strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-	    sizeof ireq.ifr_ifrn.ifrn_name);
-	if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
-		/*
-		 * We probably won't be able to set the mode, either.
-		 */
-		return PCAP_ERROR_RFMON_NOTSUP;
-	}
+added:
 
+#if 0
 	/*
-	 * Is it currently in monitor mode?
+	 * Sleep for .1 seconds.
 	 */
-	if (ireq.u.mode == IW_MODE_MONITOR) {
-		/*
-		 * Yes.  Just leave things as they are.
-		 * We don't offer multiple link-layer types, as
-		 * changing the link-layer type out from under
-		 * somebody else capturing in monitor mode would
-		 * be considered rude.
-		 */
-		return 1;
-	}
-	/*
-	 * No.  We have to put the adapter into rfmon mode.
-	 */
+	delay.tv_sec = 0;
+	delay.tv_nsec = 500000000;
+	nanosleep(&delay, NULL);
+#endif
 
 	/*
 	 * If we haven't already done so, arrange to have
@@ -5978,277 +4574,47 @@
 		 * "atexit()" failed; don't put the interface
 		 * in rfmon mode, just give up.
 		 */
-		return PCAP_ERROR_RFMON_NOTSUP;
-	}
-
-	/*
-	 * Save the old mode.
-	 */
-	handlep->oldmode = ireq.u.mode;
-
-	/*
-	 * Put the adapter in rfmon mode.  How we do this depends
-	 * on whether we have a special private ioctl or not.
-	 */
-	if (montype == MONITOR_PRISM) {
-		/*
-		 * We have the "monitor" private ioctl, but none of
-		 * the other private ioctls.  Use this, and select
-		 * the Prism header.
-		 *
-		 * If it fails, just fall back on SIOCSIWMODE.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		ireq.u.data.length = 1;	/* 1 argument */
-		args[0] = 3;	/* request Prism header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		if (ioctl(sock_fd, cmd, &ireq) != -1) {
-			/*
-			 * Success.
-			 * Note that we have to put the old mode back
-			 * when we close the device.
-			 */
-			handlep->must_do_on_close |= MUST_CLEAR_RFMON;
-
-			/*
-			 * Add this to the list of pcaps to close
-			 * when we exit.
-			 */
-			pcap_add_to_pcaps_to_close(handle);
-
-			return 1;
-		}
-
-		/*
-		 * Failure.  Fall back on SIOCSIWMODE.
-		 */
-	}
-
-	/*
-	 * First, take the interface down if it's up; otherwise, we
-	 * might get EBUSY.
-	 */
-	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "%s: Can't get flags", device);
+		del_mon_if(handle, sock_fd, &nlstate, device,
+		    handlep->mondevice);
+		nl80211_cleanup(&nlstate);
 		return PCAP_ERROR;
 	}
-	oldflags = 0;
-	if (ifr.ifr_flags & IFF_UP) {
-		oldflags = ifr.ifr_flags;
-		ifr.ifr_flags &= ~IFF_UP;
-		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
-			    device);
-			return PCAP_ERROR;
-		}
+
+	/*
+	 * Now configure the monitor interface up.
+	 */
+	memset(&ifr, 0, sizeof(ifr));
+	pcap_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
+	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "%s: Can't get flags for %s", device,
+		    handlep->mondevice);
+		del_mon_if(handle, sock_fd, &nlstate, device,
+		    handlep->mondevice);
+		nl80211_cleanup(&nlstate);
+		return PCAP_ERROR;
+	}
+	ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
+	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "%s: Can't set flags for %s", device,
+		    handlep->mondevice);
+		del_mon_if(handle, sock_fd, &nlstate, device,
+		    handlep->mondevice);
+		nl80211_cleanup(&nlstate);
+		return PCAP_ERROR;
 	}
 
 	/*
-	 * Then turn monitor mode on.
+	 * Success.  Clean up the libnl state.
 	 */
-	strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-	    sizeof ireq.ifr_ifrn.ifrn_name);
-	ireq.u.mode = IW_MODE_MONITOR;
-	if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
-		/*
-		 * Scientist, you've failed.
-		 * Bring the interface back up if we shut it down.
-		 */
-		ifr.ifr_flags = oldflags;
-		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
-			    device);
-			return PCAP_ERROR;
-		}
-		return PCAP_ERROR_RFMON_NOTSUP;
-	}
+	nl80211_cleanup(&nlstate);
 
 	/*
-	 * XXX - airmon-ng does "iwconfig {if} key off" after setting
-	 * monitor mode and setting the channel, and then does
-	 * "iwconfig up".
+	 * Note that we have to delete the monitor device when we close
+	 * the handle.
 	 */
-
-	/*
-	 * Now select the appropriate radio header.
-	 */
-	switch (montype) {
-
-	case MONITOR_WEXT:
-		/*
-		 * We don't have any private ioctl to set the header.
-		 */
-		break;
-
-	case MONITOR_HOSTAP:
-		/*
-		 * Try to select the radiotap header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 3;	/* request radiotap header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		if (ioctl(sock_fd, cmd, &ireq) != -1)
-			break;	/* success */
-
-		/*
-		 * That failed.  Try to select the AVS header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 2;	/* request AVS header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		if (ioctl(sock_fd, cmd, &ireq) != -1)
-			break;	/* success */
-
-		/*
-		 * That failed.  Try to select the Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 1;	/* request Prism header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_PRISM:
-		/*
-		 * The private ioctl failed.
-		 */
-		break;
-
-	case MONITOR_PRISM54:
-		/*
-		 * Select the Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 3;	/* request Prism header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_ACX100:
-		/*
-		 * Get the current channel.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWFREQ", device);
-			return PCAP_ERROR;
-		}
-		channel = ireq.u.freq.m;
-
-		/*
-		 * Select the Prism header, and set the channel to the
-		 * current value.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 1;		/* request Prism header */
-		args[1] = channel;	/* set channel */
-		memcpy(ireq.u.name, args, 2*sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_RT2500:
-		/*
-		 * Disallow transmission - that turns on the
-		 * Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 0;	/* disallow transmitting */
-		memcpy(ireq.u.name, args, sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_RT2570:
-		/*
-		 * Force the Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 1;	/* request Prism header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_RT73:
-		/*
-		 * Force the Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		ireq.u.data.length = 1;	/* 1 argument */
-		ireq.u.data.pointer = "1";
-		ireq.u.data.flags = 0;
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-
-	case MONITOR_RTL8XXX:
-		/*
-		 * Force the Prism header.
-		 */
-		memset(&ireq, 0, sizeof ireq);
-		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
-		    sizeof ireq.ifr_ifrn.ifrn_name);
-		args[0] = 1;	/* request Prism header */
-		memcpy(ireq.u.name, args, sizeof (int));
-		ioctl(sock_fd, cmd, &ireq);
-		break;
-	}
-
-	/*
-	 * Now bring the interface back up if we brought it down.
-	 */
-	if (oldflags != 0) {
-		ifr.ifr_flags = oldflags;
-		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
-			    device);
-
-			/*
-			 * At least try to restore the old mode on the
-			 * interface.
-			 */
-			if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
-				/*
-				 * Scientist, you've failed.
-				 */
-				fprintf(stderr,
-				    "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n"
-				    "Please adjust manually.\n",
-				    strerror(errno));
-			}
-			return PCAP_ERROR;
-		}
-	}
-
-	/*
-	 * Note that we have to put the old mode back when we
-	 * close the device.
-	 */
-	handlep->must_do_on_close |= MUST_CLEAR_RFMON;
+	handlep->must_do_on_close |= MUST_DELETE_MONIF;
 
 	/*
 	 * Add this to the list of pcaps to close when we exit.
@@ -6257,41 +4623,16 @@
 
 	return 1;
 }
-#endif /* IW_MODE_MONITOR */
-
-/*
- * Try various mechanisms to enter monitor mode.
- */
+#else /* HAVE_LIBNL */
 static int
-enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
+enter_rfmon_mode(pcap_t *handle _U_, int sock_fd _U_, const char *device _U_)
 {
-#if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR)
-	int ret;
-#endif
-
-#ifdef HAVE_LIBNL
-	ret = enter_rfmon_mode_mac80211(handle, sock_fd, device);
-	if (ret < 0)
-		return ret;	/* error attempting to do so */
-	if (ret == 1)
-		return 1;	/* success */
-#endif /* HAVE_LIBNL */
-
-#ifdef IW_MODE_MONITOR
-	ret = enter_rfmon_mode_wext(handle, sock_fd, device);
-	if (ret < 0)
-		return ret;	/* error attempting to do so */
-	if (ret == 1)
-		return 1;	/* success */
-#endif /* IW_MODE_MONITOR */
-
 	/*
-	 * Either none of the mechanisms we know about work or none
-	 * of those mechanisms are available, so we can't do monitor
-	 * mode.
+	 * We don't have libnl, so we can't do monitor mode.
 	 */
 	return 0;
 }
+#endif /* HAVE_LIBNL */
 
 #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
 /*
@@ -6310,15 +4651,21 @@
 /*
  * Set the list of time stamping types to include all types.
  */
-static void
-iface_set_all_ts_types(pcap_t *handle)
+static int
+iface_set_all_ts_types(pcap_t *handle, char *ebuf)
 {
 	u_int i;
 
-	handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES;
 	handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int));
+	if (handle->tstamp_type_list == NULL) {
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
+		return -1;
+	}
 	for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++)
 		handle->tstamp_type_list[i] = sof_ts_type_map[i].pcap_tstamp_val;
+	handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES;
+	return 0;
 }
 
 #ifdef ETHTOOL_GET_TS_INFO
@@ -6349,7 +4696,7 @@
 	/*
 	 * Create a socket from which to fetch time stamping capabilities.
 	 */
-	fd = socket(PF_UNIX, SOCK_RAW, 0);
+	fd = get_if_ioctl_socket();
 	if (fd < 0) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 		    errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)");
@@ -6357,7 +4704,7 @@
 	}
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	memset(&info, 0, sizeof(info));
 	info.cmd = ETHTOOL_GET_TS_INFO;
 	ifr.ifr_data = (caddr_t)&info;
@@ -6374,7 +4721,8 @@
 			 * asking for the time stamping types, so let's
 			 * just return all the possible types.
 			 */
-			iface_set_all_ts_types(handle);
+			if (iface_set_all_ts_types(handle, ebuf) == -1)
+				return -1;
 			return 0;
 
 		case ENODEV:
@@ -6422,15 +4770,20 @@
 		if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val)
 			num_ts_types++;
 	}
-	handle->tstamp_type_count = num_ts_types;
 	if (num_ts_types != 0) {
 		handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int));
+		if (handle->tstamp_type_list == NULL) {
+			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+			    errno, "malloc");
+			return -1;
+		}
 		for (i = 0, j = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
 			if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) {
 				handle->tstamp_type_list[j] = sof_ts_type_map[i].pcap_tstamp_val;
 				j++;
 			}
 		}
+		handle->tstamp_type_count = num_ts_types;
 	} else
 		handle->tstamp_type_list = NULL;
 
@@ -6438,7 +4791,7 @@
 }
 #else /* ETHTOOL_GET_TS_INFO */
 static int
-iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf _U_)
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf)
 {
 	/*
 	 * This doesn't apply to the "any" device; you can't say "turn on
@@ -6456,14 +4809,14 @@
 	 * We don't have an ioctl to use to ask what's supported,
 	 * so say we support everything.
 	 */
-	iface_set_all_ts_types(handle);
+	if (iface_set_all_ts_types(handle, ebuf) == -1)
+		return -1;
 	return 0;
 }
 #endif /* ETHTOOL_GET_TS_INFO */
 
 #endif /* defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) */
 
-#ifdef HAVE_PACKET_RING
 /*
  * Find out if we have any form of fragmentation/reassembly offloading.
  *
@@ -6471,21 +4824,35 @@
  * if SIOCETHTOOL isn't defined, or we don't have any #defines for any
  * of the types of offloading, there's nothing we can do to check, so
  * we just say "no, we don't".
+ *
+ * We treat EOPNOTSUPP, EINVAL and, if eperm_ok is true, EPERM as
+ * indications that the operation isn't supported.  We do EPERM
+ * weirdly because the SIOCETHTOOL code in later kernels 1) doesn't
+ * support ETHTOOL_GUFO, 2) also doesn't include it in the list
+ * of ethtool operations that don't require CAP_NET_ADMIN privileges,
+ * and 3) does the "is this permitted" check before doing the "is
+ * this even supported" check, so it fails with "this is not permitted"
+ * rather than "this is not even supported".  To work around this
+ * annoyance, we only treat EPERM as an error for the first feature,
+ * and assume that they all do the same permission checks, so if the
+ * first one is allowed all the others are allowed if supported.
  */
 #if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO))
 static int
-iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname)
+iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname,
+    int eperm_ok)
 {
 	struct ifreq	ifr;
 	struct ethtool_value eval;
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
 	eval.cmd = cmd;
 	eval.data = 0;
 	ifr.ifr_data = (caddr_t)&eval;
 	if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) {
-		if (errno == EOPNOTSUPP || errno == EINVAL) {
+		if (errno == EOPNOTSUPP || errno == EINVAL ||
+		    (errno == EPERM && eperm_ok)) {
 			/*
 			 * OK, let's just return 0, which, in our
 			 * case, either means "no, what we're asking
@@ -6502,34 +4869,41 @@
 	return eval.data;
 }
 
+/*
+ * XXX - it's annoying that we have to check for offloading at all, but,
+ * given that we have to, it's still annoying that we have to check for
+ * particular types of offloading, especially that shiny new types of
+ * offloading may be added - and, worse, may not be checkable with
+ * a particular ETHTOOL_ operation; ETHTOOL_GFEATURES would, in
+ * theory, give those to you, but the actual flags being used are
+ * opaque (defined in a non-uapi header), and there doesn't seem to
+ * be any obvious way to ask the kernel what all the offloading flags
+ * are - at best, you can ask for a set of strings(!) to get *names*
+ * for various flags.  (That whole mechanism appears to have been
+ * designed for the sole purpose of letting ethtool report flags
+ * by name and set flags by name, with the names having no semantics
+ * ethtool understands.)
+ */
 static int
 iface_get_offload(pcap_t *handle)
 {
 	int ret;
 
 #ifdef ETHTOOL_GTSO
-	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO");
+	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO", 0);
 	if (ret == -1)
 		return -1;
 	if (ret)
 		return 1;	/* TCP segmentation offloading on */
 #endif
 
-#ifdef ETHTOOL_GUFO
-	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
-	if (ret == -1)
-		return -1;
-	if (ret)
-		return 1;	/* UDP fragmentation offloading on */
-#endif
-
 #ifdef ETHTOOL_GGSO
 	/*
 	 * XXX - will this cause large unsegmented packets to be
 	 * handed to PF_PACKET sockets on transmission?  If not,
 	 * this need not be checked.
 	 */
-	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO");
+	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO", 0);
 	if (ret == -1)
 		return -1;
 	if (ret)
@@ -6537,7 +4911,7 @@
 #endif
 
 #ifdef ETHTOOL_GFLAGS
-	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
+	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS", 0);
 	if (ret == -1)
 		return -1;
 	if (ret & ETH_FLAG_LRO)
@@ -6550,13 +4924,27 @@
 	 * handed to PF_PACKET sockets on receipt?  If not,
 	 * this need not be checked.
 	 */
-	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO");
+	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO", 0);
 	if (ret == -1)
 		return -1;
 	if (ret)
 		return 1;	/* generic (large) receive offloading on */
 #endif
 
+#ifdef ETHTOOL_GUFO
+	/*
+	 * Do this one last, as support for it was removed in later
+	 * kernels, and it fails with EPERM on those kernels rather
+	 * than with EOPNOTSUPP (see explanation in comment for
+	 * iface_ethtool_flag_ioctl()).
+	 */
+	ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO", 1);
+	if (ret == -1)
+		return -1;
+	if (ret)
+		return 1;	/* UDP fragmentation offloading on */
+#endif
+
 	return 0;
 }
 #else /* SIOCETHTOOL */
@@ -6571,251 +4959,89 @@
 }
 #endif /* SIOCETHTOOL */
 
-#endif /* HAVE_PACKET_RING */
+static struct dsa_proto {
+	const char *name;
+	bpf_u_int32 linktype;
+} dsa_protos[] = {
+	/*
+	 * None is special and indicates that the interface does not have
+	 * any tagging protocol configured, and is therefore a standard
+	 * Ethernet interface.
+	 */
+	{ "none", DLT_EN10MB },
+	{ "brcm", DLT_DSA_TAG_BRCM },
+	{ "brcm-prepend", DLT_DSA_TAG_BRCM_PREPEND },
+	{ "dsa", DLT_DSA_TAG_DSA },
+	{ "edsa", DLT_DSA_TAG_EDSA },
+};
 
-#endif /* HAVE_PF_PACKET_SOCKETS */
-
-/* ===== Functions to interface to the older kernels ================== */
-
-/*
- * Try to open a packet socket using the old kernel interface.
- * Returns 1 on success and a PCAP_ERROR_ value on an error.
- */
 static int
-activate_old(pcap_t *handle)
+iface_dsa_get_proto_info(const char *device, pcap_t *handle)
 {
-	struct pcap_linux *handlep = handle->priv;
-	int		err;
-	int		arptype;
-	struct ifreq	ifr;
-	const char	*device = handle->opt.device;
-	struct utsname	utsname;
-	int		mtu;
+	char *pathstr;
+	unsigned int i;
+	/*
+	 * Make this significantly smaller than PCAP_ERRBUF_SIZE;
+	 * the tag *shouldn't* have some huge long name, and making
+	 * it smaller keeps newer versions of GCC from whining that
+	 * the error message if we don't support the tag could
+	 * overflow the error message buffer.
+	 */
+	char buf[128];
+	ssize_t r;
+	int fd;
 
-	/* Open the socket */
-
-	handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
-	if (handle->fd == -1) {
-		err = errno;
+	fd = asprintf(&pathstr, "/sys/class/net/%s/dsa/tagging", device);
+	if (fd < 0) {
 		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    err, "socket");
-		if (err == EPERM || err == EACCES) {
-			/*
-			 * You don't have permission to open the
-			 * socket.
-			 */
-			return PCAP_ERROR_PERM_DENIED;
-		} else {
-			/*
-			 * Other error.
-			 */
-			return PCAP_ERROR;
-		}
-	}
-
-	/* It worked - we are using the old interface */
-	handlep->sock_packet = 1;
-
-	/* ...which means we get the link-layer header. */
-	handlep->cooked = 0;
-
-	/* Bind to the given device */
-
-	if (strcmp(device, "any") == 0) {
-		strlcpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
-			PCAP_ERRBUF_SIZE);
+					  fd, "asprintf");
 		return PCAP_ERROR;
 	}
-	if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
+
+	fd = open(pathstr, O_RDONLY);
+	free(pathstr);
+	/*
+	 * This is not fatal, kernel >= 4.20 *might* expose this attribute
+	 */
+	if (fd < 0)
+		return 0;
+
+	r = read(fd, buf, sizeof(buf) - 1);
+	if (r <= 0) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+					  errno, "read");
+		close(fd);
 		return PCAP_ERROR;
+	}
+	close(fd);
 
 	/*
-	 * Try to get the link-layer type.
+	 * Buffer should be LF terminated.
 	 */
-	arptype = iface_get_arptype(handle->fd, device, handle->errbuf);
-	if (arptype < 0)
-		return PCAP_ERROR;
+	if (buf[r - 1] == '\n')
+		r--;
+	buf[r] = '\0';
 
-	/*
-	 * Try to find the DLT_ type corresponding to that
-	 * link-layer type.
-	 */
-	map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0);
-	if (handle->linktype == -1) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			 "unknown arptype %d", arptype);
-		return PCAP_ERROR;
-	}
-
-	/* Go to promisc mode if requested */
-
-	if (handle->opt.promisc) {
-		memset(&ifr, 0, sizeof(ifr));
-		strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-		if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
-			pcap_fmt_errmsg_for_errno(handle->errbuf,
-			    PCAP_ERRBUF_SIZE, errno, "SIOCGIFFLAGS");
-			return PCAP_ERROR;
-		}
-		if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
-			/*
-			 * Promiscuous mode isn't currently on,
-			 * so turn it on, and remember that
-			 * we should turn it off when the
-			 * pcap_t is closed.
-			 */
-
-			/*
-			 * If we haven't already done so, arrange
-			 * to have "pcap_close_all()" called when
-			 * we exit.
-			 */
-			if (!pcap_do_addexit(handle)) {
-				/*
-				 * "atexit()" failed; don't put
-				 * the interface in promiscuous
-				 * mode, just give up.
-				 */
-				return PCAP_ERROR;
+	for (i = 0; i < sizeof(dsa_protos) / sizeof(dsa_protos[0]); i++) {
+		if (strlen(dsa_protos[i].name) == (size_t)r &&
+		    strcmp(buf, dsa_protos[i].name) == 0) {
+			handle->linktype = dsa_protos[i].linktype;
+			switch (dsa_protos[i].linktype) {
+			case DLT_EN10MB:
+				return 0;
+			default:
+				return 1;
 			}
-
-			ifr.ifr_flags |= IFF_PROMISC;
-			if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
-				pcap_fmt_errmsg_for_errno(handle->errbuf,
-				    PCAP_ERRBUF_SIZE, errno, "SIOCSIFFLAGS");
-				return PCAP_ERROR;
-			}
-			handlep->must_do_on_close |= MUST_CLEAR_PROMISC;
-
-			/*
-			 * Add this to the list of pcaps
-			 * to close when we exit.
-			 */
-			pcap_add_to_pcaps_to_close(handle);
 		}
 	}
 
-	/*
-	 * Compute the buffer size.
-	 *
-	 * We're using SOCK_PACKET, so this might be a 2.0[.x]
-	 * kernel, and might require special handling - check.
-	 */
-	if (uname(&utsname) < 0 ||
-	    strncmp(utsname.release, "2.0", 3) == 0) {
-		/*
-		 * Either we couldn't find out what kernel release
-		 * this is, or it's a 2.0[.x] kernel.
-		 *
-		 * In the 2.0[.x] kernel, a "recvfrom()" on
-		 * a SOCK_PACKET socket, with MSG_TRUNC set, will
-		 * return the number of bytes read, so if we pass
-		 * a length based on the snapshot length, it'll
-		 * return the number of bytes from the packet
-		 * copied to userland, not the actual length
-		 * of the packet.
-		 *
-		 * This means that, for example, the IP dissector
-		 * in tcpdump will get handed a packet length less
-		 * than the length in the IP header, and will
-		 * complain about "truncated-ip".
-		 *
-		 * So we don't bother trying to copy from the
-		 * kernel only the bytes in which we're interested,
-		 * but instead copy them all, just as the older
-		 * versions of libpcap for Linux did.
-		 *
-		 * The buffer therefore needs to be big enough to
-		 * hold the largest packet we can get from this
-		 * device.  Unfortunately, we can't get the MRU
-		 * of the network; we can only get the MTU.  The
-		 * MTU may be too small, in which case a packet larger
-		 * than the buffer size will be truncated *and* we
-		 * won't get the actual packet size.
-		 *
-		 * However, if the snapshot length is larger than
-		 * the buffer size based on the MTU, we use the
-		 * snapshot length as the buffer size, instead;
-		 * this means that with a sufficiently large snapshot
-		 * length we won't artificially truncate packets
-		 * to the MTU-based size.
-		 *
-		 * This mess just one of many problems with packet
-		 * capture on 2.0[.x] kernels; you really want a
-		 * 2.2[.x] or later kernel if you want packet capture
-		 * to work well.
-		 */
-		mtu = iface_get_mtu(handle->fd, device, handle->errbuf);
-		if (mtu == -1)
-			return PCAP_ERROR;
-		handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
-		if (handle->bufsize < (u_int)handle->snapshot)
-			handle->bufsize = (u_int)handle->snapshot;
-	} else {
-		/*
-		 * This is a 2.2[.x] or later kernel.
-		 *
-		 * We can safely pass "recvfrom()" a byte count
-		 * based on the snapshot length.
-		 */
-		handle->bufsize = (u_int)handle->snapshot;
-	}
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		      "unsupported DSA tag: %s", buf);
 
-	/*
-	 * Default value for offset to align link-layer payload
-	 * on a 4-byte boundary.
-	 */
-	handle->offset	 = 0;
-
-	/*
-	 * SOCK_PACKET sockets don't supply information from
-	 * stripped VLAN tags.
-	 */
-	handlep->vlan_offset = -1; /* unknown */
-
-	return 1;
+	return PCAP_ERROR;
 }
 
 /*
- *  Bind the socket associated with FD to the given device using the
- *  interface of the old kernels.
- */
-static int
-iface_bind_old(int fd, const char *device, char *ebuf)
-{
-	struct sockaddr	saddr;
-	int		err;
-	socklen_t	errlen = sizeof(err);
-
-	memset(&saddr, 0, sizeof(saddr));
-	strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
-	if (bind(fd, &saddr, sizeof(saddr)) == -1) {
-		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-		    errno, "bind");
-		return -1;
-	}
-
-	/* Any pending errors, e.g., network is down? */
-
-	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
-		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-		    errno, "getsockopt");
-		return -1;
-	}
-
-	if (err > 0) {
-		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-		    err, "bind");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/* ===== System calls available on all supported kernels ============== */
-
-/*
  *  Query the kernel for the MTU of the given interface.
  */
 static int
@@ -6827,7 +5053,7 @@
 		return BIGGER_THAN_ALL_MTUS;
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
@@ -6845,28 +5071,29 @@
 iface_get_arptype(int fd, const char *device, char *ebuf)
 {
 	struct ifreq	ifr;
+	int		ret;
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
-		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-		    errno, "SIOCGIFHWADDR");
 		if (errno == ENODEV) {
 			/*
 			 * No such device.
 			 */
-			return PCAP_ERROR_NO_SUCH_DEVICE;
-		}
-		return PCAP_ERROR;
+			ret = PCAP_ERROR_NO_SUCH_DEVICE;
+		} else
+			ret = PCAP_ERROR;
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "SIOCGIFHWADDR");
+		return ret;
 	}
 
 	return ifr.ifr_hwaddr.sa_family;
 }
 
-#ifdef SO_ATTACH_FILTER
 static int
-fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
+fix_program(pcap_t *handle, struct sock_fprog *fcode)
 {
 	struct pcap_linux *handlep = handle->priv;
 	size_t prog_size;
@@ -6898,39 +5125,6 @@
 		 */
 		switch (BPF_CLASS(p->code)) {
 
-		case BPF_RET:
-			/*
-			 * It's a return instruction; are we capturing
-			 * in memory-mapped mode?
-			 */
-			if (!is_mmapped) {
-				/*
-				 * No; is the snapshot length a constant,
-				 * rather than the contents of the
-				 * accumulator?
-				 */
-				if (BPF_MODE(p->code) == BPF_K) {
-					/*
-					 * Yes - if the value to be returned,
-					 * i.e. the snapshot length, is
-					 * anything other than 0, make it
-					 * MAXIMUM_SNAPLEN, so that the packet
-					 * is truncated by "recvfrom()",
-					 * not by the filter.
-					 *
-					 * XXX - there's nothing we can
-					 * easily do if it's getting the
-					 * value from the accumulator; we'd
-					 * have to insert code to force
-					 * non-zero values to be
-					 * MAXIMUM_SNAPLEN.
-					 */
-					if (p->k != 0)
-						p->k = MAXIMUM_SNAPLEN;
-				}
-			}
-			break;
-
 		case BPF_LD:
 		case BPF_LDX:
 			/*
@@ -6950,7 +5144,7 @@
 					 * Yes, so we need to fix this
 					 * instruction.
 					 */
-					if (fix_offset(p) < 0) {
+					if (fix_offset(handle, p) < 0) {
 						/*
 						 * We failed to do so.
 						 * Return 0, so our caller
@@ -6968,38 +5162,86 @@
 }
 
 static int
-fix_offset(struct bpf_insn *p)
+fix_offset(pcap_t *handle, struct bpf_insn *p)
 {
 	/*
-	 * What's the offset?
+	 * Existing references to auxiliary data shouldn't be adjusted.
+	 *
+	 * Note that SKF_AD_OFF is negative, but p->k is unsigned, so
+	 * we use >= and cast SKF_AD_OFF to unsigned.
 	 */
-	if (p->k >= SLL_HDR_LEN) {
+	if (p->k >= (bpf_u_int32)SKF_AD_OFF)
+		return 0;
+	if (handle->linktype == DLT_LINUX_SLL2) {
 		/*
-		 * It's within the link-layer payload; that starts at an
-		 * offset of 0, as far as the kernel packet filter is
-		 * concerned, so subtract the length of the link-layer
-		 * header.
+		 * What's the offset?
 		 */
-		p->k -= SLL_HDR_LEN;
-	} else if (p->k == 0) {
+		if (p->k >= SLL2_HDR_LEN) {
+			/*
+			 * It's within the link-layer payload; that starts
+			 * at an offset of 0, as far as the kernel packet
+			 * filter is concerned, so subtract the length of
+			 * the link-layer header.
+			 */
+			p->k -= SLL2_HDR_LEN;
+		} else if (p->k == 0) {
+			/*
+			 * It's the protocol field; map it to the
+			 * special magic kernel offset for that field.
+			 */
+			p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+		} else if (p->k == 4) {
+			/*
+			 * It's the ifindex field; map it to the
+			 * special magic kernel offset for that field.
+			 */
+			p->k = SKF_AD_OFF + SKF_AD_IFINDEX;
+		} else if (p->k == 10) {
+			/*
+			 * It's the packet type field; map it to the
+			 * special magic kernel offset for that field.
+			 */
+			p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+		} else if ((bpf_int32)(p->k) > 0) {
+			/*
+			 * It's within the header, but it's not one of
+			 * those fields; we can't do that in the kernel,
+			 * so punt to userland.
+			 */
+			return -1;
+		}
+	} else {
 		/*
-		 * It's the packet type field; map it to the special magic
-		 * kernel offset for that field.
+		 * What's the offset?
 		 */
-		p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
-	} else if (p->k == 14) {
-		/*
-		 * It's the protocol field; map it to the special magic
-		 * kernel offset for that field.
-		 */
-		p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
-	} else if ((bpf_int32)(p->k) > 0) {
-		/*
-		 * It's within the header, but it's not one of those
-		 * fields; we can't do that in the kernel, so punt
-		 * to userland.
-		 */
-		return -1;
+		if (p->k >= SLL_HDR_LEN) {
+			/*
+			 * It's within the link-layer payload; that starts
+			 * at an offset of 0, as far as the kernel packet
+			 * filter is concerned, so subtract the length of
+			 * the link-layer header.
+			 */
+			p->k -= SLL_HDR_LEN;
+		} else if (p->k == 0) {
+			/*
+			 * It's the packet type field; map it to the
+			 * special magic kernel offset for that field.
+			 */
+			p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+		} else if (p->k == 14) {
+			/*
+			 * It's the protocol field; map it to the
+			 * special magic kernel offset for that field.
+			 */
+			p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+		} else if ((bpf_int32)(p->k) > 0) {
+			/*
+			 * It's within the header, but it's not one of
+			 * those fields; we can't do that in the kernel,
+			 * so punt to userland.
+			 */
+			return -1;
+		}
 	}
 	return 0;
 }
@@ -7156,7 +5398,6 @@
 		return -1;
 	return 0;
 }
-#endif
 
 int
 pcap_set_protocol_linux(pcap_t *p, int protocol)
@@ -7173,15 +5414,9 @@
 const char *
 pcap_lib_version(void)
 {
-#ifdef HAVE_PACKET_RING
- #if defined(HAVE_TPACKET3)
+#if defined(HAVE_TPACKET3)
 	return (PCAP_VERSION_STRING " (with TPACKET_V3)");
- #elif defined(HAVE_TPACKET2)
-	return (PCAP_VERSION_STRING " (with TPACKET_V2)");
- #else
-	return (PCAP_VERSION_STRING " (with TPACKET_V1)");
- #endif
 #else
-	return (PCAP_VERSION_STRING " (without TPACKET)");
+	return (PCAP_VERSION_STRING " (with TPACKET_V2)");
 #endif
 }
diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c
index d5c5dcd..17f528f 100644
--- a/pcap-netfilter-linux.c
+++ b/pcap-netfilter-linux.c
@@ -56,13 +56,13 @@
 #include <linux/netfilter/nfnetlink_log.h>
 #include <linux/netfilter/nfnetlink_queue.h>
 
-/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue.
+/* NOTE: if your program drops privileges after pcap_activate() it WON'T work with nfqueue.
  *       It took me quite some time to debug ;/
  *
- *       Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages,
+ *       Sending any data to nfnetlink socket requires CAP_NET_ADMIN privileges,
  *       and in nfqueue we need to send verdict reply after recving packet.
  *
- *       In tcpdump you can disable dropping privilages with -Z root
+ *       In tcpdump you can disable dropping privileges with -Z root
  */
 
 #include "pcap-netfilter-linux.h"
@@ -91,7 +91,7 @@
 	struct pcap_netfilter *handlep = handle->priv;
 	register u_char *bp, *ep;
 	int count = 0;
-	int len;
+	ssize_t len;
 
 	/*
 	 * Has "pcap_breakloop()" been called?
@@ -152,14 +152,25 @@
 		 */
 		if (handle->break_loop) {
 			handle->bp = bp;
-			handle->cc = ep - bp;
+			handle->cc = (int)(ep - bp);
 			if (count == 0) {
 				handle->break_loop = 0;
 				return PCAP_ERROR_BREAK;
 			} else
 				return count;
 		}
-		if (ep - bp < NLMSG_SPACE(0)) {
+		/*
+		 * NLMSG_SPACE(0) might be signed or might be unsigned,
+		 * depending on whether the kernel defines NLMSG_ALIGNTO
+		 * as 4, which older kernels do, or as 4U, which newer
+		 * kernels do.
+		 *
+		 * ep - bp is of type ptrdiff_t, which is signed.
+		 *
+		 * To squelch warnings, we cast both to size_t, which
+		 * is unsigned; ep >= bp, so the cast is safe.
+		 */
+		if ((size_t)(ep - bp) < (size_t)NLMSG_SPACE(0)) {
 			/*
 			 * There's less than one netlink message left
 			 * in the buffer.  Give up.
@@ -168,7 +179,7 @@
 		}
 
 		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);
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %zd) (nlmsg_len: %u)", len, nlh->nlmsg_len);
 			return -1;
 		}
 
@@ -190,7 +201,7 @@
 				const struct nfattr *payload_attr = NULL;
 
 				if (nlh->nlmsg_len < HDR_LENGTH) {
-					pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
+					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
 					return -1;
 				}
 
@@ -240,7 +251,7 @@
 
 				gettimeofday(&pkth.ts, NULL);
 				if (handle->fcode.bf_insns == NULL ||
-						bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
+						pcap_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
 				{
 					handlep->packets_read++;
 					callback(user, &pkth, payload);
@@ -262,14 +273,21 @@
 		 * If the message length would run past the end of the
 		 * buffer, truncate it to the remaining space in the
 		 * buffer.
+		 *
+		 * To squelch warnings, we cast ep - bp to uint32_t, which
+		 * is unsigned and is the type of msg_len; ep >= bp, and
+		 * len should fit in 32 bits (either it's set from an int
+		 * or it's set from a recv() call with a buffer size that's
+		 * an int, and we're assuming either ILP32 or LP64), so
+		 * the cast is safe.
 		 */
-		if (msg_len > ep - bp)
-			msg_len = ep - bp;
+		if (msg_len > (uint32_t)(ep - bp))
+			msg_len = (uint32_t)(ep - bp);
 
 		bp += msg_len;
 		if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
 			handle->bp = bp;
-			handle->cc = ep - bp;
+			handle->cc = (int)(ep - bp);
 			if (handle->cc < 0)
 				handle->cc = 0;
 			return count;
@@ -299,9 +317,10 @@
 }
 
 static int
-netfilter_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+netfilter_inject_linux(pcap_t *handle, const void *buf _U_, int size _U_)
 {
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packet injection is not supported on netfilter devices");
 	return (-1);
 }
 
@@ -315,6 +334,7 @@
 netfilter_send_config_msg(const pcap_t *handle, uint16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
 {
 	char buf[1024] __attribute__ ((aligned));
+	memset(buf, 0, sizeof(buf));
 
 	struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
 	struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr));
@@ -361,7 +381,11 @@
 
 		/* ignore interrupt system call error */
 		do {
-			len = recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen);
+			/*
+			 * The buffer is not so big that its size won't
+			 * fit into an int.
+			 */
+			len = (int)recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen);
 		} while ((len == -1) && (errno == EINTR));
 
 		if (len <= 0)
@@ -508,7 +532,7 @@
 			char *end_dev;
 
 			if (group_count == 32) {
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 						"Maximum 32 netfilter groups! dev: %s",
 						handle->opt.device);
 				return PCAP_ERROR;
@@ -517,7 +541,7 @@
 			group_id = strtol(dev, &end_dev, 0);
 			if (end_dev != dev) {
 				if (group_id < 0 || group_id > 65535) {
-					pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 							"Netfilter group range from 0 to 65535 (got %ld)",
 							group_id);
 					return PCAP_ERROR;
@@ -533,7 +557,7 @@
 	}
 
 	if (type == OTHER || *dev) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"Can't get netfilter group(s) index from %s",
 				handle->opt.device);
 		return PCAP_ERROR;
@@ -614,7 +638,7 @@
 			if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
 				pcap_fmt_errmsg_for_errno(handle->errbuf,
 				    PCAP_ERRBUF_SIZE, errno,
-				    "Can't listen on group group index");
+				    "Can't listen on group index");
 				goto close_fail;
 			}
 
@@ -644,7 +668,7 @@
 			if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
 				pcap_fmt_errmsg_for_errno(handle->errbuf,
 				    PCAP_ERRBUF_SIZE, errno,
-				    "Can't listen on group group index");
+				    "Can't listen on group index");
 				goto close_fail;
 			}
 
@@ -719,7 +743,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_netfilter));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_netfilter);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-netmap.c b/pcap-netmap.c
index f150563..27d36e5 100644
--- a/pcap-netmap.c
+++ b/pcap-netmap.c
@@ -29,7 +29,6 @@
 #endif
 
 #include <poll.h>
-#include <ctype.h>
 #include <errno.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -67,7 +66,7 @@
 {
 	struct pcap_netmap *pn = p->priv;
 
-	ps->ps_recv = pn->rx_pkts;
+	ps->ps_recv = (u_int)pn->rx_pkts;
 	ps->ps_drop = 0;
 	ps->ps_ifdrop = 0;
 	return 0;
@@ -82,7 +81,7 @@
 	const struct bpf_insn *pc = p->fcode.bf_insns;
 
 	++pn->rx_pkts;
-	if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
+	if (pc == NULL || pcap_filter(pc, buf, h->len, h->caplen))
 		pn->cb(pn->cb_arg, h, buf);
 }
 
@@ -117,7 +116,7 @@
 
 /* XXX need to check the NIOCTXSYNC/poll */
 static int
-pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
+pcap_netmap_inject(pcap_t *p, const void *buf, int size)
 {
 	struct pcap_netmap *pn = p->priv;
 	struct nm_desc *d = pn->d;
@@ -287,7 +286,7 @@
 	*is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
 	if (! *is_ours)
 		return NULL;
-	p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_netmap);
 	if (p == NULL)
 		return (NULL);
 	p->activate_op = pcap_netmap_activate;
diff --git a/pcap-new.c b/pcap-new.c
index 6fa52e6..7c00659 100644
--- a/pcap-new.c
+++ b/pcap-new.c
@@ -35,6 +35,8 @@
 #include <config.h>
 #endif
 
+#include "ftmacros.h"
+
 /*
  * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
  * include portability.h, and portability.h, on Windows, expects that
@@ -54,11 +56,14 @@
 
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_FILE "File"
+#define PCAP_TEXT_SOURCE_FILE_LEN (sizeof PCAP_TEXT_SOURCE_FILE - 1)
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof "Network adapter" - 1)
 
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_LOCAL_HOST + 1)
 
 /****************************************************
  *                                                  *
@@ -66,10 +71,12 @@
  *                                                  *
  ****************************************************/
 
-int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
 {
 	int type;
 	char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
+	size_t pathlen;
+	size_t stringlen;
 	pcap_t *fp;
 	char tmpstring[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
 	pcap_if_t *lastdev;	/* Last device in the pcap_if_t list */
@@ -81,7 +88,7 @@
 
 	if (strlen(source) > PCAP_BUF_SIZE)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
 		return -1;
 	}
 
@@ -112,8 +119,8 @@
 
 		if (*alldevs == NULL)
 		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				"No interfaces found! Make sure libpcap/WinPcap is properly installed"
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				"No interfaces found! Make sure libpcap/Npcap is properly installed"
 				" on the local machine.");
 			return -1;
 		}
@@ -123,6 +130,8 @@
 		dev = *alldevs;
 		while (dev)
 		{
+			char *localdesc, *desc;
+
 			/* Create the new device identifier */
 			if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
 				return -1;
@@ -141,20 +150,16 @@
 				return -1;
 			}
 
-			/* Create the new device description */
+			/*
+			 * Create the 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);
+				localdesc = dev->name;
 			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)
+				localdesc = dev->description;
+			if (pcap_asprintf(&desc, "%s '%s' %s",
+			    PCAP_TEXT_SOURCE_ADAPTER, localdesc,
+			    PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
 			{
 				pcap_fmt_errmsg_for_errno(errbuf,
 				    PCAP_ERRBUF_SIZE, errno,
@@ -163,6 +168,10 @@
 				return -1;
 			}
 
+			/* Now overwrite the description */
+			free(dev->description);
+			dev->description = desc;
+
 			dev = dev->next;
 		}
 
@@ -170,7 +179,6 @@
 
 	case PCAP_SRC_FILE:
 	{
-		size_t stringlen;
 #ifdef _WIN32
 		WIN32_FIND_DATA filedata;
 		HANDLE filehandle;
@@ -201,7 +209,8 @@
 		}
 
 		/* Save the path for future reference */
-		pcap_snprintf(path, sizeof(path), "%s", name);
+		snprintf(path, sizeof(path), "%s", name);
+		pathlen = strlen(path);
 
 #ifdef _WIN32
 		/* To perform directory listing, Win32 must have an 'asterisk' as ending char */
@@ -215,7 +224,7 @@
 
 		if (filehandle == INVALID_HANDLE_VALUE)
 		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
 			return -1;
 		}
 
@@ -228,7 +237,7 @@
 
 		if (filedata == NULL)
 		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
 			return -1;
 		}
 #endif
@@ -236,11 +245,15 @@
 		/* Add all files we find to the list. */
 		do
 		{
-
 #ifdef _WIN32
-			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
+			/* Skip the file if the pathname won't fit in the buffer */
+			if (pathlen + strlen(filedata.cFileName) >= sizeof(filename))
+				continue;
+			snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
 #else
-			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
+			if (pathlen + strlen(filedata->d_name) >= sizeof(filename))
+				continue;
+			snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
 #endif
 
 			fp = pcap_open_offline(filename, errbuf);
@@ -287,9 +300,7 @@
 					return -1;
 				}
 
-				stringlen = strlen(tmpstring);
-
-				dev->name = (char *)malloc(stringlen + 1);
+				dev->name = strdup(tmpstring);
 				if (dev->name == NULL)
 				{
 					pcap_fmt_errmsg_for_errno(errbuf,
@@ -299,19 +310,12 @@
 					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)
+				/*
+				 * Create the description.
+				 */
+				if (pcap_asprintf(&dev->description,
+				    "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+				    filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
 				{
 					pcap_fmt_errmsg_for_errno(errbuf,
 					    PCAP_ERRBUF_SIZE, errno,
@@ -320,9 +324,6 @@
 					return -1;
 				}
 
-				/* Copy the new device description into the correct memory location */
-				strlcpy(dev->description, tmpstring, stringlen + 1);
-
 				pcap_close(fp);
 			}
 		}
@@ -345,7 +346,7 @@
 		return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
 
 	default:
-		strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+		pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
 		return -1;
 	}
 }
@@ -357,9 +358,19 @@
 	pcap_t *fp;
 	int status;
 
+	/*
+	 * A null device name is equivalent to the "any" device -
+	 * which might not be supported on this platform, but
+	 * this means that you'll get a "not supported" error
+	 * rather than, say, a crash when we try to dereference
+	 * the null pointer.
+	 */
+	if (source == NULL)
+		source = "any";
+
 	if (strlen(source) > PCAP_BUF_SIZE)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
 		return NULL;
 	}
 
@@ -389,7 +400,7 @@
 		return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
 
 	default:
-		strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+		pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
 		return NULL;
 	}
 
@@ -434,15 +445,15 @@
 
 fail:
 	if (status == PCAP_ERROR)
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
 		    name, fp->errbuf);
 	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
 	    status == PCAP_ERROR_PERM_DENIED ||
 	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
 		    name, pcap_statustostr(status), fp->errbuf);
 	else
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
 		    name, pcap_statustostr(status));
 	pcap_close(fp);
 	return NULL;
diff --git a/pcap-nit.c b/pcap-nit.c
index 6a1a77c..cfd9519 100644
--- a/pcap-nit.c
+++ b/pcap-nit.c
@@ -43,7 +43,6 @@
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 
@@ -168,7 +167,7 @@
 			continue;
 
 		default:
-			pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+			snprintf(p->errbuf, sizeof(p->errbuf),
 			    "bad nit state %d", nh->nh_state);
 			return (-1);
 		}
@@ -179,7 +178,7 @@
 		caplen = nh->nh_wirelen;
 		if (caplen > p->snapshot)
 			caplen = p->snapshot;
-		if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
+		if (pcap_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
 			struct pcap_pkthdr h;
 			h.ts = nh->nh_timestamp;
 			h.len = nh->nh_wirelen;
@@ -197,7 +196,7 @@
 }
 
 static int
-pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
+pcap_inject_nit(pcap_t *p, const void *buf, int size)
 {
 	struct sockaddr sa;
 	int ret;
@@ -371,7 +370,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_nit);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-npf.c b/pcap-npf.c
index a9ff0ff..f12c701 100644
--- a/pcap-npf.c
+++ b/pcap-npf.c
@@ -41,6 +41,17 @@
 #include <pcap-int.h>
 #include <pcap/dlt.h>
 
+/*
+ * XXX - Packet32.h defines bpf_program, so we can't include
+ * <pcap/bpf.h>, which also defines it; that's why we define
+ * PCAP_DONT_INCLUDE_PCAP_BPF_H,
+ *
+ * However, no header in the WinPcap or Npcap SDKs defines the
+ * macros for BPF code, so we have to define them ourselves.
+ */
+#define		BPF_RET		0x06
+#define		BPF_K		0x00
+
 /* Old-school MinGW have these headers in a different place.
  */
 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
@@ -55,6 +66,10 @@
   #include <dagapi.h>
 #endif /* HAVE_DAG_API */
 
+#include "diag-control.h"
+
+#include "pcap-airpcap.h"
+
 static int pcap_setfilter_npf(pcap_t *, struct bpf_program *);
 static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
 static int pcap_getnonblock_npf(pcap_t *);
@@ -70,7 +85,7 @@
 #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
 
 /*
- * Private data for capturing on WinPcap devices.
+ * Private data for capturing on WinPcap/Npcap devices.
  */
 struct pcap_win {
 	ADAPTER *adapter;		/* the packet32 ADAPTER for the device */
@@ -155,7 +170,7 @@
 	 */
 	oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
 	if (oid_data_arg == NULL) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "Couldn't allocate argument buffer for PacketRequest");
 		return (PCAP_ERROR);
 	}
@@ -166,11 +181,8 @@
 	oid_data_arg->Oid = oid;
 	oid_data_arg->Length = (ULONG)(*lenp);	/* XXX - check for ridiculously large value? */
 	if (!PacketRequest(adapter, FALSE, oid_data_arg)) {
-		char errmsgbuf[PCAP_ERRBUF_SIZE+1];
-
-		pcap_win32_err_to_str(GetLastError(), errmsgbuf);
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "Error calling PacketRequest: %s", errmsgbuf);
+		pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "Error calling PacketRequest");
 		free(oid_data_arg);
 		return (-1);
 	}
@@ -193,7 +205,6 @@
 {
 	struct pcap_win *pw = p->priv;
 	struct bpf_stat bstats;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
 
 	/*
 	 * Try to get statistics.
@@ -209,9 +220,8 @@
 	 * to us.
 	 */
 	if (!PacketGetStats(pw->adapter, &bstats)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketGetStats error: %s", errbuf);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "PacketGetStats error");
 		return (-1);
 	}
 	ps->ps_recv = bstats.bs_recv;
@@ -245,18 +255,17 @@
  * 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
+ *    https://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 *
+static struct pcap_stat *
 pcap_stats_ex_npf(pcap_t *p, int *pcap_stat_size)
 {
 	struct pcap_win *pw = p->priv;
 	struct bpf_stat bstats;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
 
 	*pcap_stat_size = sizeof (p->stat);
 
@@ -268,15 +277,19 @@
 	 * same layout, but let's not cheat.)
 	 */
 	if (!PacketGetStatsEx(pw->adapter, &bstats)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketGetStatsEx error: %s", errbuf);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "PacketGetStatsEx error");
 		return (NULL);
 	}
 	p->stat.ps_recv = bstats.bs_recv;
 	p->stat.ps_drop = bstats.bs_drop;
 	p->stat.ps_ifdrop = bstats.ps_ifdrop;
-#ifdef ENABLE_REMOTE
+	/*
+	 * Just in case this is ever compiled for a target other than
+	 * Windows, which is somewhere between extremely unlikely and
+	 * impossible.
+	 */
+#ifdef _WIN32
 	p->stat.ps_capt = bstats.bs_capt;
 #endif
 	return (&p->stat);
@@ -290,7 +303,7 @@
 
 	if(PacketSetBuff(pw->adapter,dim)==FALSE)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
 		return (-1);
 	}
 	return (0);
@@ -304,7 +317,7 @@
 
 	if(PacketSetMode(pw->adapter,mode)==FALSE)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
 		return (-1);
 	}
 
@@ -319,7 +332,7 @@
 
 	if(PacketSetMinToCopy(pw->adapter, size)==FALSE)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
 		return (-1);
 	}
 	return (0);
@@ -347,7 +360,6 @@
 {
 	struct pcap_win *pw = p->priv;
 	PACKET_OID_DATA *oid_data_arg;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
 
 	/*
 	 * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
@@ -358,7 +370,7 @@
 	 */
 	oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
 	if (oid_data_arg == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Couldn't allocate argument buffer for PacketRequest");
 		return (PCAP_ERROR);
 	}
@@ -367,9 +379,8 @@
 	oid_data_arg->Length = (ULONG)(*lenp);	/* XXX - check for ridiculously large value? */
 	memcpy(oid_data_arg->Data, data, *lenp);
 	if (!PacketRequest(pw->adapter, TRUE, oid_data_arg)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error calling PacketRequest: %s", errbuf);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "Error calling PacketRequest");
 		free(oid_data_arg);
 		return (PCAP_ERROR);
 	}
@@ -391,13 +402,6 @@
 {
 	struct pcap_win *pw = p->priv;
 	u_int res;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	if (pw->adapter==NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Cannot transmit a queue to an offline capture or to a TurboCap port");
-		return (0);
-	}
 
 	res = PacketSendPackets(pw->adapter,
 		queue->buffer,
@@ -405,9 +409,8 @@
 		(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);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "Error queueing packets");
 	}
 
 	return (res);
@@ -420,7 +423,7 @@
 
 	if (size<=0) {
 		/* Bogus parameter */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Error: invalid size %d",size);
 		return (-1);
 	}
@@ -429,7 +432,7 @@
 	new_buff=(unsigned char*)malloc(sizeof(char)*size);
 
 	if (!new_buff) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Error: not enough memory");
 		return (-1);
 	}
@@ -451,7 +454,7 @@
 	/* Set the packet driver in dump mode */
 	res = PacketSetMode(pw->adapter, PACKET_MODE_DUMP);
 	if(res == FALSE){
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Error setting dump mode");
 		return (-1);
 	}
@@ -459,7 +462,7 @@
 	/* Set the name of the dump file */
 	res = PacketSetDumpName(pw->adapter, filename, (int)strlen(filename));
 	if(res == FALSE){
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Error setting kernel dump file name");
 		return (-1);
 	}
@@ -467,8 +470,8 @@
 	/* Set the limits of the dump file */
 	res = PacketSetDumpLimits(pw->adapter, maxsize, maxpacks);
 	if(res == FALSE) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    		"Error setting dump limit");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				"Error setting dump limit");
 		return (-1);
 	}
 
@@ -483,30 +486,34 @@
 	return (PacketIsDumpEnded(pw->adapter, (BOOLEAN)sync));
 }
 
+#ifdef HAVE_AIRPCAP_API
 static PAirpcapHandle
 pcap_get_airpcap_handle_npf(pcap_t *p)
 {
-#ifdef HAVE_AIRPCAP_API
 	struct pcap_win *pw = p->priv;
 
 	return (PacketGetAirPcapHandle(pw->adapter));
-#else
-	return (NULL);
-#endif /* HAVE_AIRPCAP_API */
 }
+#else /* HAVE_AIRPCAP_API */
+static PAirpcapHandle
+pcap_get_airpcap_handle_npf(pcap_t *p _U_)
+{
+	return (NULL);
+}
+#endif /* HAVE_AIRPCAP_API */
 
 static int
 pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
 	PACKET Packet;
 	int cc;
-	int n = 0;
+	int n;
 	register u_char *bp, *ep;
 	u_char *datap;
 	struct pcap_win *pw = p->priv;
 
 	cc = p->cc;
-	if (p->cc == 0) {
+	if (cc == 0) {
 		/*
 		 * Has "pcap_breakloop()" been called?
 		 */
@@ -534,7 +541,34 @@
 		 */
 		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
 		if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+			/*
+			 * Did the device go away?
+			 * If so, the error we get is ERROR_GEN_FAILURE.
+			 */
+			DWORD errcode = GetLastError();
+
+			if (errcode == ERROR_GEN_FAILURE) {
+				/*
+				 * The device on which we're capturing
+				 * went away, or it became unusable
+				 * by NPF due to a suspend/resume.
+				 *
+				 * XXX - hopefully no other error
+				 * conditions are indicated by this.
+				 *
+				 * XXX - we really should return an
+				 * appropriate error for that, but
+				 * pcap_dispatch() etc. aren't
+				 * documented as having error returns
+				 * other than PCAP_ERROR or PCAP_ERROR_BREAK.
+				 */
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "The interface disappeared");
+			} else {
+				pcap_fmt_errmsg_for_win32_err(p->errbuf,
+				    PCAP_ERRBUF_SIZE, errcode,
+				    "PacketReceivePacket error");
+			}
 			return (PCAP_ERROR);
 		}
 
@@ -549,9 +583,10 @@
 	 * Loop through each packet.
 	 */
 #define bhp ((struct bpf_hdr *)bp)
+	n = 0;
 	ep = bp + cc;
 	for (;;) {
-		register int caplen, hdrlen;
+		register u_int caplen, hdrlen;
 
 		/*
 		 * Has "pcap_breakloop()" been called?
@@ -585,13 +620,13 @@
 		 * in kernel, no need to do it now - we already know
 		 * the packet passed the filter.
 		 *
-		 * XXX - bpf_filter() should always return TRUE if
+		 * XXX - pcap_filter() should always return TRUE if
 		 * handed a null pointer for the program, but it might
 		 * just try to "run" the filter, so we check here.
 		 */
 		if (pw->filtering_in_kernel ||
 		    p->fcode.bf_insns == NULL ||
-		    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+		    pcap_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
 #ifdef ENABLE_REMOTE
 			switch (p->rmt_samp.method) {
 
@@ -690,7 +725,7 @@
 		 */
 		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
 		if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
 			return (-1);
 		}
 
@@ -798,7 +833,7 @@
 		/* No underlaying filtering system. We need to filter on our own */
 		if (p->fcode.bf_insns)
 		{
-			if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
+			if (pcap_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
 			{
 				/* Move to next packet */
 				header = (dag_record_t*)((char*)header + erf_record_len);
@@ -832,14 +867,14 @@
 
 /* Send a packet to the network */
 static int
-pcap_inject_npf(pcap_t *p, const void *buf, size_t size)
+pcap_inject_npf(pcap_t *p, const void *buf, int size)
 {
 	struct pcap_win *pw = p->priv;
 	PACKET pkt;
 
 	PacketInitPacket(&pkt, (PVOID)buf, size);
 	if(PacketSendPacket(pw->adapter,&pkt,TRUE) == FALSE) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
 		return (-1);
 	}
 
@@ -848,7 +883,7 @@
 	 * "pcap_inject()" is expected to return the number of bytes
 	 * sent.
 	 */
-	return ((int)size);
+	return (size);
 }
 
 static void
@@ -867,13 +902,25 @@
 	pcap_cleanup_live_common(p);
 }
 
+static void
+pcap_breakloop_npf(pcap_t *p)
+{
+	pcap_breakloop_common(p);
+	struct pcap_win *pw = p->priv;
+
+	/* XXX - what if this fails? */
+	SetEvent(PacketGetReadEvent(pw->adapter));
+}
+
 static int
 pcap_activate_npf(pcap_t *p)
 {
 	struct pcap_win *pw = p->priv;
 	NetType type;
 	int res;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
+	int status = 0;
+	struct bpf_insn total_insn;
+	struct bpf_program total_prog;
 
 	if (p->opt.rfmon) {
 		/*
@@ -905,30 +952,52 @@
 		}
 	}
 
-	/* Init WinSock */
+	/* Init Winsock if it hasn't already been initialized */
 	pcap_wsockinit();
 
 	pw->adapter = PacketOpenAdapter(p->opt.device);
 
 	if (pw->adapter == NULL)
 	{
-		/* Adapter detected but we are not able to open it. Return failure. */
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		if (pw->rfmon_selfstart)
-		{
-			PacketSetMonitorMode(p->opt.device, 0);
+		DWORD errcode = GetLastError();
+
+		/*
+		 * What error did we get when trying to open the adapter?
+		 */
+		switch (errcode) {
+
+		case ERROR_BAD_UNIT:
+			/*
+			 * There's no such device.
+			 */
+			return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+		case ERROR_ACCESS_DENIED:
+			/*
+			 * There is, but we don't have permission to
+			 * use it.
+			 */
+			return (PCAP_ERROR_PERM_DENIED);
+
+		default:
+			/*
+			 * Unknown - report details.
+			 */
+			pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errcode, "Error opening adapter");
+			if (pw->rfmon_selfstart)
+			{
+				PacketSetMonitorMode(p->opt.device, 0);
+			}
+			return (PCAP_ERROR);
 		}
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error opening adapter: %s", errbuf);
-		return (PCAP_ERROR);
 	}
 
 	/*get network type*/
 	if(PacketGetNetType (pw->adapter,&type) == FALSE)
 	{
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Cannot determine the network type: %s", errbuf);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "Cannot determine the network type");
 		goto bad;
 	}
 
@@ -1006,11 +1075,89 @@
 		p->linktype = DLT_PPI;
 		break;
 
+	case NdisMediumWirelessWan:
+		p->linktype = DLT_RAW;
+		break;
+
 	default:
-		p->linktype = DLT_EN10MB;			/*an unknown adapter is assumed to be ethernet*/
+		/*
+		 * An unknown medium type is assumed to supply Ethernet
+		 * headers; if not, the user will have to report it,
+		 * so that the medium type and link-layer header type
+		 * can be determined.  If we were to fail here, we
+		 * might get the link-layer type in the error, but
+		 * the user wouldn't get a capture, so we wouldn't
+		 * be able to determine the link-layer type; we report
+		 * a warning with the link-layer type, so at least
+		 * some programs will report the warning.
+		 */
+		p->linktype = DLT_EN10MB;
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Unknown NdisMedium value %d, defaulting to DLT_EN10MB",
+		    type.LinkType);
+		status = PCAP_WARNING;
 		break;
 	}
 
+#ifdef HAVE_PACKET_GET_TIMESTAMP_MODES
+	/*
+	 * Set the timestamp type.
+	 * (Yes, we require PacketGetTimestampModes(), not just
+	 * PacketSetTimestampMode().  If we have the former, we
+	 * have the latter, unless somebody's using a version
+	 * of Npcap that they've hacked to provide the former
+	 * but not the latter; if they've done that, either
+	 * they're confused or they're trolling us.)
+	 */
+	switch (p->opt.tstamp_type) {
+
+	case PCAP_TSTAMP_HOST_HIPREC_UNSYNCED:
+		/*
+		 * Better than low-res, but *not* synchronized with
+		 * the OS clock.
+		 */
+		if (!PacketSetTimestampMode(pw->adapter, TIMESTAMPMODE_SINGLE_SYNCHRONIZATION))
+		{
+			pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+			    GetLastError(), "Cannot set the time stamp mode to TIMESTAMPMODE_SINGLE_SYNCHRONIZATION");
+			goto bad;
+		}
+		break;
+
+	case PCAP_TSTAMP_HOST_LOWPREC:
+		/*
+		 * Low-res, but synchronized with the OS clock.
+		 */
+		if (!PacketSetTimestampMode(pw->adapter, TIMESTAMPMODE_QUERYSYSTEMTIME))
+		{
+			pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+			    GetLastError(), "Cannot set the time stamp mode to TIMESTAMPMODE_QUERYSYSTEMTIME");
+			goto bad;
+		}
+		break;
+
+	case PCAP_TSTAMP_HOST_HIPREC:
+		/*
+		 * High-res, and synchronized with the OS clock.
+		 */
+		if (!PacketSetTimestampMode(pw->adapter, TIMESTAMPMODE_QUERYSYSTEMTIME_PRECISE))
+		{
+			pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+			    GetLastError(), "Cannot set the time stamp mode to TIMESTAMPMODE_QUERYSYSTEMTIME_PRECISE");
+			goto bad;
+		}
+		break;
+
+	case PCAP_TSTAMP_HOST:
+		/*
+		 * XXX - do whatever the default is, for now.
+		 * Set to the highest resolution that's synchronized
+		 * with the system clock?
+		 */
+		break;
+	}
+#endif /* HAVE_PACKET_GET_TIMESTAMP_MODES */
+
 	/*
 	 * Turn a negative snapshot value (invalid), a snapshot value of
 	 * 0 (unspecified), or a value bigger than the normal maximum
@@ -1028,7 +1175,9 @@
 
 		if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+			pcap_fmt_errmsg_for_win32_err(p->errbuf,
+			    PCAP_ERRBUF_SIZE, GetLastError(),
+			    "failed to set hardware filter to promiscuous mode");
 			goto bad;
 		}
 	}
@@ -1046,7 +1195,9 @@
 			NDIS_PACKET_TYPE_BROADCAST |
 			NDIS_PACKET_TYPE_MULTICAST) == FALSE)
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+			pcap_fmt_errmsg_for_win32_err(p->errbuf,
+			    PCAP_ERRBUF_SIZE, GetLastError(),
+			    "failed to set hardware filter to non-promiscuous mode");
 			goto bad;
 		}
 	}
@@ -1063,12 +1214,12 @@
 		 * If the buffer size wasn't explicitly set, default to
 		 * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
 		 */
-	 	if (p->opt.buffer_size == 0)
-	 		p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
+		if (p->opt.buffer_size == 0)
+			p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
 
 		if(PacketSetBuff(pw->adapter,p->opt.buffer_size)==FALSE)
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
 			goto bad;
 		}
 
@@ -1085,10 +1236,9 @@
 			/* tell the driver to copy the buffer as soon as data arrives */
 			if(PacketSetMinToCopy(pw->adapter,0)==FALSE)
 			{
-				pcap_win32_err_to_str(GetLastError(), errbuf);
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "Error calling PacketSetMinToCopy: %s",
-				    errbuf);
+				pcap_fmt_errmsg_for_win32_err(p->errbuf,
+				    PCAP_ERRBUF_SIZE, GetLastError(),
+				    "Error calling PacketSetMinToCopy");
 				goto bad;
 			}
 		}
@@ -1097,10 +1247,9 @@
 			/* tell the driver to copy the buffer only if it contains at least 16K */
 			if(PacketSetMinToCopy(pw->adapter,16000)==FALSE)
 			{
-				pcap_win32_err_to_str(GetLastError(), errbuf);
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "Error calling PacketSetMinToCopy: %s",
-				    errbuf);
+				pcap_fmt_errmsg_for_win32_err(p->errbuf,
+				    PCAP_ERRBUF_SIZE, GetLastError(),
+				    "Error calling PacketSetMinToCopy");
 				goto bad;
 			}
 		}
@@ -1119,7 +1268,7 @@
 		int		postype = 0;
 		char	keyname[512];
 
-		pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+		snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
 			"SYSTEM\\CurrentControlSet\\Services\\DAG",
 			strstr(_strlwr(p->opt.device), "dag"));
 		do
@@ -1158,6 +1307,29 @@
 #endif /* HAVE_DAG_API */
 	}
 
+	/*
+	 * If there's no filter program installed, there's
+	 * no indication to the kernel of what the snapshot
+	 * length should be, so no snapshotting is done.
+	 *
+	 * Therefore, when we open the device, we install
+	 * an "accept everything" filter with the specified
+	 * snapshot length.
+	 */
+	total_insn.code = (u_short)(BPF_RET | BPF_K);
+	total_insn.jt = 0;
+	total_insn.jf = 0;
+	total_insn.k = p->snapshot;
+
+	total_prog.bf_len = 1;
+	total_prog.bf_insns = &total_insn;
+	if (!PacketSetBpf(pw->adapter, &total_prog)) {
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "PacketSetBpf");
+		status = PCAP_ERROR;
+		goto bad;
+	}
+
 	PacketSetReadTimeout(pw->adapter, p->opt.timeout);
 
 	/* disable loopback capture if requested */
@@ -1165,7 +1337,7 @@
 	{
 		if (!PacketSetLoopbackBehavior(pw->adapter, NPF_DISABLE_LOOPBACK))
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "Unable to disable the capture of loopback packets.");
 			goto bad;
 		}
@@ -1194,6 +1366,7 @@
 	p->getnonblock_op = pcap_getnonblock_npf;
 	p->setnonblock_op = pcap_setnonblock_npf;
 	p->stats_op = pcap_stats_npf;
+	p->breakloop_op = pcap_breakloop_npf;
 	p->stats_ex_op = pcap_stats_ex_npf;
 	p->setbuff_op = pcap_setbuff_npf;
 	p->setmode_op = pcap_setmode_npf;
@@ -1221,7 +1394,7 @@
 	 */
 	p->handle = pw->adapter->hFile;
 
-	return (0);
+	return (status);
 bad:
 	pcap_cleanup_npf(p);
 	return (PCAP_ERROR);
@@ -1240,13 +1413,177 @@
 pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
+#ifdef HAVE_PACKET_GET_TIMESTAMP_MODES
+	char *device_copy;
+	ADAPTER *adapter;
+	ULONG num_ts_modes;
+	BOOL ret;
+	DWORD error;
+	ULONG *modes;
+#endif
 
-	p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_win);
 	if (p == NULL)
 		return (NULL);
 
 	p->activate_op = pcap_activate_npf;
 	p->can_set_rfmon_op = pcap_can_set_rfmon_npf;
+
+#ifdef HAVE_PACKET_GET_TIMESTAMP_MODES
+	/*
+	 * First, find out how many time stamp modes we have.
+	 * To do that, we have to open the adapter.
+	 *
+	 * XXX - PacketOpenAdapter() takes a non-const pointer
+	 * as an argument, so we make a copy of the argument and
+	 * pass that to it.
+	 */
+	device_copy = strdup(device);
+	adapter = PacketOpenAdapter(device_copy);
+	free(device_copy);
+	if (adapter != NULL)
+	{
+		/*
+		 * Get the total number of time stamp modes.
+		 *
+		 * The buffer for PacketGetTimestampModes() is
+		 * a sequence of 1 or more ULONGs.  What's
+		 * passed to PacketGetTimestampModes() should have
+		 * the total number of ULONGs in the first ULONG;
+		 * what's returned *from* PacketGetTimestampModes()
+		 * has the total number of time stamp modes in
+		 * the first ULONG.
+		 *
+		 * Yes, that means if there are N time stamp
+		 * modes, the first ULONG should be set to N+1
+		 * on input, and will be set to N on output.
+		 *
+		 * We first make a call to PacketGetTimestampModes()
+		 * with a pointer to a single ULONG set to 1; the
+		 * call should fail with ERROR_MORE_DATA (unless
+		 * there are *no* modes, but that should never
+		 * happen), and that ULONG should be set to the
+		 * number of modes.
+		 */
+		num_ts_modes = 1;
+		ret = PacketGetTimestampModes(adapter, &num_ts_modes);
+		if (!ret) {
+			/*
+			 * OK, it failed.  Did it fail with
+			 * ERROR_MORE_DATA?
+			 */
+			error = GetLastError();
+			if (error != ERROR_MORE_DATA) {
+				/*
+				 * No, some other error.  Fail.
+				 */
+				pcap_fmt_errmsg_for_win32_err(ebuf,
+				    PCAP_ERRBUF_SIZE, GetLastError(),
+				    "Error calling PacketGetTimestampModes");
+				pcap_close(p);
+				return (NULL);
+			}
+
+			/*
+			 * Yes, so we now know how many types to fetch.
+			 *
+		    	 * The buffer needs to have one ULONG for the
+		    	 * count and num_ts_modes ULONGs for the
+		    	 * num_ts_modes time stamp types.
+		    	 */
+			modes = (ULONG *)malloc((1 + num_ts_modes) * sizeof(ULONG));
+			if (modes == NULL) {
+				/* Out of memory. */
+				/* XXX SET ebuf */
+				pcap_close(p);
+				return (NULL);
+			}
+			modes[0] = 1 + num_ts_modes;
+			if (!PacketGetTimestampModes(adapter, modes)) {
+				pcap_fmt_errmsg_for_win32_err(ebuf,
+				    PCAP_ERRBUF_SIZE, GetLastError(),
+				    "Error calling PacketGetTimestampModes");
+				free(modes);
+				pcap_close(p);
+				return (NULL);
+			}
+			if (modes[0] != num_ts_modes) {
+				snprintf(ebuf, PCAP_ERRBUF_SIZE,
+				    "First PacketGetTimestampModes() call gives %lu modes, second call gives %u modes",
+				    num_ts_modes, modes[0]);
+				free(modes);
+				pcap_close(p);
+				return (NULL);
+			}
+			if (num_ts_modes != 0) {
+				u_int num_ts_types;
+
+				/*
+				 * Allocate a buffer big enough for
+				 * PCAP_TSTAMP_HOST (default) plus
+				 * the explicitly specified modes.
+				 */
+				p->tstamp_type_list = malloc((1 + modes[0]) * sizeof(u_int));
+				if (p->tstamp_type_list == NULL) {
+					/* XXX SET ebuf */
+					free(modes);
+					pcap_close(p);
+					return (NULL);
+				}
+				num_ts_types = 0;
+				p->tstamp_type_list[num_ts_types] =
+				    PCAP_TSTAMP_HOST;
+				num_ts_types++;
+				for (ULONG i = 0; i < modes[0]; i++) {
+					switch (modes[i + 1]) {
+
+					case TIMESTAMPMODE_SINGLE_SYNCHRONIZATION:
+						/*
+						 * Better than low-res,
+						 * but *not* synchronized
+						 * with the OS clock.
+						 */
+						p->tstamp_type_list[num_ts_types] =
+						    PCAP_TSTAMP_HOST_HIPREC_UNSYNCED;
+						num_ts_types++;
+						break;
+
+					case TIMESTAMPMODE_QUERYSYSTEMTIME:
+						/*
+						 * Low-res, but synchronized
+						 * with the OS clock.
+						 */
+						p->tstamp_type_list[num_ts_types] =
+						    PCAP_TSTAMP_HOST_LOWPREC;
+						num_ts_types++;
+						break;
+
+					case TIMESTAMPMODE_QUERYSYSTEMTIME_PRECISE:
+						/*
+						 * High-res, and synchronized
+						 * with the OS clock.
+						 */
+						p->tstamp_type_list[num_ts_types] =
+						    PCAP_TSTAMP_HOST_HIPREC;
+						num_ts_types++;
+						break;
+
+					default:
+						/*
+						 * Unknown, so we can't
+						 * report it.
+						 */
+						break;
+					}
+				}
+				p->tstamp_type_count = num_ts_types;
+				free(modes);
+			}
+		}
+		PacketCloseAdapter(adapter);
+	}
+#endif /* HAVE_PACKET_GET_TIMESTAMP_MODES */
+
 	return (p);
 }
 
@@ -1309,14 +1646,14 @@
 }
 
 /*
- * We filter at user level, since the kernel driver does't process the packets
+ * We filter at user level, since the kernel driver doesn't process the packets
  */
 static int
 pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
 
 	if(!fp)
 	{
-		strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+		pcap_strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
 		return (-1);
 	}
 
@@ -1345,7 +1682,6 @@
 {
 	struct pcap_win *pw = p->priv;
 	int newtimeout;
-	char win_errbuf[PCAP_ERRBUF_SIZE+1];
 
 	if (nonblock) {
 		/*
@@ -1365,9 +1701,8 @@
 		newtimeout = p->opt.timeout;
 	}
 	if (!PacketSetReadTimeout(pw->adapter, newtimeout)) {
-		pcap_win32_err_to_str(GetLastError(), win_errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketSetReadTimeout: %s", win_errbuf);
+		pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "PacketSetReadTimeout");
 		return (-1);
 	}
 	pw->nonblock = (newtimeout == -1);
@@ -1551,6 +1886,12 @@
 			 * running.
 			 */
 			break;
+
+		default:
+			/*
+			 * Unknown.
+			 */
+			break;
 		}
 	} else {
 		/*
@@ -1587,7 +1928,13 @@
 	if (status == 0) {
 		/*
 		 * We got the physical medium.
+		 *
+		 * XXX - we might want to check for NdisPhysicalMediumWiMax
+		 * and NdisPhysicalMediumNative802_15_4 being
+		 * part of the enum, and check for those in the "wireless"
+		 * case.
 		 */
+DIAG_OFF_ENUM_SWITCH
 		switch (phys_medium) {
 
 		case NdisPhysicalMediumWirelessLan:
@@ -1604,10 +1951,11 @@
 
 		default:
 			/*
-			 * Not wireless.
+			 * Not wireless or unknown
 			 */
 			break;
 		}
+DIAG_ON_ENUM_SWITCH
 	}
 #endif
 
@@ -1638,6 +1986,13 @@
 			 */
 			*flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
 			break;
+
+		case MediaConnectStateUnknown:
+		default:
+			/*
+			 * It's unknown whether it's connected or not.
+			 */
+			break;
 		}
 	}
 #else
@@ -1684,7 +2039,6 @@
 	char *AdaptersName;
 	ULONG NameLength;
 	char *name;
-	char our_errbuf[PCAP_ERRBUF_SIZE+1];
 
 	/*
 	 * Find out how big a buffer we need.
@@ -1710,9 +2064,8 @@
 
 		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);
+			pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+			    last_error, "PacketGetAdapterNames");
 			return (-1);
 		}
 	}
@@ -1722,14 +2075,13 @@
 	AdaptersName = (char*) malloc(NameLength);
 	if (AdaptersName == NULL)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+		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);
+		pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "PacketGetAdapterNames");
 		free(AdaptersName);
 		return (-1);
 	}
@@ -1764,6 +2116,20 @@
 	name = &AdaptersName[0];
 	while (*name != '\0') {
 		bpf_u_int32 flags = 0;
+
+#ifdef HAVE_AIRPCAP_API
+		/*
+		 * Is this an AirPcap device?
+		 * If so, ignore it; it'll get added later, by the
+		 * AirPcap code.
+		 */
+		if (device_is_airpcap(name, errbuf) == 1) {
+			name += strlen(name) + 1;
+			desc += strlen(desc) + 1;
+			continue;
+		}
+#endif
+
 #ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
 		/*
 		 * Is this a loopback interface?
@@ -1818,12 +2184,27 @@
 {
 	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 */
+	/*
+	 * We disable this in "new API" mode, because 1) in WinPcap/Npcap,
+	 * it may return UTF-16 strings, for backwards-compatibility
+	 * reasons, and we're also disabling the hack to make that work,
+	 * for not-going-past-the-end-of-a-string reasons, and 2) we
+	 * want its behavior to be consistent.
+	 *
+	 * In addition, it's not thread-safe, so we've marked it as
+	 * deprecated.
+	 */
+	if (pcap_new_api) {
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "pcap_lookupdev() is deprecated and is not supported in programs calling pcap_init()");
+		return (NULL);
+	}
+
+/* disable MSVC's GetVersion() deprecated warning here */
+DIAG_OFF_DEPRECATION
 	dwVersion = GetVersion();	/* get the OS version */
-#pragma warning (pop)
+DIAG_ON_DEPRECATION
 	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
 
 	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
@@ -1854,15 +2235,14 @@
 
 		if(TAdaptersName == NULL)
 		{
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
+			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
 			return NULL;
 		}
 
 		if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
 		{
-			pcap_win32_err_to_str(GetLastError(), our_errbuf);
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				"PacketGetAdapterNames: %s", our_errbuf);
+			pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+			    GetLastError(), "PacketGetAdapterNames");
 			free(TAdaptersName);
 			return NULL;
 		}
@@ -2000,59 +2380,48 @@
  * 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.)
+ * XXX - it'd be nice if we could somehow generate the WinPcap/Npcap version
+ * number when building as part of WinPcap/Npcap.  (It'd be nice to do so
+ * for the packet.dll version number as well.)
  */
 #include "../../version.h"
 
 static const char pcap_version_string[] =
 	WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
-static const char pcap_version_string_packet_dll_fmt[] =
-	WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING;
 
 const char *
 pcap_lib_version(void)
 {
-	char *packet_version_string;
-	size_t full_pcap_version_string_len;
-	char *full_pcap_version_string;
-
 	if (pcap_lib_version_string == NULL) {
 		/*
 		 * Generate the version string.
 		 */
-		packet_version_string = PacketGetVersion();
+		const char *packet_version_string = PacketGetVersion();
+
 		if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
 			/*
-			 * WinPcap version string and packet.dll version
-			 * string are the same; just report the WinPcap
+			 * WinPcap/Npcap version string and packet.dll version
+			 * string are the same; just report the WinPcap/Npcap
 			 * version.
 			 */
 			pcap_lib_version_string = pcap_version_string;
 		} else {
 			/*
-			 * WinPcap version string and packet.dll version
+			 * WinPcap/Npcap version string and packet.dll version
 			 * string are different; that shouldn't be the
 			 * case (the two libraries should come from the
-			 * same version of WinPcap), so we report both
+			 * same version of WinPcap/Npcap), so we report both
 			 * versions.
-			 *
-			 * The -2 is for the %s in the format string,
-			 * which will be replaced by packet_version_string.
 			 */
-			full_pcap_version_string_len =
-			    (sizeof pcap_version_string_packet_dll_fmt - 2) +
-			    strlen(packet_version_string);
-			full_pcap_version_string = malloc(full_pcap_version_string_len);
-			if (full_pcap_version_string == NULL)
-				return (NULL);
-			pcap_snprintf(full_pcap_version_string,
-			    full_pcap_version_string_len,
-			    pcap_version_string_packet_dll_fmt,
-			    packet_version_string);
+			char *full_pcap_version_string;
+
+			if (pcap_asprintf(&full_pcap_version_string,
+			    WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING,
+			    packet_version_string) != -1) {
+				/* Success */
+				pcap_lib_version_string = full_pcap_version_string;
+			}
 		}
-		pcap_lib_version_string = full_pcap_version_string;
 	}
 	return (pcap_lib_version_string);
 }
@@ -2063,35 +2432,22 @@
  * libpcap being built for Windows, not as part of a WinPcap/Npcap source
  * tree.
  */
-static const char pcap_version_string_packet_dll_fmt[] =
-	PCAP_VERSION_STRING " (packet.dll version %s)";
 const char *
 pcap_lib_version(void)
 {
-	char *packet_version_string;
-	size_t full_pcap_version_string_len;
-	char *full_pcap_version_string;
-
 	if (pcap_lib_version_string == NULL) {
 		/*
 		 * Generate the version string.  Report the packet.dll
 		 * version.
-		 *
-		 * The -2 is for the %s in the format string, which will
-		 * be replaced by packet_version_string.
 		 */
-		packet_version_string = PacketGetVersion();
-		full_pcap_version_string_len =
-		    (sizeof pcap_version_string_packet_dll_fmt - 2) +
-		    strlen(packet_version_string);
-		full_pcap_version_string = malloc(full_pcap_version_string_len);
-		if (full_pcap_version_string == NULL)
-			return (NULL);
-		pcap_snprintf(full_pcap_version_string,
-		    full_pcap_version_string_len,
-		    pcap_version_string_packet_dll_fmt,
-		    packet_version_string);
-		pcap_lib_version_string = full_pcap_version_string;
+		char *full_pcap_version_string;
+
+		if (pcap_asprintf(&full_pcap_version_string,
+		    PCAP_VERSION_STRING " (packet.dll version %s)",
+		    PacketGetVersion()) != -1) {
+			/* Success */
+			pcap_lib_version_string = full_pcap_version_string;
+		}
 	}
 	return (pcap_lib_version_string);
 }
diff --git a/pcap-null.c b/pcap-null.c
index 92a5e2d..2ae27bf 100644
--- a/pcap-null.c
+++ b/pcap-null.c
@@ -32,12 +32,12 @@
 pcap_t *
 pcap_create_interface(const char *device _U_, char *ebuf)
 {
-	(void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
+	(void)pcap_strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
 	return (NULL);
 }
 
 int
-pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf _U_)
 {
 	/*
 	 * There are no interfaces on which we can capture.
@@ -50,7 +50,7 @@
 pcap_lookupnet(const char *device _U_, bpf_u_int32 *netp _U_,
     bpf_u_int32 *maskp _U_, char *errbuf)
 {
-	(void)strlcpy(errbuf, nosup, PCAP_ERRBUF_SIZE);
+	(void)pcap_strlcpy(errbuf, nosup, PCAP_ERRBUF_SIZE);
 	return (-1);
 }
 #endif
diff --git a/pcap-pf.c b/pcap-pf.c
index fde97ba..4563a22 100644
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -48,7 +48,6 @@
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -104,9 +103,7 @@
 	register u_char *p, *bp;
 	register int cc, n, buflen, inc;
 	register struct enstamp *sp;
-#ifdef LBL_ALIGN
 	struct enstamp stamp;
-#endif
 	register u_int pad;
 
  again:
@@ -160,19 +157,17 @@
 			}
 		}
 		if (cc < sizeof(*sp)) {
-			pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
+			snprintf(pc->errbuf, sizeof(pc->errbuf),
 			    "pf short read (%d)", cc);
 			return (-1);
 		}
-#ifdef LBL_ALIGN
 		if ((long)bp & 3) {
 			sp = &stamp;
 			memcpy((char *)sp, (char *)bp, sizeof(*sp));
 		} else
-#endif
 			sp = (struct enstamp *)bp;
 		if (sp->ens_stamplen != sizeof(*sp)) {
-			pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
+			snprintf(pc->errbuf, sizeof(pc->errbuf),
 			    "pf short stamplen (%d)",
 			    sp->ens_stamplen);
 			return (-1);
@@ -205,7 +200,7 @@
 		 * skipping that padding.
 		 */
 		if (pf->filtering_in_kernel ||
-		    bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
+		    pcap_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
 			struct pcap_pkthdr h;
 			pf->TotAccepted++;
 			h.ts = sp->ens_tstamp;
@@ -226,7 +221,7 @@
 }
 
 static int
-pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
+pcap_inject_pf(pcap_t *p, const void *buf, int size)
 {
 	int ret;
 
@@ -261,7 +256,7 @@
 	 *	full.
 	 *
 	 *	"ps_ifdrop" counts packets dropped by the network
-	 *	inteface (regardless of whether they would have passed
+	 *	interface (regardless of whether they would have passed
 	 *	the input filter, of course).
 	 *
 	 * If packet filtering is not being done in the kernel:
@@ -273,7 +268,7 @@
 	 *	the userland filter.
 	 *
 	 *	"ps_ifdrop" counts packets dropped by the network
-	 *	inteface (regardless of whether they would have passed
+	 *	interface (regardless of whether they would have passed
 	 *	the input filter, of course).
 	 *
 	 * These statistics don't include packets not yet read from
@@ -331,7 +326,7 @@
 		p->fd = pfopen(p->opt.device, O_RDONLY);
 	if (p->fd < 0) {
 		if (errno == EACCES) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "pf open: %s: Permission denied\n"
 "your system may not be properly configured; see the packetfilter(4) man page",
 			    p->opt.device);
@@ -464,7 +459,7 @@
 		 * framing", there's not much we can do, as that
 		 * doesn't specify a particular type of header.
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown data-link type %u", devparams.end_dev_type);
 		err = PCAP_ERROR;
 		goto bad;
@@ -540,7 +535,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_pf);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-rdmasniff.c b/pcap-rdmasniff.c
index c50fe3f..224821d 100644
--- a/pcap-rdmasniff.c
+++ b/pcap-rdmasniff.c
@@ -57,7 +57,7 @@
 	struct ibv_flow *               flow;
 	struct ibv_mr *			mr;
 	u_char *			oneshot_buffer;
-	unsigned			port_num;
+	unsigned long			port_num;
 	int                             cq_event;
 	u_int                           packets_recv;
 };
@@ -156,7 +156,7 @@
 		pktd = (u_char *) handle->buffer + wc.wr_id * RDMASNIFF_RECEIVE_SIZE;
 
 		if (handle->fcode.bf_insns == NULL ||
-		    bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+		    pcap_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
 			callback(user, &pkth, pktd);
 			++priv->packets_recv;
 			++count;
@@ -197,21 +197,21 @@
 
 	priv->context = ibv_open_device(priv->rdma_device);
 	if (!priv->context) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to open device %s", handle->opt.device);
 		goto error;
 	}
 
 	priv->pd = ibv_alloc_pd(priv->context);
 	if (!priv->pd) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to alloc PD for device %s", handle->opt.device);
 		goto error;
 	}
 
 	priv->channel = ibv_create_comp_channel(priv->context);
 	if (!priv->channel) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to create comp channel for device %s", handle->opt.device);
 		goto error;
 	}
@@ -219,7 +219,7 @@
 	priv->cq = ibv_create_cq(priv->context, RDMASNIFF_NUM_RECEIVES,
 				 NULL, priv->channel, 0);
 	if (!priv->cq) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to create CQ for device %s", handle->opt.device);
 		goto error;
 	}
@@ -233,7 +233,7 @@
 	qp_init_attr.qp_type = IBV_QPT_RAW_PACKET;
 	priv->qp = ibv_create_qp(priv->pd, &qp_init_attr);
 	if (!priv->qp) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to create QP for device %s", handle->opt.device);
 		goto error;
 	}
@@ -242,7 +242,7 @@
 	qp_attr.qp_state = IBV_QPS_INIT;
 	qp_attr.port_num = priv->port_num;
 	if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE | IBV_QP_PORT)) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to modify QP to INIT for device %s", handle->opt.device);
 		goto error;
 	}
@@ -250,7 +250,7 @@
 	memset(&qp_attr, 0, sizeof qp_attr);
 	qp_attr.qp_state = IBV_QPS_RTR;
 	if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE)) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to modify QP to RTR for device %s", handle->opt.device);
 		goto error;
 	}
@@ -261,7 +261,7 @@
 	flow_attr.port = priv->port_num;
 	priv->flow = ibv_create_flow(priv->qp, &flow_attr);
 	if (!priv->flow) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to create flow for device %s", handle->opt.device);
 		goto error;
 	}
@@ -269,21 +269,21 @@
 	handle->bufsize = RDMASNIFF_NUM_RECEIVES * RDMASNIFF_RECEIVE_SIZE;
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to allocate receive buffer for device %s", handle->opt.device);
 		goto error;
 	}
 
 	priv->oneshot_buffer = malloc(RDMASNIFF_RECEIVE_SIZE);
 	if (!priv->oneshot_buffer) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to allocate oneshot buffer for device %s", handle->opt.device);
 		goto error;
 	}
 
 	priv->mr = ibv_reg_mr(priv->pd, handle->buffer, handle->bufsize, IBV_ACCESS_LOCAL_WRITE);
 	if (!priv->mr) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			      "Failed to register MR for device %s", handle->opt.device);
 		goto error;
 	}
@@ -361,14 +361,18 @@
 	int numdev;
 	size_t namelen;
 	const char *port;
-	unsigned port_num;
+	unsigned long port_num;
 	int i;
 	pcap_t *p = NULL;
 
 	*is_ours = 0;
 
 	dev_list = ibv_get_device_list(&numdev);
-	if (!dev_list || !numdev) {
+	if (!dev_list) {
+		return NULL;
+	}
+	if (!numdev) {
+		ibv_free_device_list(dev_list);
 		return NULL;
 	}
 
@@ -391,7 +395,7 @@
 		    !strncmp(device, dev_list[i]->name, namelen)) {
 			*is_ours = 1;
 
-			p = pcap_create_common(ebuf, sizeof (struct pcap_rdmasniff));
+			p = PCAP_CREATE_COMMON(ebuf, struct pcap_rdmasniff);
 			if (p) {
 				p->activate_op = rdmasniff_activate;
 				priv = p->priv;
@@ -415,7 +419,7 @@
 	int ret = 0;
 
 	dev_list = ibv_get_device_list(&numdev);
-	if (!dev_list || !numdev) {
+	if (!dev_list) {
 		return 0;
 	}
 
@@ -426,11 +430,10 @@
 		 */
 		if (!add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) {
 			ret = -1;
-			goto out;
+			break;
 		}
 	}
 
-out:
 	ibv_free_device_list(dev_list);
 	return ret;
 }
diff --git a/pcap-rpcap.c b/pcap-rpcap.c
index e9d6245..a2612e9 100644
--- a/pcap-rpcap.c
+++ b/pcap-rpcap.c
@@ -46,6 +46,14 @@
 #include "rpcap-protocol.h"
 #include "pcap-rpcap.h"
 
+#ifdef _WIN32
+#include "charconv.h"		/* for utf_8_to_acp_truncated() */
+#endif
+
+#ifdef HAVE_OPENSSL
+#include "sslutils.h"
+#endif
+
 /*
  * This file contains the pcap module for capturing from a remote machine's
  * interfaces using the RPCAP protocol.
@@ -83,6 +91,7 @@
 {
 	struct sockaddr_storage host;
 	SOCKET sockctrl;
+	SSL *ssl;
 	uint8 protocol_version;
 	struct activehosts *next;
 };
@@ -97,6 +106,7 @@
  * pcap_remoteact_cleanup() for more details.
  */
 static SOCKET sockmain;
+static SSL *ssl_main;
 
 /*
  * Private data for capturing remotely using the rpcap protocol.
@@ -111,11 +121,13 @@
 
 	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 */
+	SSL *ctrl_ssl, *data_ssl;	/* optional transport of rmt_sockctrl and rmt_sockdata via TLS */
 	int rmt_flags;			/* we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture() */
 	int rmt_capstarted;		/* 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture() */
 	char *currentfilter;		/* Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on. */
 
 	uint8 protocol_version;		/* negotiated protocol version */
+	uint8 uses_ssl;				/* User asked for rpcaps scheme */
 
 	unsigned int TotNetDrops;	/* keeps the number of packets that have been dropped by the network */
 
@@ -155,15 +167,14 @@
 static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog);
 static int pcap_setsampling_remote(pcap_t *fp);
 static int pcap_startcapture_remote(pcap_t *fp);
-static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf);
-static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf);
-static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
-static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
-static int rpcap_process_msg_header(SOCKET sock, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
-static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf);
-static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf);
-static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf);
-static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size);
+static int rpcap_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_ver(SOCKET sock, SSL *, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_type(SOCKET sock, SSL *, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
+static int rpcap_process_msg_header(SOCKET sock, SSL *, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
+static int rpcap_recv(SOCKET sock, SSL *, void *buffer, size_t toread, uint32 *plen, char *errbuf);
+static void rpcap_msg_err(SOCKET sockctrl, SSL *, uint32 plen, char *remote_errbuf);
+static int rpcap_discard(SOCKET sock, SSL *, uint32 len, char *errbuf);
+static int rpcap_read_packet_msg(struct pcap_rpcap const *, pcap_t *p, size_t size);
 
 /****************************************************
  *                                                  *
@@ -376,7 +387,7 @@
 	struct rpcap_pkthdr *net_pkt_header;	/* header of the packet, from the message */
 	u_char *net_pkt_data;			/* packet data from the message */
 	uint32 plen;
-	int retval;				/* generic return value */
+	int retval = 0;				/* generic return value */
 	int msglen;
 
 	/* Structures needed for the select() call */
@@ -388,29 +399,42 @@
 	 * '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;
+	tv.tv_usec = (suseconds_t)((p->opt.timeout - tv.tv_sec * 1000) * 1000);
 
-	/* Watch out sockdata to see if it has input */
-	FD_ZERO(&rfds);
-
-	/*
-	 * 'fp->rmt_sockdata' has always to be set before calling the select(),
-	 * since it is cleared by the select()
-	 */
-	FD_SET(pr->rmt_sockdata, &rfds);
-
-	retval = select((int) pr->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
-	if (retval == -1)
-	{
-#ifndef _WIN32
-		if (errno == EINTR)
-		{
-			/* Interrupted. */
-			return 0;
-		}
+#ifdef HAVE_OPENSSL
+	/* Check if we still have bytes available in the last decoded TLS record.
+	 * If that's the case, we know SSL_read will not block. */
+	retval = pr->data_ssl && SSL_pending(pr->data_ssl) > 0;
 #endif
-		sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE);
-		return -1;
+	if (! retval)
+	{
+		/* Watch out sockdata to see if it has input */
+		FD_ZERO(&rfds);
+
+		/*
+		 * 'fp->rmt_sockdata' has always to be set before calling the select(),
+		 * since it is cleared by the select()
+		 */
+		FD_SET(pr->rmt_sockdata, &rfds);
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+		retval = 1;
+#else
+		retval = select((int) pr->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+#endif
+
+		if (retval == -1)
+		{
+#ifndef _WIN32
+			if (errno == EINTR)
+			{
+				/* Interrupted. */
+				return 0;
+			}
+#endif
+			sock_geterror("select()", p->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
 	}
 
 	/* There is no data waiting, so return '0' */
@@ -428,7 +452,7 @@
 	if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
 	{
 		/* Read the entire message from the network */
-		msglen = sock_recv_dgram(pr->rmt_sockdata, p->buffer,
+		msglen = sock_recv_dgram(pr->rmt_sockdata, pr->data_ssl, p->buffer,
 		    p->bufsize, p->errbuf, PCAP_ERRBUF_SIZE);
 		if (msglen == -1)
 		{
@@ -445,7 +469,7 @@
 			/*
 			 * Message is shorter than an rpcap header.
 			 */
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "UDP packet message is shorter than an rpcap header");
 			return -1;
 		}
@@ -456,7 +480,7 @@
 			 * Message is shorter than the header claims it
 			 * is.
 			 */
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "UDP packet message is shorter than its rpcap header claims");
 			return -1;
 		}
@@ -472,8 +496,7 @@
 			 * The size we should get is the size of the
 			 * packet header.
 			 */
-			status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
-			    sizeof(struct rpcap_header));
+			status = rpcap_read_packet_msg(pr, p, sizeof(struct rpcap_header));
 			if (status == -1)
 			{
 				/* Network error. */
@@ -501,12 +524,11 @@
 			 * subtracting in order to avoid an
 			 * overflow.)
 			 */
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "Server sent us a message larger than the largest expected packet message");
 			return -1;
 		}
-		status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
-		    sizeof(struct rpcap_header) + plen);
+		status = rpcap_read_packet_msg(pr, p, sizeof(struct rpcap_header) + plen);
 		if (status == -1)
 		{
 			/* Network error. */
@@ -535,7 +557,7 @@
 	/*
 	 * Did the server specify the version we negotiated?
 	 */
-	if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->protocol_version,
+	if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->data_ssl, pr->protocol_version,
 	    header, p->errbuf) == -1)
 	{
 		return 0;	/* Return 'no packets received' */
@@ -551,7 +573,7 @@
 
 	if (ntohl(net_pkt_header->caplen) > plen)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Packet's captured data goes past the end of the received packet message.");
 		return -1;
 	}
@@ -679,7 +701,9 @@
 }
 
 /*
- * This function sends a CLOSE command to the capture server.
+ * This function sends a CLOSE command to the capture server if we're in
+ * passive mode and an ENDCAP command to the capture server if we're in
+ * active mode.
  *
  * It is called when the user calls pcap_close().  It sends a command
  * to our peer that says 'ok, let's stop capturing'.
@@ -715,7 +739,7 @@
 		 * we're closing this pcap_t, and have no place to report
 		 * the error.  No reply is sent to this message.
 		 */
-		(void)sock_send(pr->rmt_sockctrl, (char *)&header,
+		(void)sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
 		    sizeof(struct rpcap_header), NULL, 0);
 	}
 	else
@@ -728,7 +752,7 @@
 		 * as we're closing this pcap_t, and have no place to
 		 * report the error.
 		 */
-		if (sock_send(pr->rmt_sockctrl, (char *)&header,
+		if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
 		    sizeof(struct rpcap_header), NULL, 0) == 0)
 		{
 			/*
@@ -736,11 +760,11 @@
 			 * as we're closing this pcap_t, and have no
 			 * place to report the error.
 			 */
-			if (rpcap_process_msg_header(pr->rmt_sockctrl,
+			if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl,
 			    pr->protocol_version, RPCAP_MSG_ENDCAP_REQ,
 			    &header, NULL) == 0)
 			{
-				(void)rpcap_discard(pr->rmt_sockctrl,
+				(void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl,
 				    header.plen, NULL);
 			}
 		}
@@ -748,14 +772,35 @@
 
 	if (pr->rmt_sockdata)
 	{
+#ifdef HAVE_OPENSSL
+		if (pr->data_ssl)
+		{
+			// Finish using the SSL handle for the data socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(pr->data_ssl);
+			pr->data_ssl = NULL;
+		}
+#endif
 		sock_close(pr->rmt_sockdata, NULL, 0);
 		pr->rmt_sockdata = 0;
 	}
 
 	if ((!active) && (pr->rmt_sockctrl))
+	{
+#ifdef HAVE_OPENSSL
+		if (pr->ctrl_ssl)
+		{
+			// Finish using the SSL handle for the control socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(pr->ctrl_ssl);
+			pr->ctrl_ssl = NULL;
+		}
+#endif
 		sock_close(pr->rmt_sockctrl, NULL, 0);
+	}
 
 	pr->rmt_sockctrl = 0;
+	pr->ctrl_ssl = NULL;
 
 	if (pr->currentfilter)
 	{
@@ -763,6 +808,8 @@
 		pr->currentfilter = NULL;
 	}
 
+	pcap_cleanup_live_common(fp);
+
 	/* To avoid inconsistencies in the number of sock_init() */
 	sock_cleanup();
 }
@@ -847,7 +894,7 @@
 	if (mode != PCAP_STATS_STANDARD)
 #endif
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Invalid stats mode %d", mode);
 		return NULL;
 	}
@@ -878,19 +925,19 @@
 	    RPCAP_MSG_STATS_REQ, 0, 0);
 
 	/* Send the PCAP_STATS command */
-	if (sock_send(pr->rmt_sockctrl, (char *)&header,
+	if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
 	    sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) < 0)
 		return NULL;		/* Unrecoverable network error */
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
 	    RPCAP_MSG_STATS_REQ, &header, p->errbuf) == -1)
 		return NULL;		/* Error */
 
 	plen = header.plen;
 
 	/* Read the reply body */
-	if (rpcap_recv(pr->rmt_sockctrl, (char *)&netstats,
+	if (rpcap_recv(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&netstats,
 	    sizeof(struct rpcap_stats), &plen, p->errbuf) == -1)
 		goto error;
 
@@ -907,7 +954,7 @@
 #endif /* _WIN32 */
 
 	/* Discard the rest of the message. */
-	if (rpcap_discard(pr->rmt_sockctrl, plen, p->errbuf) == -1)
+	if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, p->errbuf) == -1)
 		goto error_nodiscard;
 
 	return ps;
@@ -918,7 +965,7 @@
 	 * We already reported an error; if this gets an error, just
 	 * drive on.
 	 */
-	(void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+	(void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
 	return NULL;
@@ -959,7 +1006,7 @@
 	retval = getaddrinfo(host, "0", &hints, &addrinfo);
 	if (retval != 0)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s",
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s",
 		    gai_strerror(retval));
 		*error = 1;
 		return NULL;
@@ -1038,6 +1085,10 @@
 	int sockbufsize = 0;
 	uint32 server_sockbufsize;
 
+	// Take the opportunity to clear pr->data_ssl before any goto error,
+	// as it seems pr->priv is not zeroed after its malloced.
+	pr->data_ssl = NULL;
+
 	/*
 	 * Let's check if sampling has been required.
 	 * If so, let's set it first
@@ -1069,7 +1120,7 @@
 	saddrlen = sizeof(struct sockaddr_storage);
 	if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 	{
-		sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+		sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
 		goto error_nodiscard;
 	}
 	ai_family = ((struct sockaddr_storage *) &saddr)->ss_family;
@@ -1078,7 +1129,7 @@
 	if (getnameinfo((struct sockaddr *) &saddr, saddrlen, host,
 		sizeof(host), NULL, 0, NI_NUMERICHOST))
 	{
-		sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+		sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
 		goto error_nodiscard;
 	}
 
@@ -1116,7 +1167,7 @@
 		saddrlen = sizeof(struct sockaddr_storage);
 		if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
-			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			goto error_nodiscard;
 		}
 
@@ -1124,7 +1175,7 @@
 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
 			0, portdata, sizeof(portdata), NI_NUMERICSERV))
 		{
-			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			goto error_nodiscard;
 		}
 	}
@@ -1177,18 +1228,18 @@
 	if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode))
 		goto error_nodiscard;
 
-	if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+	if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
 	    PCAP_ERRBUF_SIZE) < 0)
 		goto error_nodiscard;
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
 	    RPCAP_MSG_STARTCAP_REQ, &header, fp->errbuf) == -1)
 		goto error_nodiscard;
 
 	plen = header.plen;
 
-	if (rpcap_recv(pr->rmt_sockctrl, (char *)&startcapreply,
+	if (rpcap_recv(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&startcapreply,
 	    sizeof(struct rpcap_startcapreply), &plen, fp->errbuf) == -1)
 		goto error;
 
@@ -1210,7 +1261,7 @@
 			memset(&hints, 0, sizeof(struct addrinfo));
 			hints.ai_family = ai_family;		/* Use the same address family of the control socket */
 			hints.ai_socktype = (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
-			pcap_snprintf(portdata, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
+			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)
@@ -1234,7 +1285,7 @@
 
 			if (socktemp == INVALID_SOCKET)
 			{
-				sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+				sock_geterror("accept()", fp->errbuf, PCAP_ERRBUF_SIZE);
 				goto error;
 			}
 
@@ -1247,6 +1298,14 @@
 	/* Let's save the socket of the data connection */
 	pr->rmt_sockdata = sockdata;
 
+#ifdef HAVE_OPENSSL
+	if (pr->uses_ssl)
+	{
+		pr->data_ssl = ssl_promotion(0, sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
+		if (! pr->data_ssl) goto error;
+	}
+#endif
+
 	/*
 	 * Set the size of the socket buffer for the data socket.
 	 * It has the same size as the local capture buffer used
@@ -1260,8 +1319,8 @@
 	res = getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &itemp);
 	if (res == -1)
 	{
-		sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
-		SOCK_DEBUG_MESSAGE(fp->errbuf);
+		sock_geterror("pcap_startcapture_remote(): getsockopt() failed", fp->errbuf, PCAP_ERRBUF_SIZE);
+		goto error;
 	}
 
 	/*
@@ -1334,7 +1393,7 @@
 	fp->cc = 0;
 
 	/* Discard the rest of the message. */
-	if (rpcap_discard(pr->rmt_sockctrl, plen, fp->errbuf) == -1)
+	if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, fp->errbuf) == -1)
 		goto error_nodiscard;
 
 	/*
@@ -1374,14 +1433,36 @@
 	 * We already reported an error; if this gets an error, just
 	 * drive on.
 	 */
-	(void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+	(void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
-	if ((sockdata) && (sockdata != -1))		/* we can be here because sockdata said 'error' */
+#ifdef HAVE_OPENSSL
+	if (pr->data_ssl)
+	{
+		// Finish using the SSL handle for the data socket.
+		// This must be done *before* the socket is closed.
+		ssl_finish(pr->data_ssl);
+		pr->data_ssl = NULL;
+	}
+#endif
+
+	/* we can be here because sockdata said 'error' */
+	if ((sockdata != 0) && (sockdata != INVALID_SOCKET))
 		sock_close(sockdata, NULL, 0);
 
 	if (!active)
+	{
+#ifdef HAVE_OPENSSL
+		if (pr->ctrl_ssl)
+		{
+			// Finish using the SSL handle for the control socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(pr->ctrl_ssl);
+			pr->ctrl_ssl = NULL;
+		}
+#endif
 		sock_close(pr->rmt_sockctrl, NULL, 0);
+	}
 
 	if (addrinfo != NULL)
 		freeaddrinfo(addrinfo);
@@ -1407,7 +1488,7 @@
  * This function can be called in two cases:
  * - pcap_startcapture_remote() is called (we have to send the filter
  *   along with the 'start capture' command)
- * - we want to udpate the filter during a capture (i.e. pcap_setfilter()
+ * - we want to update the filter during a capture (i.e. pcap_setfilter()
  *   after the capture has been started)
  *
  * This function serializes the filter into the sending buffer ('sendbuf',
@@ -1514,19 +1595,19 @@
 	if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog))
 		return -1;
 
-	if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+	if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
 	    PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
 	    RPCAP_MSG_UPDATEFILTER_REQ, &header, fp->errbuf) == -1)
 		return -1;
 
 	/*
 	 * It shouldn't have any contents; discard it if it does.
 	 */
-	if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+	if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, header.plen, fp->errbuf) == -1)
 		return -1;
 
 	return 0;
@@ -1612,21 +1693,19 @@
 		char peeraddress[128];
 		char peerctrlport[128];
 		char *newfilter;
-		const int newstringsize = 1024;
-		size_t currentfiltersize;
 
 		/* Get the name/port of our peer */
 		saddrlen = sizeof(struct sockaddr_storage);
 		if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
-			sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			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);
+			sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
 		}
 
@@ -1634,7 +1713,7 @@
 		/* Get the name/port of the current host */
 		if (getsockname(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
-			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
 		}
 
@@ -1642,43 +1721,60 @@
 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, myaddress,
 			sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
 		{
-			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
 		}
 
 		/* Let's now check the data port */
 		if (getsockname(pr->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
-			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			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);
+			sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
 		}
 
-		currentfiltersize = pr->currentfilter ? strlen(pr->currentfilter) : 0;
-
-		newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
-
-		if (currentfiltersize)
+		if (pr->currentfilter && pr->currentfilter[0] != '\0')
 		{
-			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)",
-				pr->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+			/*
+			 * We have a current filter; add items to it to
+			 * filter out this rpcap session.
+			 */
+			if (pcap_asprintf(&newfilter,
+			    "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+			    pr->currentfilter, myaddress, peeraddress,
+			    myctrlport, peerctrlport, myaddress, peeraddress,
+			    mydataport) == -1)
+			{
+				/* Failed. */
+				snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+				    "Can't allocate memory for new filter");
+				return -1;
+			}
 		}
 		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);
+			/*
+			 * We have no current filter; construct a filter to
+			 * filter out this rpcap session.
+			 */
+			if (pcap_asprintf(&newfilter,
+			    "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+			    myaddress, peeraddress, myctrlport, peerctrlport,
+			    myaddress, peeraddress, mydataport) == -1)
+			{
+				/* Failed. */
+				snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+				    "Can't allocate memory for new filter");
+				return -1;
+			}
 		}
 
-		newfilter[currentfiltersize + newstringsize] = 0;
-
 		/*
 		 * This is only an hack to prevent the save_current_filter
 		 * routine, which will be called when we call pcap_compile(),
@@ -1729,12 +1825,12 @@
 	 * that do fit into the message.
 	 */
 	if (fp->rmt_samp.method < 0 || fp->rmt_samp.method > 255) {
-		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
 		    "Invalid sampling method %d", fp->rmt_samp.method);
 		return -1;
 	}
 	if (fp->rmt_samp.value < 0 || fp->rmt_samp.value > 65535) {
-		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
 		    "Invalid sampling value %d", fp->rmt_samp.value);
 		return -1;
 	}
@@ -1759,19 +1855,19 @@
 	sampling_pars->method = (uint8)fp->rmt_samp.method;
 	sampling_pars->value = (uint16)htonl(fp->rmt_samp.value);
 
-	if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+	if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
 	    PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+	if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
 	    RPCAP_MSG_SETSAMPLING_REQ, &header, fp->errbuf) == -1)
 		return -1;
 
 	/*
 	 * It shouldn't have any contents; discard it if it does.
 	 */
-	if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+	if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, header.plen, fp->errbuf) == -1)
 		return -1;
 
 	return 0;
@@ -1785,16 +1881,25 @@
 
 /*
  * This function performs authentication and protocol version
- * negotiation.  It first tries to authenticate with the maximum
- * version we support and, if that fails with an "I don't support
- * that version" error from the server, and the version number in
- * the reply from the server is one we support, tries again with
- * that version.
+ * negotiation.  It is required in order to open the connection
+ * with the other end party.
+ *
+ * It sends authentication parameters on the control socket and
+ * reads the reply.  If the reply is a success indication, it
+ * checks whether the reply includes minimum and maximum supported
+ * versions from the server; if not, it assumes both are 0, as
+ * that means it's an older server that doesn't return supported
+ * version numbers in authentication replies, so it only supports
+ * version 0.  It then tries to determine the maximum version
+ * supported both by us and by the server.  If it can find such a
+ * version, it sets us up to use that version; otherwise, it fails,
+ * indicating that there is no version supported by us and by the
+ * server.
  *
  * \param sock: the socket we are currently using.
  *
- * \param ver: pointer to variable holding protocol version number to send
- * and to set to the protocol version number in the reply.
+ * \param ver: pointer to variable to which to set the protocol version
+ * number we selected.
  *
  * \param auth: authentication parameters that have to be sent.
  *
@@ -1806,97 +1911,18 @@
  * \return '0' if everything is fine, '-1' for an error.  For errors,
  * an error message string is returned in the 'errbuf' variable.
  */
-static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
-{
-	int status;
-
-	/*
-	 * Send authentication to the remote machine.
-	 *
-	 * First try with the maximum version number we support.
-	 */
-	*ver = RPCAP_MAX_VERSION;
-	status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
-	if (status == 0)
-	{
-		//
-		// Success.
-		//
-		return 0;
-	}
-	if (status == -1)
-	{
-		/* Unrecoverable error. */
-		return -1;
-	}
-
-	/*
-	 * The server doesn't support the version we used in the initial
-	 * message, and it sent us back a reply either with the maximum
-	 * version they do support, or with the version we sent, and we
-	 * support that version.  *ver has been set to that version; try
-	 * authenticating again with that version.
-	 */
-	status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
-	if (status == 0)
-	{
-		//
-		// Success.
-		//
-		return 0;
-	}
-	if (status == -1)
-	{
-		/* Unrecoverable error. */
-		return -1;
-	}
-	if (status == -2)
-	{
-		/*
-		 * The server doesn't support that version, which
-		 * means there is no version we both support, so
-		 * this is a fatal error.
-		 */
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
-		return -1;
-	}
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "rpcap_sendauth() returned %d", status);
-	return -1;
-}
-
-/*
- * This function sends the authentication message.
- *
- * It sends the authentication parameters on the control socket.
- * It is required in order to open the connection with the other end party.
- *
- * \param sock: the socket we are currently using.
- *
- * \param ver: pointer to variable holding protocol version number to send
- * and to set to the protocol version number in the reply.
- *
- * \param auth: authentication parameters that have to be sent.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size
- * PCAP_ERRBUF_SIZE) that will contain the error message (in case there
- * is one). It could be a network problem or the fact that the authorization
- * failed.
- *
- * \return '0' if everything is fine, '-2' if the server didn't reply with
- * the protocol version we requested but replied with a version we do
- * support, or '-1' for other errors.  For errors, an error message string
- * is returned in the 'errbuf' variable.
- */
-static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
+static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
 {
 	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data that has to be sent is buffered */
 	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
 	uint16 length;				/* length of the payload of this message */
-	uint16 errcode;
 	struct rpcap_auth *rpauth;
 	uint16 auth_type;
 	struct rpcap_header header;
 	size_t str_length;
+	uint32 plen;
+	struct rpcap_authreply authreply;	/* authentication reply message */
+	uint8 ourvers;
 
 	if (auth)
 	{
@@ -1913,7 +1939,7 @@
 				str_length = strlen(auth->username);
 				if (str_length > 65535)
 				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "User name is too long (> 65535 bytes)");
+					snprintf(errbuf, PCAP_ERRBUF_SIZE, "User name is too long (> 65535 bytes)");
 					return -1;
 				}
 				length += (uint16)str_length;
@@ -1923,7 +1949,7 @@
 				str_length = strlen(auth->password);
 				if (str_length > 65535)
 				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Password is too long (> 65535 bytes)");
+					snprintf(errbuf, PCAP_ERRBUF_SIZE, "Password is too long (> 65535 bytes)");
 					return -1;
 				}
 				length += (uint16)str_length;
@@ -1931,7 +1957,7 @@
 			break;
 
 		default:
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
 			return -1;
 		}
 
@@ -1943,12 +1969,11 @@
 		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, *ver,
+	rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
 	    RPCAP_MSG_AUTH_REQ, 0, length);
 
 	rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
@@ -1985,69 +2010,111 @@
 		rpauth->slen2 = htons(rpauth->slen2);
 	}
 
-	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+	if (sock_send(sockctrl, ssl, sendbuf, sendbufidx, errbuf,
+	    PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
-	/* Receive the reply */
-	if (rpcap_recv_msg_header(sock, &header, errbuf) == -1)
+	/* Receive and process the reply message header */
+	if (rpcap_process_msg_header(sockctrl, ssl, 0, RPCAP_MSG_AUTH_REQ,
+	    &header, errbuf) == -1)
 		return -1;
 
-	if (rpcap_check_msg_type(sock, RPCAP_MSG_AUTH_REQ, &header,
-	    &errcode, errbuf) == -1)
+	/*
+	 * OK, it's an authentication reply, so we're logged in.
+	 *
+	 * Did it send any additional information?
+	 */
+	plen = header.plen;
+	if (plen != 0)
 	{
-		/* Error message - or something else, which is a protocol error. */
-		if (header.type == RPCAP_MSG_ERROR &&
-		    errcode == PCAP_ERR_WRONGVER)
+		/* Yes - is it big enough to be version information? */
+		if (plen < sizeof(struct rpcap_authreply))
 		{
-			/*
-			 * The server didn't support the version we sent,
-			 * and replied with the maximum version it supports
-			 * if our version was too big or with the version
-			 * we sent if out version was too small.
-			 *
-			 * Do we also support it?
-			 */
-			if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
-			{
-				/*
-				 * No, so there's no version we both support.
-				 * This is an unrecoverable error.
-				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
-				return -1;
-			}
-
-			/*
-			 * OK, use that version, and tell our caller to
-			 * try again.
-			 */
-			*ver = header.ver;
-			return -2;
+			/* No - discard it and fail. */
+			(void)rpcap_discard(sockctrl, ssl, plen, NULL);
+			return -1;
 		}
 
+		/* Read the reply body */
+		if (rpcap_recv(sockctrl, ssl, (char *)&authreply,
+		    sizeof(struct rpcap_authreply), &plen, errbuf) == -1)
+		{
+			(void)rpcap_discard(sockctrl, ssl, plen, NULL);
+			return -1;
+		}
+
+		/* Discard the rest of the message, if there is any. */
+		if (rpcap_discard(sockctrl, ssl, plen, errbuf) == -1)
+			return -1;
+
 		/*
-		 * Other error - unrecoverable.
+		 * Check the minimum and maximum versions for sanity;
+		 * the minimum must be <= the maximum.
 		 */
-		return -1;
+		if (authreply.minvers > authreply.maxvers)
+		{
+			/*
+			 * Bogus - give up on this server.
+			 */
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "The server's minimum supported protocol version is greater than its maximum supported protocol version");
+			return -1;
+		}
+	}
+	else
+	{
+		/* No - it supports only version 0. */
+		authreply.minvers = 0;
+		authreply.maxvers = 0;
 	}
 
 	/*
-	 * OK, it's an authentication reply, so they're OK with the
-	 * protocol version we sent.
-	 *
-	 * Discard the rest of it.
+	 * OK, let's start with the maximum version the server supports.
 	 */
-	if (rpcap_discard(sock, header.plen, errbuf) == -1)
-		return -1;
+	ourvers = authreply.maxvers;
 
+#if RPCAP_MIN_VERSION != 0
+	/*
+	 * If that's less than the minimum version we support, we
+	 * can't communicate.
+	 */
+	if (ourvers < RPCAP_MIN_VERSION)
+		goto novers;
+#endif
+
+	/*
+	 * If that's greater than the maximum version we support,
+	 * choose the maximum version we support.
+	 */
+	if (ourvers > RPCAP_MAX_VERSION)
+	{
+		ourvers = RPCAP_MAX_VERSION;
+
+		/*
+		 * If that's less than the minimum version they
+		 * support, we can't communicate.
+		 */
+		if (ourvers < authreply.minvers)
+			goto novers;
+	}
+
+	*ver = ourvers;
 	return 0;
+
+novers:
+	/*
+	 * There is no version we both support; that is a fatal error.
+	 */
+	snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	    "The server doesn't support any protocol version that we support");
+	return -1;
 }
 
 /* We don't currently support non-blocking mode. */
 static int
 pcap_getnonblock_rpcap(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for capturing remotely with rpcap");
 	return (-1);
 }
@@ -2055,11 +2122,150 @@
 static int
 pcap_setnonblock_rpcap(pcap_t *p, int nonblock _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for capturing remotely with rpcap");
 	return (-1);
 }
 
+static int
+rpcap_setup_session(const char *source, struct pcap_rmtauth *auth,
+    int *activep, SOCKET *sockctrlp, uint8 *uses_sslp, SSL **sslp,
+    int rmt_flags, uint8 *protocol_versionp, char *host, char *port,
+    char *iface, char *errbuf)
+{
+	int type;
+	struct activehosts *activeconn;		/* active connection, if there is one */
+	int error;				/* 1 if rpcap_remoteact_getsock got an error */
+
+	/*
+	 * Determine the type of the source (NULL, file, local, remote).
+	 * You must have a valid source string even if we're in active mode,
+	 * because otherwise the call to the following function will fail.
+	 */
+	if (pcap_parsesrcstr_ex(source, &type, host, port, iface, uses_sslp,
+	    errbuf) == -1)
+		return -1;
+
+	/*
+	 * It must be remote.
+	 */
+	if (type != PCAP_SRC_IFREMOTE)
+	{
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Non-remote interface passed to remote capture routine");
+		return -1;
+	}
+
+	/*
+	 * We don't yet support DTLS, so if the user asks for a TLS
+	 * connection and asks for data packets to be sent over UDP,
+	 * we have to give up.
+	 */
+	if (*uses_sslp && (rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	{
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "TLS not supported with UDP forward of remote packets");
+		return -1;
+	}
+
+	/* Warning: this call can be the first one called by the user. */
+	/* For this reason, we have to initialize the Winsock support. */
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Check for active mode */
+	activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
+	if (activeconn != NULL)
+	{
+		*activep = 1;
+		*sockctrlp = activeconn->sockctrl;
+		*sslp = activeconn->ssl;
+		*protocol_versionp = activeconn->protocol_version;
+	}
+	else
+	{
+		*activep = 0;
+		struct addrinfo hints;		/* temp variable needed to resolve hostnames into to socket representation */
+		struct addrinfo *addrinfo;	/* temp variable needed to resolve hostnames into to socket representation */
+
+		if (error)
+		{
+			/*
+			 * Call failed.
+			 */
+			return -1;
+		}
+
+		/*
+		 * We're not in active mode; let's try to open a new
+		 * control connection.
+		 */
+		memset(&hints, 0, sizeof(struct addrinfo));
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = SOCK_STREAM;
+
+		if (port[0] == 0)
+		{
+			/* the user chose not to specify the port */
+			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
+			    &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+		else
+		{
+			if (sock_initaddress(host, port, &hints, &addrinfo,
+			    errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+
+		if ((*sockctrlp = sock_open(addrinfo, SOCKOPEN_CLIENT, 0,
+		    errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+		{
+			freeaddrinfo(addrinfo);
+			return -1;
+		}
+
+		/* addrinfo is no longer used */
+		freeaddrinfo(addrinfo);
+		addrinfo = NULL;
+
+		if (*uses_sslp)
+		{
+#ifdef HAVE_OPENSSL
+			*sslp = ssl_promotion(0, *sockctrlp, errbuf,
+			    PCAP_ERRBUF_SIZE);
+			if (!*sslp)
+			{
+				sock_close(*sockctrlp, NULL, 0);
+				return -1;
+			}
+#else
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "No TLS support");
+			sock_close(*sockctrlp, NULL, 0);
+			return -1;
+#endif
+		}
+
+		if (rpcap_doauth(*sockctrlp, *sslp, protocol_versionp, auth,
+		    errbuf) == -1)
+		{
+#ifdef HAVE_OPENSSL
+			if (*sslp)
+			{
+				// Finish using the SSL handle for the socket.
+				// This must be done *before* the socket is
+				// closed.
+				ssl_finish(*sslp);
+			}
+#endif
+			sock_close(*sockctrlp, NULL, 0);
+			return -1;
+		}
+	}
+	return 0;
+}
+
 /*
  * This function opens a remote adapter by opening an RPCAP connection and
  * so on.
@@ -2105,21 +2311,19 @@
 	char *source_str;
 	struct pcap_rpcap *pr;		/* structure used when doing a remote live capture */
 	char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
-	struct activehosts *activeconn;		/* active connection, if there is one */
-	int error;				/* '1' if rpcap_remoteact_getsock returned an error */
 	SOCKET sockctrl;
+	SSL *ssl = NULL;
 	uint8 protocol_version;			/* negotiated protocol version */
 	int active;
 	uint32 plen;
 	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data to be sent is buffered */
 	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
-	int retval;				/* store the return value of the functions */
 
 	/* RPCAP-related variables */
 	struct rpcap_header header;		/* header of the RPCAP packet */
 	struct rpcap_openreply openreply;	/* open reply message */
 
-	fp = pcap_create_common(errbuf, sizeof (struct pcap_rpcap));
+	fp = PCAP_CREATE_COMMON(errbuf, struct pcap_rpcap);
 	if (fp == NULL)
 	{
 		return NULL;
@@ -2152,99 +2356,19 @@
 	pr->rmt_flags = flags;
 
 	/*
-	 * determine the type of the source (NULL, file, local, remote)
-	 * You must have a valid source string even if we're in active mode, because otherwise
-	 * the call to the following function will fail.
+	 * Attempt to set up the session with the server.
 	 */
-	if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, errbuf) == -1)
+	if (rpcap_setup_session(fp->opt.device, auth, &active, &sockctrl,
+	    &pr->uses_ssl, &ssl, flags, &protocol_version, host, ctrlport,
+	    iface, errbuf) == -1)
 	{
+		/* Session setup failed. */
 		pcap_close(fp);
 		return NULL;
 	}
 
-	if (retval != PCAP_SRC_IFREMOTE)
-	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
-		pcap_close(fp);
-		return NULL;
-	}
-
-	/*
-	 * Warning: this call can be the first one called by the user.
-	 * For this reason, we have to initialize the WinSock support.
-	 */
-	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
-	{
-		pcap_close(fp);
-		return NULL;
-	}
-
-	/* Check for active mode */
-	activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
-	if (activeconn != NULL)
-	{
-		sockctrl = activeconn->sockctrl;
-		protocol_version = activeconn->protocol_version;
-		active = 1;
-	}
-	else
-	{
-		struct addrinfo hints;			/* temp, needed to open a socket connection */
-		struct addrinfo *addrinfo;		/* temp, needed to open a socket connection */
-
-		if (error)
-		{
-			/*
-			 * Call failed.
-			 */
-			pcap_close(fp);
-			return NULL;
-		}
-
-		/*
-		 * We're not in active mode; let's try to open a new
-		 * control connection.
-		 */
-		memset(&hints, 0, sizeof(struct addrinfo));
-		hints.ai_family = PF_UNSPEC;
-		hints.ai_socktype = SOCK_STREAM;
-
-		if (ctrlport[0] == 0)
-		{
-			/* the user chose not to specify the port */
-			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-			{
-				pcap_close(fp);
-				return NULL;
-			}
-		}
-		else
-		{
-			if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-			{
-				pcap_close(fp);
-				return NULL;
-			}
-		}
-
-		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
-		{
-			freeaddrinfo(addrinfo);
-			pcap_close(fp);
-			return NULL;
-		}
-
-		/* addrinfo is no longer used */
-		freeaddrinfo(addrinfo);
-
-		if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
-		{
-			sock_close(sockctrl, NULL, 0);
-			pcap_close(fp);
-			return NULL;
-		}
-		active = 0;
-	}
+	/* All good so far, save the ssl handler */
+	ssl_main = ssl;
 
 	/*
 	 * Now it's time to start playing with the RPCAP protocol
@@ -2261,29 +2385,29 @@
 		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
 		goto error_nodiscard;
 
-	if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf,
+	if (sock_send(sockctrl, ssl, sendbuf, sendbufidx, errbuf,
 	    PCAP_ERRBUF_SIZE) < 0)
 		goto error_nodiscard;
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(sockctrl, protocol_version,
+	if (rpcap_process_msg_header(sockctrl, ssl, protocol_version,
 	    RPCAP_MSG_OPEN_REQ, &header, errbuf) == -1)
 		goto error_nodiscard;
 	plen = header.plen;
 
 	/* Read the reply body */
-	if (rpcap_recv(sockctrl, (char *)&openreply,
+	if (rpcap_recv(sockctrl, ssl, (char *)&openreply,
 	    sizeof(struct rpcap_openreply), &plen, errbuf) == -1)
 		goto error;
 
 	/* Discard the rest of the message, if there is any. */
-	if (rpcap_discard(pr->rmt_sockctrl, plen, errbuf) == -1)
+	if (rpcap_discard(sockctrl, ssl, plen, errbuf) == -1)
 		goto error_nodiscard;
 
 	/* Set proper fields into the pcap_t struct */
 	fp->linktype = ntohl(openreply.linktype);
-	fp->tzoff = ntohl(openreply.tzoff);
 	pr->rmt_sockctrl = sockctrl;
+	pr->ctrl_ssl = ssl;
 	pr->protocol_version = protocol_version;
 	pr->rmt_clientside = 1;
 
@@ -2315,11 +2439,21 @@
 	 * We already reported an error; if this gets an error, just
 	 * drive on.
 	 */
-	(void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+	(void)rpcap_discard(sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
 	if (!active)
+	{
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
+	}
 
 	pcap_close(fp);
 	return NULL;
@@ -2327,8 +2461,10 @@
 
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof PCAP_TEXT_SOURCE_ADAPTER - 1)
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_REMOTE_HOST - 1)
 
 static void
 freeaddr(struct pcap_addr *addr)
@@ -2341,18 +2477,17 @@
 }
 
 int
-pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
 {
-	struct activehosts *activeconn;	/* active connection, if there is one */
-	int error;			/* '1' if rpcap_remoteact_getsock returned an error */
 	uint8 protocol_version;		/* protocol version */
 	SOCKET sockctrl;		/* socket descriptor of the control connection */
+	SSL *ssl = NULL;		/* optional SSL handler for sockctrl */
 	uint32 plen;
 	struct rpcap_header header;	/* structure that keeps the general header of the rpcap protocol */
 	int i, j;		/* temp variables */
 	int nif;		/* Number of interfaces listed */
 	int active;			/* 'true' if we the other end-party is in active mode */
-	int type;
+	uint8 uses_ssl;
 	char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE];
 	char tmpstring[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
 	pcap_if_t *lastdev;	/* Last device in the pcap_if_t list */
@@ -2362,84 +2497,26 @@
 	(*alldevs) = NULL;
 	lastdev = NULL;
 
-	/* Retrieve the needed data for getting adapter list */
-	if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
-		return -1;
-
-	/* Warning: this call can be the first one called by the user. */
-	/* For this reason, we have to initialize the WinSock support. */
-	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
-		return -1;
-
-	/* Check for active mode */
-	activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
-	if (activeconn != NULL)
+	/*
+	 * Attempt to set up the session with the server.
+	 */
+	if (rpcap_setup_session(source, auth, &active, &sockctrl, &uses_ssl,
+	    &ssl, 0, &protocol_version, host, port, NULL, errbuf) == -1)
 	{
-		sockctrl = activeconn->sockctrl;
-		protocol_version = activeconn->protocol_version;
-		active = 1;
-	}
-	else
-	{
-		struct addrinfo hints;		/* temp variable needed to resolve hostnames into to socket representation */
-		struct addrinfo *addrinfo;	/* temp variable needed to resolve hostnames into to socket representation */
-
-		if (error)
-		{
-			/*
-			 * Call failed.
-			 */
-			return -1;
-		}
-
-		/*
-		 * We're not in active mode; let's try to open a new
-		 * control connection.
-		 */
-		memset(&hints, 0, sizeof(struct addrinfo));
-		hints.ai_family = PF_UNSPEC;
-		hints.ai_socktype = SOCK_STREAM;
-
-		if (port[0] == 0)
-		{
-			/* the user chose not to specify the port */
-			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-		else
-		{
-			if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-
-		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
-		{
-			freeaddrinfo(addrinfo);
-			return -1;
-		}
-
-		/* addrinfo is no longer used */
-		freeaddrinfo(addrinfo);
-		addrinfo = NULL;
-
-		if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
-		{
-			sock_close(sockctrl, NULL, 0);
-			return -1;
-		}
-		active = 0;
+		/* Session setup failed. */
+		return -1;
 	}
 
 	/* RPCAP findalldevs command */
 	rpcap_createhdr(&header, protocol_version, RPCAP_MSG_FINDALLIF_REQ,
 	    0, 0);
 
-	if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header),
+	if (sock_send(sockctrl, ssl, (char *)&header, sizeof(struct rpcap_header),
 	    errbuf, PCAP_ERRBUF_SIZE) < 0)
 		goto error_nodiscard;
 
 	/* Receive and process the reply message header. */
-	if (rpcap_process_msg_header(sockctrl, protocol_version,
+	if (rpcap_process_msg_header(sockctrl, ssl, protocol_version,
 	    RPCAP_MSG_FINDALLIF_REQ, &header, errbuf) == -1)
 		goto error_nodiscard;
 
@@ -2453,13 +2530,12 @@
 	{
 		struct rpcap_findalldevs_if findalldevs_if;
 		char tmpstring2[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
-		size_t stringlen;
 		struct pcap_addr *addr, *prevaddr;
 
 		tmpstring2[PCAP_BUF_SIZE] = 0;
 
 		/* receive the findalldevs structure from remote host */
-		if (rpcap_recv(sockctrl, (char *)&findalldevs_if,
+		if (rpcap_recv(sockctrl, ssl, (char *)&findalldevs_if,
 		    sizeof(struct rpcap_findalldevs_if), &plen, errbuf) == -1)
 			goto error;
 
@@ -2503,66 +2579,54 @@
 
 			if (findalldevs_if.namelen >= sizeof(tmpstring))
 			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
+				snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
 				goto error;
 			}
 
 			/* Retrieve adapter name */
-			if (rpcap_recv(sockctrl, tmpstring,
+			if (rpcap_recv(sockctrl, ssl, tmpstring,
 			    findalldevs_if.namelen, &plen, errbuf) == -1)
 				goto error;
 
 			tmpstring[findalldevs_if.namelen] = 0;
 
 			/* Create the new device identifier */
-			if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
-				return -1;
+			if (pcap_createsrcstr_ex(tmpstring2, PCAP_SRC_IFREMOTE,
+			    host, port, tmpstring, uses_ssl, errbuf) == -1)
+				goto error;
 
-			stringlen = strlen(tmpstring2);
-
-			dev->name = (char *)malloc(stringlen + 1);
+			dev->name = strdup(tmpstring2);
 			if (dev->name == NULL)
 			{
 				pcap_fmt_errmsg_for_errno(errbuf,
 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
 				goto error;
 			}
-
-			/* Copy the new device name into the correct memory location */
-			strlcpy(dev->name, tmpstring2, stringlen + 1);
 		}
 
 		if (findalldevs_if.desclen)
 		{
 			if (findalldevs_if.desclen >= sizeof(tmpstring))
 			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
+				snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
 				goto error;
 			}
 
 			/* Retrieve adapter description */
-			if (rpcap_recv(sockctrl, tmpstring,
+			if (rpcap_recv(sockctrl, ssl, tmpstring,
 			    findalldevs_if.desclen, &plen, errbuf) == -1)
 				goto error;
 
 			tmpstring[findalldevs_if.desclen] = 0;
 
-			pcap_snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
-				tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
-
-			stringlen = strlen(tmpstring2);
-
-			dev->description = (char *)malloc(stringlen + 1);
-
-			if (dev->description == NULL)
+			if (pcap_asprintf(&dev->description,
+			    "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+			    tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host) == -1)
 			{
 				pcap_fmt_errmsg_for_errno(errbuf,
 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
 				goto error;
 			}
-
-			/* Copy the new device description into the correct memory location */
-			strlcpy(dev->description, tmpstring2, stringlen + 1);
 		}
 
 		dev->flags = ntohl(findalldevs_if.flags);
@@ -2574,7 +2638,7 @@
 			struct rpcap_findalldevs_ifaddr ifaddr;
 
 			/* Retrieve the interface addresses */
-			if (rpcap_recv(sockctrl, (char *)&ifaddr,
+			if (rpcap_recv(sockctrl, ssl, (char *)&ifaddr,
 			    sizeof(struct rpcap_findalldevs_ifaddr),
 			    &plen, errbuf) == -1)
 				goto error;
@@ -2648,13 +2712,21 @@
 	}
 
 	/* Discard the rest of the message. */
-	if (rpcap_discard(sockctrl, plen, errbuf) == 1)
+	if (rpcap_discard(sockctrl, ssl, plen, errbuf) == 1)
 		goto error_nodiscard;
 
 	/* Control connection has to be closed only in case the remote machine is in passive mode */
 	if (!active)
 	{
 		/* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
 			return -1;
 	}
@@ -2678,12 +2750,22 @@
 	 *
 	 * Checks if all the data has been read; if not, discard the data in excess
 	 */
-	(void) rpcap_discard(sockctrl, plen, NULL);
+	(void) rpcap_discard(sockctrl, ssl, plen, NULL);
 
 error_nodiscard:
 	/* Control connection has to be closed only in case the remote machine is in passive mode */
 	if (!active)
+	{
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
+	}
 
 	/* To avoid inconsistencies in the number of sock_init() */
 	sock_cleanup();
@@ -2701,7 +2783,7 @@
  * to implement; we provide some APIs for it that work only with rpcap.
  */
 
-SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+SOCKET pcap_remoteact_accept_ex(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, int uses_ssl, char *errbuf)
 {
 	/* socket-related variables */
 	struct addrinfo hints;			/* temporary struct to keep settings needed to open the new socket */
@@ -2709,6 +2791,7 @@
 	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 */
+	SSL *ssl = NULL;				/* Optional SSL handler for sockctrl */
 	uint8 protocol_version;			/* negotiated protocol version */
 	struct activehosts *temp, *prev;	/* temp var needed to scan he host list chain */
 
@@ -2722,7 +2805,7 @@
 	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. */
+	/* For this reason, we have to initialize the Winsock support. */
 	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
 		return (SOCKET)-1;
 
@@ -2731,7 +2814,6 @@
 	{
 		if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
-			SOCK_DEBUG_MESSAGE(errbuf);
 			return (SOCKET)-2;
 		}
 	}
@@ -2739,7 +2821,6 @@
 	{
 		if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
-			SOCK_DEBUG_MESSAGE(errbuf);
 			return (SOCKET)-2;
 		}
 	}
@@ -2747,7 +2828,6 @@
 
 	if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
 	{
-		SOCK_DEBUG_MESSAGE(errbuf);
 		freeaddrinfo(addrinfo);
 		return (SOCKET)-2;
 	}
@@ -2765,15 +2845,40 @@
 
 	if (sockctrl == INVALID_SOCKET)
 	{
-		sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
+		sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
 		return (SOCKET)-2;
 	}
 
+	/* Promote to SSL early before any error message may be sent */
+	if (uses_ssl)
+	{
+#ifdef HAVE_OPENSSL
+		ssl = ssl_promotion(0, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+		if (! ssl)
+		{
+			sock_close(sockctrl, NULL, 0);
+			return (SOCKET)-1;
+		}
+#else
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "No TLS support");
+		sock_close(sockctrl, NULL, 0);
+		return (SOCKET)-1;
+#endif
+	}
+
 	/* Get the numeric for of the name of the connecting host */
 	if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
 	{
-		sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+		sock_geterror("getnameinfo()", errbuf, PCAP_ERRBUF_SIZE);
+		rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
 		return (SOCKET)-1;
 	}
@@ -2781,7 +2886,15 @@
 	/* checks if the connecting host is among the ones allowed */
 	if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
 	{
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+		rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
 		return (SOCKET)-1;
 	}
@@ -2789,10 +2902,18 @@
 	/*
 	 * Send authentication to the remote machine.
 	 */
-	if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+	if (rpcap_doauth(sockctrl, ssl, &protocol_version, auth, errbuf) == -1)
 	{
 		/* Unrecoverable error. */
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+		rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
 		return (SOCKET)-3;
 	}
@@ -2829,19 +2950,33 @@
 	{
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "malloc() failed");
-		rpcap_senderror(sockctrl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+		rpcap_senderror(sockctrl, ssl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+		if (ssl)
+		{
+			// Finish using the SSL handle for the socket.
+			// This must be done *before* the socket is closed.
+			ssl_finish(ssl);
+		}
+#endif
 		sock_close(sockctrl, NULL, 0);
 		return (SOCKET)-1;
 	}
 
 	memcpy(&temp->host, &from, fromlen);
 	temp->sockctrl = sockctrl;
+	temp->ssl = ssl;
 	temp->protocol_version = protocol_version;
 	temp->next = NULL;
 
 	return sockctrl;
 }
 
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+{
+	return pcap_remoteact_accept_ex(address, port, hostlist, connectinghost, auth, 0, errbuf);
+}
+
 int pcap_remoteact_close(const char *host, char *errbuf)
 {
 	struct activehosts *temp, *prev;	/* temp var needed to scan the host list chain */
@@ -2860,7 +2995,7 @@
 	retval = getaddrinfo(host, "0", &hints, &addrinfo);
 	if (retval != 0)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
 		return -1;
 	}
 
@@ -2882,7 +3017,7 @@
 				 * Don't check for errors, since we're
 				 * just cleaning up.
 				 */
-				if (sock_send(temp->sockctrl,
+				if (sock_send(temp->sockctrl, temp->ssl,
 				    (char *)&header,
 				    sizeof(struct rpcap_header), errbuf,
 				    PCAP_ERRBUF_SIZE) < 0)
@@ -2891,12 +3026,32 @@
 					 * Let that error be the one we
 					 * report.
 					 */
+#ifdef HAVE_OPENSSL
+					if (temp->ssl)
+					{
+						// Finish using the SSL handle
+						// for the socket.
+						// This must be done *before*
+						// the socket is closed.
+						ssl_finish(temp->ssl);
+					}
+#endif
 					(void)sock_close(temp->sockctrl, NULL,
 					   0);
 					status = -1;
 				}
 				else
 				{
+#ifdef HAVE_OPENSSL
+					if (temp->ssl)
+					{
+						// Finish using the SSL handle
+						// for the socket.
+						// This must be done *before*
+						// the socket is closed.
+						ssl_finish(temp->ssl);
+					}
+#endif
 					if (sock_close(temp->sockctrl, errbuf,
 					   PCAP_ERRBUF_SIZE) == -1)
 						status = -1;
@@ -2933,12 +3088,22 @@
 	/* 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");
+	snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
 	return -1;
 }
 
 void pcap_remoteact_cleanup(void)
 {
+#	ifdef HAVE_OPENSSL
+	if (ssl_main)
+	{
+		// Finish using the SSL handle for the main active socket.
+		// This must be done *before* the socket is closed.
+		ssl_finish(ssl_main);
+		ssl_main = NULL;
+	}
+#	endif
+
 	/* Very dirty, but it works */
 	if (sockmain)
 	{
@@ -2947,7 +3112,6 @@
 		/* To avoid inconsistencies in the number of sock_init() */
 		sock_cleanup();
 	}
-
 }
 
 int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
@@ -2971,7 +3135,7 @@
 			/*	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); */
+			/*	sock_geterror("getnameinfo()", errbuf, PCAP_ERRBUF_SIZE); */
 			return -1;
 		}
 
@@ -2979,12 +3143,12 @@
 
 		if ((size < 0) || (len >= (size_t)size))
 		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
+			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);
+		pcap_strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
 		hostlist[len - 1] = sep;
 		hostlist[len] = 0;
 
@@ -2997,11 +3161,11 @@
 /*
  * Receive the header of a message.
  */
-static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf)
+static int rpcap_recv_msg_header(SOCKET sock, SSL *ssl, struct rpcap_header *header, char *errbuf)
 {
 	int nrecv;
 
-	nrecv = sock_recv(sock, (char *) header, sizeof(struct rpcap_header),
+	nrecv = sock_recv(sock, ssl, (char *) header, sizeof(struct rpcap_header),
 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
 	    PCAP_ERRBUF_SIZE);
 	if (nrecv == -1)
@@ -3017,7 +3181,7 @@
  * Make sure the protocol version of a received message is what we were
  * expecting.
  */
-static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
+static int rpcap_check_msg_ver(SOCKET sock, SSL *ssl, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
 {
 	/*
 	 * Did the server specify the version we negotiated?
@@ -3027,7 +3191,7 @@
 		/*
 		 * Discard the rest of the message.
 		 */
-		if (rpcap_discard(sock, header->plen, errbuf) == -1)
+		if (rpcap_discard(sock, ssl, header->plen, errbuf) == -1)
 			return -1;
 
 		/*
@@ -3035,7 +3199,7 @@
 		 */
 		if (errbuf != NULL)
 		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "Server sent us a message with version %u when we were expecting %u",
 			    header->ver, expected_ver);
 		}
@@ -3048,7 +3212,7 @@
  * Check the message type of a received message, which should either be
  * the expected message type or RPCAP_MSG_ERROR.
  */
-static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
+static int rpcap_check_msg_type(SOCKET sock, SSL *ssl, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
 {
 	const char *request_type_string;
 	const char *msg_type_string;
@@ -3063,7 +3227,7 @@
 		 * Hand that error back to our caller.
 		 */
 		*errcode = ntohs(header->value);
-		rpcap_msg_err(sock, header->plen, errbuf);
+		rpcap_msg_err(sock, ssl, header->plen, errbuf);
 		return -1;
 	}
 
@@ -3082,7 +3246,7 @@
 		/*
 		 * Discard the rest of the message.
 		 */
-		if (rpcap_discard(sock, header->plen, errbuf) == -1)
+		if (rpcap_discard(sock, ssl, header->plen, errbuf) == -1)
 			return -1;
 
 		/*
@@ -3095,17 +3259,17 @@
 			if (request_type_string == NULL)
 			{
 				/* This should not happen. */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "rpcap_check_msg_type called for request message with type %u",
 				    request_type);
 				return -1;
 			}
 			if (msg_type_string != NULL)
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "%s message received in response to a %s message",
 				    msg_type_string, request_type_string);
 			else
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Message of unknown type %u message received in response to a %s request",
 				    header->type, request_type_string);
 		}
@@ -3118,11 +3282,11 @@
 /*
  * Receive and process the header of a message.
  */
-static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
+static int rpcap_process_msg_header(SOCKET sock, SSL *ssl, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
 {
 	uint16 errcode;
 
-	if (rpcap_recv_msg_header(sock, header, errbuf) == -1)
+	if (rpcap_recv_msg_header(sock, ssl, header, errbuf) == -1)
 	{
 		/* Network error. */
 		return -1;
@@ -3131,13 +3295,13 @@
 	/*
 	 * Did the server specify the version we negotiated?
 	 */
-	if (rpcap_check_msg_ver(sock, expected_ver, header, errbuf) == -1)
+	if (rpcap_check_msg_ver(sock, ssl, expected_ver, header, errbuf) == -1)
 		return -1;
 
 	/*
 	 * Check the message type.
 	 */
-	return rpcap_check_msg_type(sock, request_type, header,
+	return rpcap_check_msg_type(sock, ssl, request_type, header,
 	    &errcode, errbuf);
 }
 
@@ -3150,17 +3314,17 @@
  * Returns 0 on success, logs a message and returns -1 on a network
  * error.
  */
-static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf)
+static int rpcap_recv(SOCKET sock, SSL *ssl, void *buffer, size_t toread, uint32 *plen, char *errbuf)
 {
 	int nread;
 
 	if (toread > *plen)
 	{
 		/* The server sent us a bad message */
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
 		return -1;
 	}
-	nread = sock_recv(sock, buffer, toread,
+	nread = sock_recv(sock, ssl, buffer, toread,
 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
 	if (nread == -1)
 	{
@@ -3173,7 +3337,7 @@
 /*
  * This handles the RPCAP_MSG_ERROR message.
  */
-static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
+static void rpcap_msg_err(SOCKET sockctrl, SSL *ssl, uint32 plen, char *remote_errbuf)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];
 
@@ -3183,12 +3347,12 @@
 		 * Message is too long; just read as much of it as we
 		 * can into the buffer provided, and discard the rest.
 		 */
-		if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+		if (sock_recv(sockctrl, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
 			// Network error.
-			pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+			snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
 			return;
 		}
 
@@ -3197,10 +3361,19 @@
 		 */
 		remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
 
+#ifdef _WIN32
+		/*
+		 * If we're not in UTF-8 mode, convert it to the local
+		 * code page.
+		 */
+		if (!pcap_utf_8_mode)
+			utf_8_to_acp_truncated(remote_errbuf);
+#endif
+
 		/*
 		 * Throw away the rest.
 		 */
-		(void)rpcap_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
+		(void)rpcap_discard(sockctrl, ssl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
 	}
 	else if (plen == 0)
 	{
@@ -3209,12 +3382,12 @@
 	}
 	else
 	{
-		if (sock_recv(sockctrl, remote_errbuf, plen,
+		if (sock_recv(sockctrl, ssl, remote_errbuf, plen,
 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
 			// Network error.
-			pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+			snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
 			return;
 		}
 
@@ -3231,11 +3404,11 @@
  * Returns 0 on success, logs a message and returns -1 on a network
  * error.
  */
-static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf)
+static int rpcap_discard(SOCKET sock, SSL *ssl, uint32 len, char *errbuf)
 {
 	if (len != 0)
 	{
-		if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
 			// Network error.
 			return -1;
@@ -3248,7 +3421,7 @@
  * Read bytes into the pcap_t's buffer until we have the specified
  * number of bytes read or we get an error or interrupt indication.
  */
-static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size)
+static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t size)
 {
 	u_char *bp;
 	int cc;
@@ -3267,9 +3440,10 @@
 		 * We haven't read all of the packet header yet.
 		 * Read what remains, which could be all of it.
 		 */
-		bytes_read = sock_recv(sock, bp, size - cc,
+		bytes_read = sock_recv(rp->rmt_sockdata, rp->data_ssl, bp, size - cc,
 		    SOCK_RECEIVEALL_NO|SOCK_EOF_IS_ERROR, p->errbuf,
 		    PCAP_ERRBUF_SIZE);
+
 		if (bytes_read == -1)
 		{
 			/*
@@ -3298,7 +3472,7 @@
 			 * Update the read pointer and byte count, and
 			 * return an error indication.
 			 */
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "The server terminated the connection.");
 			return -1;
 		}
diff --git a/pcap-rpcap.h b/pcap-rpcap.h
index be31c40..6ad6d98 100644
--- a/pcap-rpcap.h
+++ b/pcap-rpcap.h
@@ -43,7 +43,7 @@
 /*
  * Internal interfaces for "pcap_findalldevs_ex()".
  */
-int	pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth,
-   pcap_if_t **alldevs, char *errbuf);
+int	pcap_findalldevs_ex_remote(const char *source,
+    struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
 
 #endif
diff --git a/pcap-savefile.manfile b/pcap-savefile.manfile
deleted file mode 100644
index f07d849..0000000
--- a/pcap-savefile.manfile
+++ /dev/null
@@ -1,133 +0,0 @@
-.\" 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 451dd90..a7ae9af 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@ "8 March 2015"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "24 April 2020"
 .SH NAME
 pcap-savefile \- libpcap savefile format
 .SH DESCRIPTION
@@ -51,6 +51,8 @@
 .TE
 .RE
 .PP
+The per-file header length is 24 octets.
+.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
@@ -117,6 +119,8 @@
 .TE
 .RE
 .PP
+The per-packet header length is 16 octets.
+.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
@@ -130,4 +134,4 @@
 will be equal if the number of bytes of packet data are less than or
 equal to the snapshot length.
 .SH SEE ALSO
-pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
+.BR pcap (3PCAP)
diff --git a/pcap-septel.c b/pcap-septel.c
index 0471153..e917edd 100644
--- a/pcap-septel.c
+++ b/pcap-septel.c
@@ -1,15 +1,6 @@
 /*
  * pcap-septel.c: Packet capture interface for Intel/Septel card.
  *
- * The functionality of this code attempts to mimic that of pcap-linux as much
- * as possible.  This code is compiled in several different ways depending on
- * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined.  If HAVE_SEPTEL_API is
- * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is
- * defined then the 'septel_' function calls are renamed to 'pcap_'
- * equivalents.  If SEPTEL_ONLY is not defined then nothing is altered - the
- * septel_ functions will be called as required from their
- * pcap-linux/equivalents.
- *
  * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
  * (+961 3 485243)
  */
@@ -26,7 +17,6 @@
 
 #include "pcap-int.h"
 
-#include <ctype.h>
 #include <netinet/in.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
@@ -41,7 +31,6 @@
 
 #include "pcap-septel.h"
 
-static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
 static int septel_stats(pcap_t *p, struct pcap_stat *ps);
 static int septel_getnonblock(pcap_t *p);
 static int septel_setnonblock(pcap_t *p, int nonblock);
@@ -56,7 +45,7 @@
 /*
  *  Read at most max_packets from the capture queue and call the callback
  *  for each of them. Returns the number of packets handled, -1 if an
- *  error occured, or -2 if we were told to break out of the loop.
+ *  error occurred, or -2 if we were told to break out of the loop.
  */
 static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
 
@@ -135,7 +124,7 @@
         caplen = packet_len;
       }
       /* Run the packet filter if there is one. */
-      if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+      if ((p->fcode.bf_insns == NULL) || pcap_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
 
 
         /*  get a time stamp , consisting of :
@@ -180,9 +169,9 @@
 
 
 static int
-septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
+septel_inject(pcap_t *handle, const void *buf _U_, int size _U_)
 {
-  strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
+  pcap_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
           PCAP_ERRBUF_SIZE);
   return (-1);
 }
@@ -218,7 +207,7 @@
 
   handle->read_op = septel_read;
   handle->inject_op = septel_inject;
-  handle->setfilter_op = septel_setfilter;
+  handle->setfilter_op = install_bpf_program;
   handle->set_datalink_op = NULL; /* can't change data link type */
   handle->getnonblock_op = septel_getnonblock;
   handle->setnonblock_op = septel_setnonblock;
@@ -244,7 +233,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_septel));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_septel);
 	if (p == NULL)
 		return NULL;
 
@@ -285,28 +274,6 @@
 
 
 /*
- * Installs the given bpf filter program in the given pcap structure.  There is
- * no attempt to store the filter in kernel memory as that is not supported
- * with Septel cards.
- */
-static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
-  if (!p)
-    return -1;
-  if (!fp) {
-    strncpy(p->errbuf, "setfilter: No filter specified",
-	    sizeof(p->errbuf));
-    return -1;
-  }
-
-  /* Make our private copy of the filter */
-
-  if (install_bpf_program(p, fp) < 0)
-    return -1;
-
-  return (0);
-}
-
-/*
  * We don't support non-blocking mode.  I'm not sure what we'd
  * do to support it and, given that we don't support select()/
  * poll()/epoll_wait()/kevent() etc., it probably doesn't
@@ -347,7 +314,7 @@
 pcap_t *
 pcap_create_interface(const char *device, char *errbuf)
 {
-  pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+  snprintf(errbuf, PCAP_ERRBUF_SIZE,
                 "This version of libpcap only supports Septel cards");
   return (NULL);
 }
diff --git a/pcap-sita.c b/pcap-sita.c
index 7c42791..c53f323 100644
--- a/pcap-sita.c
+++ b/pcap-sita.c
@@ -72,6 +72,14 @@
 	int			len;		/* the current size of the inbound message */
 } unit_t;
 
+/*
+ * Private data.
+ * Currently contains nothing.
+ */
+struct pcap_sita {
+	int	dummy;
+};
+
 static unit_t		units[MAX_CHASSIS+1][MAX_GEOSLOT+1];	/* we use indexes of 1 through 8, but we reserve/waste index 0 */
 static fd_set		readfds;				/* a place to store the file descriptors for the connections to the IOPs */
 static int		max_fs;
@@ -266,7 +274,7 @@
 
 	empty_unit_table();
 	if ((fp = fopen("/etc/hosts", "r")) == NULL) {										/* try to open the hosts file and if it fails */
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading.");	/* return the nohostsfile error response */
+		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 */
@@ -289,15 +297,15 @@
 		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... */
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'.");	/* warn the user */
+			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) {
+		ptr2 = strdup(ptr);					/* copy the IP address into our malloc'ed memory */
+		if (ptr2 == NULL) {
 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "malloc");
 			continue;
 		}
-		strcpy(ptr2, ptr);								/* copy the IP address into our malloc'ed memory */
 		u = &units[chassis][geoslot];
 		u->ip = ptr2;									/* and remember the whole shebang */
 		u->chassis = chassis;
@@ -407,19 +415,18 @@
 
 static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
 
-	pcap_snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
+	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;
-	pcap_snprintf(buf, bufsize, "%s_%d", proto, portnum);
+	snprintf(buf, bufsize, "%s_%d", proto, portnum);
 }
 
 static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
 	iface_t		*iface_ptr, *iface;
-	char		*name;
 	char		buf[32];
 	char		*proto;
 	char		*port;
@@ -434,15 +441,12 @@
 
 	iface->iftype = iftype;					/* remember the interface type of this interface */
 
-	name = malloc(strlen(IOPname) + 1);		/* get memory for the IOP's name */
-        if (name == NULL) {    /* oops, we didn't get the memory requested     */
+	iface->IOPname = strdup(IOPnam);			/* copy it and stick it into the structure */
+        if (iface->IOPname == NULL) {    /* oops, we didn't get the memory requested     */
                 fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno);
                 return NULL;
         }
 
-	strcpy(name, IOPname);					/* and copy it in */
-	iface->IOPname = name;					/* and stick it into the structure */
-
 	if (strncmp(IOPname, "lo", 2) == 0) {
 		IOPportnum = atoi(&IOPname[2]);
 		switch (iftype) {
@@ -478,15 +482,12 @@
 		return NULL;
 	}
 
-	name = malloc(strlen(buf) + 1);			/* get memory for that name */
-        if (name == NULL) {    /* oops, we didn't get the memory requested     */
+	iface->name = strdup(buf);					/* make a copy and stick it into the structure */
+        if (iface->name == NULL) {    /* oops, we didn't get the memory requested     */
                 fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno);
                 return NULL;
         }
 
-	strcpy(name, buf);						/* and copy it in */
-	iface->name = name;						/* and stick it into the structure */
-
 	if (u->iface == 0) {					/* if this is the first name */
 		u->iface = iface;					/* stick this entry at the head of the list */
 	} else {
@@ -703,7 +704,7 @@
 				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 */
-				bigger_buffer = realloc(iff->name, strlen(newname) + 1));
+				bigger_buffer = realloc(iff->name, strlen(newname) + 1);
 				if (bigger_buffer == NULL) {	/* we now re-write the name stored in the interface list */
 					pcap_fmt_errmsg_for_errno(errbuf,
 					    PCAP_ERRBUF_SIZE, errno, "realloc");
@@ -754,9 +755,9 @@
 
 		memcpy(&working_set, &readfds, sizeof(readfds));				/* otherwise, we still have to listen for more stuff, till we timeout */
 		retval = select(max_fs + 1, &working_set, NULL, NULL, &tv);
-		if (retval == -1) {												/* an error occured !!!!! */
+		if (retval == -1) {												/* an error occurred !!!!! */
 			return;
-		} else if (retval == 0) {										/* timeout occured, so process what we've got sofar and return */
+		} else if (retval == 0) {										/* timeout occurred, so process what we've got sofar and return */
 			printf("timeout\n");
 			return;
 		} else {
@@ -883,8 +884,8 @@
 	//printf("acn_start_monitor() complete\n");				// fulko
 }
 
-static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) {
-	strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
+static int pcap_inject_acn(pcap_t *p, const void *buf _U_, int size _U_) {
+	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
 	    PCAP_ERRBUF_SIZE);
 	return (-1);
 }
@@ -915,12 +916,6 @@
 	return 0;
 }
 
-static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
-	pcap_snprintf(handle->errbuf, sizeof(handle->errbuf),
-	    "Setting direction is not supported on ACN adapters");
-	return -1;
-}
-
 static int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) {
 	struct		timeval tv;
 	int			retval, fd;
@@ -940,10 +935,10 @@
 	bp = handle->bp;
 	while (count) {
 		retval = select(fd + 1, &w_fds, NULL, NULL, &tv);
-		if (retval == -1) {											/* an error occured !!!!! */
+		if (retval == -1) {											/* an error occurred !!!!! */
 //			fprintf(stderr, "error during packet data read\n");
-			return -1;												/* but we need to return a good indication to prevent unneccessary popups */
-		} else if (retval == 0) {									/* timeout occured, so process what we've got sofar and return */
+			return -1;										/* but we need to return a good indication to prevent unnecessary popups */
+		} else if (retval == 0) {									/* timeout occurred, so process what we've got sofar and return */
 //			fprintf(stderr, "timeout during packet data read\n");
 			return -1;
 		} else {
@@ -997,7 +992,7 @@
 
 	handle->inject_op = pcap_inject_acn;
 	handle->setfilter_op = pcap_setfilter_acn;
-	handle->setdirection_op = pcap_setdirection_acn;
+	handle->setdirection_op = NULL; /* Not implemented */
 	handle->set_datalink_op = NULL;	/* can't change data link type */
 	handle->getnonblock_op = pcap_getnonblock_fd;
 	handle->setnonblock_op = pcap_setnonblock_fd;
@@ -1046,7 +1041,7 @@
 pcap_t *pcap_create_interface(const char *device _U_, char *ebuf) {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, 0);
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_sita);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-sita.html b/pcap-sita.html
index 97408d8..33f1e10 100644
--- a/pcap-sita.html
+++ b/pcap-sita.html
@@ -22,7 +22,7 @@
 <UL>
 	<STRONG>Note:</STRONG> This document is part of the libpcap Git and was derived from 'pcap.3' (circa Aug/07).
 	<P>
-	The ACN provides a customized/distributed version of this library that alows SMPs to
+	The ACN provides a customized/distributed version of this library that allows SMPs to
 	interact with the various IOPs within the site providing a standard mechanism
 	to capture LAN and WAN message traffic.
 	<P>
@@ -31,7 +31,7 @@
 			<TR>
 				<TH VALIGN=TOP>SMP</TH>
 				<TD VALIGN=TOP>The Supervisory Management Processor where Wireshark (or equivalent)
-								runs in conjuction with a libpcap front-end.</TD>
+								runs in conjunction with a libpcap front-end.</TD>
 			</TR>
 			<TR>
 				<TH VALIGN=TOP>IOP</TH>
@@ -43,7 +43,7 @@
 	<P>
 	Each IOP will be capable of supporting multiple connections from an SMP
 	enabling monitoring of more than one interface at a time, each through
-	its own seperate connection.  The IOP is responsible to ensure and report
+	its own separate connection.  The IOP is responsible to ensure and report
 	an error if any attempt is made to monitor the same interface more than once.
 	<P>
 	There are three applications that will be supported by the ACN version of libpcap.
@@ -121,8 +121,8 @@
 		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
 			<TD>
 			After any required processing is complete, the IOP will return a
-			null terminated string containing an error message if one occured.
-			If no error occured, a empty string is still returned.
+			null terminated string containing an error message if one occurred.
+			If no error occurred, a empty string is still returned.
 			Errors are:
 			<UL>
 			<LI>"Interface (xxx) does not exist."
@@ -298,7 +298,7 @@
 			<TD>
 			The SMP reads only the next packet from the reverse channel of the connection
 			between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
-			with a count of 1) and returns seperate pointers to both the
+			with a count of 1) and returns separate pointers to both the
 			packet header and packet data by invoking an internal callback.
 			</TD>
 		</TR>
@@ -322,7 +322,7 @@
 		<TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
 			<TD>
 			The IOP returns a null terminated error string if it failed to accept the filter.
-			If no error occured, then a NULL terminated empty string is returned instead.
+			If no error occurred, then a NULL terminated empty string is returned instead.
 			Errors are:
 			<UL>
 			<LI>"Invalid BPF."
@@ -362,7 +362,7 @@
 		<TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
 			<TD>
 			The SMP closes the file descriptor, and if the descriptor is that of
-			the comminucation session with an IOP, it too is terminated.
+			the communication session with an IOP, it too is terminated.
 			</TD>
 		</TR>
 		<TR><TH VALIGN=TOP NOWRAP>IOP</TH>
@@ -370,7 +370,7 @@
 			If the IOP detects that its communication session with an SMP
 			has closed, it will terminate any monitoring in progress,
 			release any resources and close its end of the session.
-			It will not maintain persistance of any information or prior mode of operation.
+			It will not maintain persistence of any information or prior mode of operation.
 			</TD>
 		</TR>
 	</TABLE></TD></TR>
@@ -411,7 +411,7 @@
 					<TR>
 						<TD VALIGN=TOP>Interface ID</TD>
 						<TD VALIGN=TOP ALIGN=CENTER>1</TD>
-						<TD VALIGN=TOP>A NULL to indicate an an empty 'interface ID'.</TD>
+						<TD VALIGN=TOP>A NULL to indicate an empty 'interface ID'.</TD>
 					</TR>
 				</TABLE>
 			</TD>
@@ -442,7 +442,7 @@
 			<TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
 			<TD VALIGN=TOP>The IOP returns a list of sequences of information as
 				defined by the return parameter of this function call (as shown in the following table).
-				Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
+				Elements are specified by providing an unsigned byte preceding the actual data that contains length information.
 				<P>
 				<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
 				<TR>
@@ -635,7 +635,7 @@
 						<TD VALIGN=TOP>BPF program</TD>
 						<TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
 						<TD VALIGN=TOP>8 bytes of each command (repeated 'n' times).<BR>
-								 	Each command consists of that C-style structure which contains:
+									Each command consists of that C-style structure which contains:
 							<P>
 							<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
 								<TR>
@@ -719,7 +719,7 @@
 					<TR>
 						<TD VALIGN=TOP>ps_ifdrop</TD>
 						<TD VALIGN=TOP ALIGN=CENTER>4</TD>
-						<TD VALIGN=TOP>The number of packets dropped by the network inteface
+						<TD VALIGN=TOP>The number of packets dropped by the network interface
 							(regardless of whether they would have passed the input filter).</TD>
 					</TR>
 				</TABLE>
@@ -839,7 +839,7 @@
 	<UL>
 	PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support
 	monitoring of its ports, however each of these facilities were focused on capturing
-	and displaying traffic from LAN interfaces.  The SITA extentions to these facilities
+	and displaying traffic from LAN interfaces.  The SITA extensions to these facilities
 	are used to also provide the ability to capture, filter, and display information from
 	an ACN's WAN ports.
 	<P>
@@ -849,7 +849,7 @@
 	<P>
 	<UL TYPE=DISC>
 		<LI>For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format.
-		<LI>For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data
+		<LI>For WAN devices, the packet contains a 5 byte header that precedes the actual captured data
 			described by the following table:
 	</UL>
 	<P>
diff --git a/pcap-snf.c b/pcap-snf.c
index 4eae0b3..a9162eb 100644
--- a/pcap-snf.c
+++ b/pcap-snf.c
@@ -10,7 +10,6 @@
 #include <string.h>
 #include <errno.h>
 
-#include <ctype.h>
 #ifndef _WIN32
 #include <netinet/in.h>
 #include <sys/mman.h>
@@ -177,13 +176,13 @@
 			caplen = p->snapshot;
 
 		if ((p->fcode.bf_insns == NULL) ||
-		     bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
+		     pcap_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
 			hdr.ts = snf_timestamp_to_timeval(req.timestamp, p->opt.tstamp_precision);
 			hdr.caplen = caplen;
 			hdr.len = req.length;
 			callback(user, &hdr, req.pkt_addr);
+			n++;
 		}
-		n++;
 
 		/* After one successful packet is received, we won't block
 		* again for that timeout. */
@@ -194,26 +193,7 @@
 }
 
 static int
-snf_setfilter(pcap_t *p, struct bpf_program *fp)
-{
-	if (!p)
-		return -1;
-	if (!fp) {
-		strncpy(p->errbuf, "setfilter: No filter specified",
-			sizeof(p->errbuf));
-		return -1;
-	}
-
-	/* Make our private copy of the filter */
-
-	if (install_bpf_program(p, fp) < 0)
-		return -1;
-
-	return (0);
-}
-
-static int
-snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+snf_inject(pcap_t *p, const void *buf _U_, int size _U_)
 {
 #ifdef SNF_HAVE_INJECT_API
 	struct pcap_snf *ps = p->priv;
@@ -237,7 +217,7 @@
 		return (-1);
 	}
 #else
-	strlcpy(p->errbuf, "Sending packets isn't supported with this snf version",
+	pcap_strlcpy(p->errbuf, "Sending packets isn't supported with this snf version",
 	    PCAP_ERRBUF_SIZE);
 	return (-1);
 #endif
@@ -253,7 +233,7 @@
 	int flags = -1, ring_id = -1;
 
 	if (device == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
 		return -1;
 	}
 
@@ -327,7 +307,7 @@
 	p->linktype = DLT_EN10MB;
 	p->read_op = snf_read;
 	p->inject_op = snf_inject;
-	p->setfilter_op = snf_setfilter;
+	p->setfilter_op = install_bpf_program;
 	p->setdirection_op = NULL; /* Not implemented.*/
 	p->set_datalink_op = snf_set_datalink;
 	p->getnonblock_op = snf_getnonblock;
@@ -355,7 +335,7 @@
 	const char *nr = NULL;
 
 	if (snf_init(SNF_VERSION_API)) {
-		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "snf_getifaddrs: snf_init failed");
 		return (-1);
 	}
@@ -370,7 +350,7 @@
 		errno = 0;
 		merge = strtol(nr, NULL, 0);
 		if (errno) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				"snf_getifaddrs: SNF_FLAGS is not a valid number");
 			return (-1);
 		}
@@ -408,7 +388,7 @@
 		 * entry for the device, if they're not already in the
 		 * list of IP addresses for the device?
  		 */
-		(void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom %ssnf%d",
+		(void)snprintf(desc,MAX_DESC_LENGTH,"Myricom %ssnf%d",
 			merge ? "Merge Bitmask Port " : "",
 			merge ? 1 << ifa->snf_ifa_portnum : ifa->snf_ifa_portnum);
 		/*
@@ -484,8 +464,8 @@
 		/*
 		 * Add a new entry with all ports bitmask
 		 */
-		(void)pcap_snprintf(name,MAX_DESC_LENGTH,"snf%d",allports);
-		(void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom Merge Bitmask All Ports snf%d",
+		(void)snprintf(name,MAX_DESC_LENGTH,"snf%d",allports);
+		(void)snprintf(desc,MAX_DESC_LENGTH,"Myricom Merge Bitmask All Ports snf%d",
 			allports);
 		/*
 		 * XXX - is there any notion of "up" and "running" that
@@ -560,7 +540,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_snf));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_snf);
 	if (p == NULL)
 		return NULL;
 	ps = p->priv;
@@ -568,7 +548,6 @@
 	/*
 	 * We support microsecond and nanosecond time stamps.
 	 */
-	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
@@ -578,6 +557,7 @@
 	}
 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
 	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+	p->tstamp_precision_count = 2;
 
 	p->activate_op = snf_activate;
 	ps->snf_boardnum = boardnum;
@@ -605,7 +585,7 @@
 pcap_t *
 pcap_create_interface(const char *device, char *errbuf)
 {
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(errbuf, PCAP_ERRBUF_SIZE,
 	    "This version of libpcap only supports SNF cards");
 	return NULL;
 }
diff --git a/pcap-snit.c b/pcap-snit.c
index 9c6fbd4..ca6222c 100644
--- a/pcap-snit.c
+++ b/pcap-snit.c
@@ -53,7 +53,6 @@
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
@@ -190,7 +189,7 @@
 		if (caplen > p->snapshot)
 			caplen = p->snapshot;
 
-		if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) {
+		if (pcap_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) {
 			struct pcap_pkthdr h;
 			h.ts = ntp->nh_timestamp;
 			h.len = nlp->nh_pktlen;
@@ -208,7 +207,7 @@
 }
 
 static int
-pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
+pcap_inject_snit(pcap_t *p, const void *buf, int size)
 {
 	struct strbuf ctl, data;
 
@@ -460,7 +459,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_snit);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-snoop.c b/pcap-snoop.c
index a598bae..2f44b1d 100644
--- a/pcap-snoop.c
+++ b/pcap-snoop.c
@@ -126,7 +126,7 @@
 	}
 
 	if (p->fcode.bf_insns == NULL ||
-	    bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
+	    pcap_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
 		struct pcap_pkthdr h;
 		++psn->stat.ps_recv;
 		h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
@@ -140,7 +140,7 @@
 }
 
 static int
-pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
+pcap_inject_snoop(pcap_t *p, const void *buf, int size)
 {
 	int ret;
 
@@ -310,7 +310,7 @@
 		p->linktype = DLT_NULL;
 		ll_hdrlen = 4;
 	} else {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "snoop: unknown physical layer type");
 		goto bad;
 	}
@@ -421,7 +421,7 @@
 {
 	pcap_t *p;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_snoop));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_snoop);
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-tc.c b/pcap-tc.c
index 38c7024..9902633 100644
--- a/pcap-tc.c
+++ b/pcap-tc.c
@@ -123,10 +123,9 @@
 static int TcGetNonBlock(pcap_t *p);
 static int TcSetNonBlock(pcap_t *p, int nonblock);
 static void TcCleanup(pcap_t *p);
-static int TcInject(pcap_t *p, const void *buf, size_t size);
+static int TcInject(pcap_t *p, const void *buf, int size);
 static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
 static int TcStats(pcap_t *p, struct pcap_stat *ps);
-static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
 #ifdef _WIN32
 static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
 static int TcSetBuff(pcap_t *p, int dim);
@@ -253,58 +252,6 @@
 #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
@@ -341,34 +288,34 @@
 
 		currentStatus = TC_API_CANNOT_LOAD;
 
-		g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
+		g_TcFunctions.hTcApiDllHandle = pcap_load_code("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.QueryPortList			= (TcFcnQueryPortList)			pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
+		g_TcFunctions.FreePortList			= (TcFcnFreePortList)			pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
 
-		g_TcFunctions.StatusGetString				= (TcFcnStatusGetString)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
+		g_TcFunctions.StatusGetString			= (TcFcnStatusGetString)		pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
 
-		g_TcFunctions.PortGetName					= (TcFcnPortGetName)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
-		g_TcFunctions.PortGetDescription			= (TcFcnPortGetDescription)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
+		g_TcFunctions.PortGetName			= (TcFcnPortGetName)			pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
+		g_TcFunctions.PortGetDescription		= (TcFcnPortGetDescription)		pcap_find_function(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.InstanceOpenByName		= (TcFcnInstanceOpenByName)		pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
+		g_TcFunctions.InstanceClose			= (TcFcnInstanceClose)			pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
+		g_TcFunctions.InstanceSetFeature		= (TcFcnInstanceSetFeature)		pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
+		g_TcFunctions.InstanceQueryFeature		= (TcFcnInstanceQueryFeature)	pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
+		g_TcFunctions.InstanceReceivePackets		= (TcFcnInstanceReceivePackets)	pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
+		g_TcFunctions.InstanceGetReceiveWaitHandle	= (TcFcnInstanceGetReceiveWaitHandle)pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
+		g_TcFunctions.InstanceTransmitPackets		= (TcFcnInstanceTransmitPackets)pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
+		g_TcFunctions.InstanceQueryStatistics		= (TcFcnInstanceQueryStatistics)pcap_find_function(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.PacketsBufferCreate		= (TcFcnPacketsBufferCreate)	pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
+		g_TcFunctions.PacketsBufferDestroy		= (TcFcnPacketsBufferDestroy)	pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
+		g_TcFunctions.PacketsBufferQueryNextPacket	= (TcFcnPacketsBufferQueryNextPacket)pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
+		g_TcFunctions.PacketsBufferCommitNextPacket	= (TcFcnPacketsBufferCommitNextPacket)pcap_find_function(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");
+		g_TcFunctions.StatisticsDestroy			= (TcFcnStatisticsDestroy)		pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
+		g_TcFunctions.StatisticsUpdate			= (TcFcnStatisticsUpdate)		pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
+		g_TcFunctions.StatisticsQueryValue		= (TcFcnStatisticsQueryValue)	pcap_find_function(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
 
 		if (   g_TcFunctions.QueryPortList == NULL
 			|| g_TcFunctions.FreePortList == NULL
@@ -440,7 +387,7 @@
 	PTC_PORT pPorts = NULL;
 	TC_STATUS status;
 	int result = 0;
-	pcap_if_t *dev, *cursor;
+	pcap_if_t *dev;
 	ULONG i;
 
 	do
@@ -472,22 +419,7 @@
 			dev = TcCreatePcapIfFromPort(pPorts[i]);
 
 			if (dev != NULL)
-			{
-				/*
-				 * append it at the end
-				 */
-				if (devlistp->beginning == NULL)
-				{
-					devlistp->beginning = dev;
-				}
-				else
-				{
-					for (cursor = devlistp->beginning;
-					    cursor->next != NULL;
-					    cursor = cursor->next);
-					cursor->next = dev;
-				}
-			}
+				add_dev(devlist, dev->name, dev->flags, dev->description, errbuf);
 		}
 
 		if (numPorts > 0)
@@ -567,7 +499,7 @@
 
 	if (pt->PpiPacket == NULL)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
 		return PCAP_ERROR;
 	}
 
@@ -602,7 +534,7 @@
 	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));
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
 		return PCAP_ERROR;
 	}
 
@@ -634,7 +566,7 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
 		goto bad;
 	}
 
@@ -673,12 +605,12 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+		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->setfilter_op = install_bpf_program;
 	p->setdirection_op = NULL;	/* Not implemented. */
 	p->set_datalink_op = TcSetDatalink;
 	p->getnonblock_op = TcGetNonBlock;
@@ -771,7 +703,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_tc);
 	if (p == NULL)
 		return NULL;
 
@@ -806,14 +738,14 @@
 
 static int TcGetNonBlock(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for TurboCap ports");
 	return -1;
 }
 
 static int TcSetNonBlock(pcap_t *p, int nonblock)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Non-blocking mode isn't supported for TurboCap ports");
 	return -1;
 }
@@ -846,7 +778,7 @@
 }
 
 /* Send a packet to the network */
-static int TcInject(pcap_t *p, const void *buf, size_t size)
+static int TcInject(pcap_t *p, const void *buf, int size)
 {
 	struct pcap_tc *pt = p->priv;
 	TC_STATUS status;
@@ -855,7 +787,7 @@
 
 	if (size >= 0xFFFF)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
 		return -1;
 	}
 
@@ -863,7 +795,7 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return -1;
 	}
 
@@ -883,12 +815,12 @@
 
 		if (status != TC_SUCCESS)
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+			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);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 	}
 
 	g_TcFunctions.PacketsBufferDestroy(buffer);
@@ -928,7 +860,7 @@
 		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);
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 			return -1;
 		}
 	}
@@ -978,14 +910,14 @@
 
 		if (status != TC_SUCCESS)
 		{
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+			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);
+			filterResult = pcap_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
 
 			if (filterResult == 0)
 			{
@@ -1068,7 +1000,7 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return -1;
 	}
 
@@ -1077,7 +1009,7 @@
 	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);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return -1;
 	}
 	if (counter <= (ULONGLONG)0xFFFFFFFF)
@@ -1092,7 +1024,7 @@
 	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);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return -1;
 	}
 	if (counter <= (ULONGLONG)0xFFFFFFFF)
@@ -1115,27 +1047,6 @@
 }
 
 
-/*
- * We filter at user level, since the kernel driver does't process the packets
- */
-static int
-TcSetFilter(pcap_t *p, struct bpf_program *fp)
-{
-	if(!fp)
-	{
-		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
-		return -1;
-	}
-
-	/* Install a user level filter */
-	if (install_bpf_program(p, fp) < 0)
-	{
-		return -1;
-	}
-
-	return 0;
-}
-
 #ifdef _WIN32
 static struct pcap_stat *
 TcStatsEx(pcap_t *p, int *pcap_stat_size)
@@ -1151,7 +1062,7 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return NULL;
 	}
 
@@ -1160,7 +1071,7 @@
 	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);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return NULL;
 	}
 	if (counter <= (ULONGLONG)0xFFFFFFFF)
@@ -1175,7 +1086,7 @@
 	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);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 		return NULL;
 	}
 	if (counter <= (ULONGLONG)0xFFFFFFFF)
@@ -1213,7 +1124,7 @@
 {
 	if (mode != MODE_CAPT)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
 		return -1;
 	}
 
@@ -1228,7 +1139,7 @@
 
 	if (size < 0)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
 		return -1;
 	}
 
@@ -1236,7 +1147,7 @@
 
 	if (status != TC_SUCCESS)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
 	}
 
 	return 0;
@@ -1253,7 +1164,7 @@
 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,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "An OID get request cannot be performed on a TurboCap device");
 	return PCAP_ERROR;
 }
@@ -1262,7 +1173,7 @@
 TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
     size_t *lenp _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "An OID set request cannot be performed on a TurboCap device");
 	return PCAP_ERROR;
 }
@@ -1270,7 +1181,7 @@
 static u_int
 TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Packets cannot be bulk transmitted on a TurboCap device");
 	return 0;
 }
@@ -1278,7 +1189,7 @@
 static int
 TcSetUserBuffer(pcap_t *p, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The user buffer cannot be set on a TurboCap device");
 	return -1;
 }
@@ -1286,7 +1197,7 @@
 static int
 TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Live packet dumping cannot be performed on a TurboCap device");
 	return -1;
 }
@@ -1294,7 +1205,7 @@
 static int
 TcLiveDumpEnded(pcap_t *p, int sync _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Live packet dumping cannot be performed on a TurboCap device");
 	return -1;
 }
diff --git a/pcap-tstamp.manmisc b/pcap-tstamp.manmisc
deleted file mode 100644
index c8b7fed..0000000
--- a/pcap-tstamp.manmisc
+++ /dev/null
@@ -1,177 +0,0 @@
-.\"
-.\" 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
-.na
-pcap_set_tstamp_type(3PCAP),
-pcap_list_tstamp_types(3PCAP),
-pcap_tstamp_type_val_to_name(3PCAP),
-pcap_tstamp_type_name_to_val(3PCAP),
-pcap_set_tstamp_precision(3PCAP),
-pcap_open_offline_with_tstamp_precision(3PCAP),
-\%pcap_fopen_offline_with_tstamp_precision(3PCAP),
-\%pcap_get_tstamp_precision(3PCAP)
-.ad
diff --git a/pcap-tstamp.manmisc.in b/pcap-tstamp.manmisc.in
index 38c5651..eea8c1d 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@ "8 March 2015"
+.TH PCAP-TSTAMP @MAN_MISC_INFO@ "14 July 2020"
 .SH NAME
 pcap-tstamp \- packet time stamps in libpcap
 .SH DESCRIPTION
@@ -58,7 +58,20 @@
 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.
+consistent time stamps;
+.IP
+some time sources, such as those that supply POSIX "seconds since the
+Epoch" time, do not count leap seconds, meaning that the seconds
+portion
+.RB ( tv_sec )
+of the time stamp might not be incremented for a leap second, so that
+the fraction-of-a-second part of the time stamp might roll over past
+zero but the second part would not change, or the clock might run
+slightly more slowly for a period before the leap second.
+.LP
+For these reasons, time differences between packet time stamps will not
+necessarily accurately reflect the time differences between the receipt
+or transmission times of the packets.
 .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
@@ -73,6 +86,9 @@
 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.
+If they are synchronized with the host operating system's clock, some of
+the issues listed above with time stamps supplied by the host operating
+system may also apply to time stamps supplied by the capture device.
 .LP
 Depending on the capture device and the software on the host, libpcap
 might allow different types of time stamp to be used.  The
@@ -87,15 +103,15 @@
 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()
+.BR pcap_create ()
 call and before a
-.B pcap_activate()
+.BR 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()
+.BR pcap_tstamp_type_val_to_name (3PCAP)
 and accepted by
-.BR pcap_tstamp_type_name_to_val() .
+.BR pcap_tstamp_type_name_to_val (3PCAP) .
 .RS 5
 .TP 5
 .BR PCAP_TSTAMP_HOST " - " host
@@ -110,9 +126,14 @@
 .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
+This is a high-precision time stamp, 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_HOST_HIPREC_UNSYNCED " - " host_hiprec_unsynced
+Time stamp provided by the host on which the capture is being done.
+This is a high-precision time stamp, not 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
@@ -126,6 +147,18 @@
 the host operating system's clock.
 .RE
 .LP
+Time stamps synchronized with the system clock can go backwards, as the
+system clock can go backwards. If a clock is not in sync with the
+system clock, that could be because the system clock isn't keeping
+accurate time, because the other clock isn't keeping accurate time, or
+both.
+.LP
+Host-provided time stamps generally correspond to the time when the
+time-stamping code sees the packet; this could be some unknown amount of
+time after the first or last bit of the packet is received by the
+network adapter, due to batching of interrupts for packet arrival,
+queueing delays, etc..
+.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
@@ -137,21 +170,21 @@
 The
 .BR pcap_set_tstamp_precision (3PCAP)
 routine can be used after a
-.B pcap_create()
+.BR pcap_create ()
 call and after a
-.B pcap_activate()
+.BR 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()
+.BR pcap_set_tstamp_precision ()
 call will fail, and the time stamps supplied after the
-.B pcap_activate()
+.BR pcap_activate ()
 call will have microsecond resolution.
 .LP
 When opening a savefile, the
-.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+.BR \%pcap_open_offline_with_tstamp_precision (3PCAP)
 and
-.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+.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
@@ -165,13 +198,4 @@
 reading a savefile, this does not indicate the actual precision of time
 stamps in the file.
 .SH SEE ALSO
-.na
-pcap_set_tstamp_type(3PCAP),
-pcap_list_tstamp_types(3PCAP),
-pcap_tstamp_type_val_to_name(3PCAP),
-pcap_tstamp_type_name_to_val(3PCAP),
-pcap_set_tstamp_precision(3PCAP),
-pcap_open_offline_with_tstamp_precision(3PCAP),
-\%pcap_fopen_offline_with_tstamp_precision(3PCAP),
-\%pcap_get_tstamp_precision(3PCAP)
-.ad
+.BR pcap (3PCAP)
diff --git a/pcap-types.h b/pcap-types.h
index 9614f9f..7d0fe81 100644
--- a/pcap-types.h
+++ b/pcap-types.h
@@ -35,7 +35,6 @@
  * Get u_int defined, by hook or by crook.
  */
 #ifdef _WIN32
-
   /*
    * This defines u_int.
    */
diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c
index 6f8adf6..3596428 100644
--- a/pcap-usb-linux.c
+++ b/pcap-usb-linux.c
@@ -41,15 +41,17 @@
 #include "pcap-usb-linux.h"
 #include "pcap/usb.h"
 
+#include "extract.h"
+
 #ifdef NEED_STRERROR_H
 #include "strerror.h"
 #endif
 
-#include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <string.h>
 #include <dirent.h>
 #include <byteswap.h>
@@ -135,7 +137,7 @@
 static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
 static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
 static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
-static int usb_inject_linux(pcap_t *, const void *, size_t);
+static int usb_inject_linux(pcap_t *, const void *, int);
 static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
 static void usb_cleanup_linux_mmap(pcap_t *);
 
@@ -144,7 +146,7 @@
 {
 	struct utsname utsname;
 	char *version_component, *endp;
-	int major, minor, subminor;
+	long major, minor, subminor;
 
 	if (uname(&utsname) == 0) {
 		/*
@@ -229,7 +231,7 @@
 {
 	char dev_name[10];
 	char dev_descr[30];
-	pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
+	snprintf(dev_name, 10, USB_IFACE"%d", n);
 	/*
 	 * XXX - is there any notion of "up" and "running"?
 	 */
@@ -241,7 +243,7 @@
 		 */
 		if (add_dev(devlistp, dev_name,
 		    PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
-		    "All USB buses", err_str) == NULL)
+		    "Raw USB traffic, all USB buses", err_str) == NULL)
 			return -1;
 	} else {
 		/*
@@ -250,7 +252,7 @@
 		 * PCAP_IF_CONNECTION_STATUS_CONNECTED or
 		 * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
 		 */
-		pcap_snprintf(dev_descr, 30, "USB bus number %d", n);
+		snprintf(dev_descr, 30, "Raw USB traffic, bus number %d", n);
 		if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
 			return -1;
 	}
@@ -278,7 +280,7 @@
 		 * Split LINUX_USB_MON_DEV into a directory that we'll
 		 * scan and a file name prefix that we'll check for.
 		 */
-		strlcpy(usb_mon_dir, LINUX_USB_MON_DEV, sizeof usb_mon_dir);
+		pcap_strlcpy(usb_mon_dir, LINUX_USB_MON_DEV, sizeof usb_mon_dir);
 		usb_mon_prefix = strrchr(usb_mon_dir, '/');
 		if (usb_mon_prefix == NULL) {
 			/*
@@ -362,9 +364,9 @@
 				len = strlen(name);
 
 				/* if this file name does not end with a number it's not of our interest */
-				if ((len < 1) || !isdigit(name[--len]))
+				if ((len < 1) || !PCAP_ISDIGIT(name[--len]))
 					continue;
-				while (isdigit(name[--len]));
+				while (PCAP_ISDIGIT(name[--len]));
 				if (sscanf(&name[len+1], "%d", &n) != 1)
 					continue;
 
@@ -380,18 +382,102 @@
 	}
 }
 
+/*
+ * Matches what's in mon_bin.c in the Linux kernel.
+ */
+#define MIN_RING_SIZE	(8*1024)
+#define MAX_RING_SIZE	(1200*1024)
+
+static int
+usb_set_ring_size(pcap_t* handle, int header_size)
+{
+	/*
+	 * A packet from binary usbmon has:
+	 *
+	 *  1) a fixed-length header, of size header_size;
+	 *  2) descriptors, for isochronous transfers;
+	 *  3) the payload.
+	 *
+	 * The kernel buffer has a size, defaulting to 300KB, with a
+	 * minimum of 8KB and a maximum of 1200KB.  The size is set with
+	 * the MON_IOCT_RING_SIZE ioctl; the size passed in is rounded up
+	 * to a page size.
+	 *
+	 * No more than {buffer size}/5 bytes worth of payload is saved.
+	 * Therefore, if we subtract the fixed-length size from the
+	 * snapshot length, we have the biggest payload we want (we
+	 * don't worry about the descriptors - if we have descriptors,
+	 * we'll just discard the last bit of the payload to get it
+	 * to fit).  We multiply that result by 5 and set the buffer
+	 * size to that value.
+	 */
+	int ring_size;
+
+	if (handle->snapshot < header_size)
+		handle->snapshot = header_size;
+	/* The maximum snapshot size is small enough that this won't overflow */
+	ring_size = (handle->snapshot - header_size) * 5;
+
+	/*
+	 * Will this get an error?
+	 * (There's no wqy to query the minimum or maximum, so we just
+	 * copy the value from the kernel source.  We don't round it
+	 * up to a multiple of the page size.)
+	 */
+	if (ring_size > MAX_RING_SIZE) {
+		/*
+		 * Yes.  Lower the ring size to the maximum, and set the
+		 * snapshot length to the value that would give us a
+		 * maximum-size ring.
+		 */
+		ring_size = MAX_RING_SIZE;
+		handle->snapshot = header_size + (MAX_RING_SIZE/5);
+	} else if (ring_size < MIN_RING_SIZE) {
+		/*
+		 * Yes.  Raise the ring size to the minimum, but leave
+		 * the snapshot length unchanged, so we show the
+		 * callback no more data than specified by the
+		 * snapshot length.
+		 */
+		ring_size = MIN_RING_SIZE;
+	}
+
+	if (ioctl(handle->fd, MON_IOCT_RING_SIZE, ring_size) == -1) {
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "Can't set ring size from fd %d", handle->fd);
+		return -1;
+	}
+	return ring_size;
+}
+
 static
 int usb_mmap(pcap_t* handle)
 {
 	struct pcap_usb_linux *handlep = handle->priv;
-	int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
-	if (len < 0)
+	int len;
+
+	/*
+	 * Attempt to set the ring size as appropriate for the snapshot
+	 * length, reducing the snapshot length if that'd make the ring
+	 * bigger than the kernel supports.
+	 */
+	len = usb_set_ring_size(handle, (int)sizeof(pcap_usb_header_mmapped));
+	if (len == -1) {
+		/* Failed.  Fall back on non-memory-mapped access. */
 		return 0;
+	}
 
 	handlep->mmapbuflen = len;
 	handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
 	    MAP_SHARED, handle->fd, 0);
-	return handlep->mmapbuf != MAP_FAILED;
+	if (handlep->mmapbuf == MAP_FAILED) {
+		/*
+		 * Failed.  We don't treat that as a fatal error, we
+		 * just try to fall back on non-memory-mapped access.
+		 */
+		return 0;
+	}
+	return 1;
 }
 
 #ifdef HAVE_LINUX_USBDEVICE_FS_H
@@ -405,6 +491,10 @@
 #define USB_REQ_GET_DESCRIPTOR	6
 
 #define USB_DT_DEVICE		1
+#define USB_DT_CONFIG		2
+
+#define USB_DEVICE_DESCRIPTOR_SIZE	18
+#define USB_CONFIG_DESCRIPTOR_SIZE	9
 
 /* probe the descriptors of the devices attached to the bus */
 /* the descriptors will end up in the captured packet stream */
@@ -416,12 +506,14 @@
 	struct usbdevfs_ctrltransfer ctrl;
 	struct dirent* data;
 	int ret = 0;
-	char buf[sizeof("/dev/bus/usb/000/") + NAME_MAX];
+	char busdevpath[sizeof("/dev/bus/usb/000/") + NAME_MAX];
 	DIR* dir;
+	uint8_t descriptor[USB_DEVICE_DESCRIPTOR_SIZE];
+	uint8_t configdesc[USB_CONFIG_DESCRIPTOR_SIZE];
 
 	/* scan usb bus directories for device nodes */
-	pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
-	dir = opendir(buf);
+	snprintf(busdevpath, sizeof(busdevpath), "/dev/bus/usb/%03d", bus);
+	dir = opendir(busdevpath);
 	if (!dir)
 		return;
 
@@ -432,9 +524,9 @@
 		if (name[0] == '.')
 			continue;
 
-		pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
+		snprintf(busdevpath, sizeof(busdevpath), "/dev/bus/usb/%03d/%s", bus, data->d_name);
 
-		fd = open(buf, O_RDWR);
+		fd = open(busdevpath, O_RDWR);
 		if (fd == -1)
 			continue;
 
@@ -447,19 +539,43 @@
 		ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
 		ctrl.wValue = USB_DT_DEVICE << 8;
 		ctrl.wIndex = 0;
- 		ctrl.wLength = sizeof(buf);
+ 		ctrl.wLength = sizeof(descriptor);
 #else
 		ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
 		ctrl.request = USB_REQ_GET_DESCRIPTOR;
 		ctrl.value = USB_DT_DEVICE << 8;
 		ctrl.index = 0;
- 		ctrl.length = sizeof(buf);
+ 		ctrl.length = sizeof(descriptor);
 #endif
-		ctrl.data = buf;
+		ctrl.data = descriptor;
 		ctrl.timeout = CTRL_TIMEOUT;
 
 		ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
 
+		/* Request CONFIGURATION descriptor alone to know wTotalLength */
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+		ctrl.wValue = USB_DT_CONFIG << 8;
+		ctrl.wLength = sizeof(configdesc);
+#else
+		ctrl.value = USB_DT_CONFIG << 8;
+		ctrl.length = sizeof(configdesc);
+#endif
+		ctrl.data = configdesc;
+		ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+		if (ret >= 0) {
+			uint16_t wtotallength;
+			wtotallength = EXTRACT_LE_U_2(&configdesc[2]);
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+			ctrl.wLength = wtotallength;
+#else
+			ctrl.length = wtotallength;
+#endif
+			ctrl.data = malloc(wtotallength);
+			if (ctrl.data) {
+				ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+				free(ctrl.data);
+			}
+		}
 		close(fd);
 	}
 	closedir(dir);
@@ -501,7 +617,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));
+	p = PCAP_CREATE_COMMON(ebuf, struct pcap_usb_linux);
 	if (p == NULL)
 		return (NULL);
 
@@ -514,6 +630,7 @@
 {
 	struct pcap_usb_linux *handlep = handle->priv;
 	char 		full_path[USB_LINE_LEN];
+	int		ret;
 
 	/*
 	 * Turn a negative snapshot value (invalid), a snapshot value of
@@ -541,7 +658,7 @@
 	/*get usb bus index from device name */
 	if (sscanf(handle->opt.device, USB_IFACE"%d", &handlep->bus_index) != 1)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't get USB bus index from %s", handle->opt.device);
 		return PCAP_ERROR;
 	}
@@ -552,7 +669,7 @@
 		 * We have binary-mode support.
 		 * Try to open the binary interface.
 		 */
-		pcap_snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
+		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)
 		{
@@ -604,6 +721,7 @@
 		/* try to use fast mmap access */
 		if (usb_mmap(handle))
 		{
+			/* We succeeded. */
 			handle->linktype = DLT_USB_LINUX_MMAPPED;
 			handle->stats_op = usb_stats_linux_bin;
 			handle->read_op = usb_read_linux_mmap;
@@ -620,7 +738,19 @@
 			return 0;
 		}
 
-		/* can't mmap, use plain binary interface access */
+		/*
+		 * We failed; try plain binary interface access.
+		 *
+		 * Attempt to set the ring size as appropriate for
+		 * the snapshot length, reducing the snapshot length
+		 * if that'd make the ring bigger than the kernel
+		 * supports.
+		 */
+		if (usb_set_ring_size(handle, (int)sizeof(pcap_usb_header)) == -1) {
+			/* Failed. */
+			close(handle->fd);
+			return PCAP_ERROR;
+		}
 		handle->stats_op = usb_stats_linux_bin;
 		handle->read_op = usb_read_linux_bin;
 #ifdef HAVE_LINUX_USBDEVICE_FS_H
@@ -632,7 +762,7 @@
 		 * We don't have binary mode support.
 		 * Try opening the text-mode device.
 		 */
-		pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
+		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)
 		{
@@ -642,42 +772,42 @@
 				 * Not found at the new location; try
 				 * the old location.
 				 */
-				pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
+				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) {
-				/*
-				 * Is the problem that we didn't have
-				 * sufficient permission to open it?
-				 */
-				if (errno == EACCES) {
+				if (errno == ENOENT)
+				{
 					/*
-					 * Yes - return that error.
+					 * The problem is that the file
+					 * doesn't exist.  Report that as
+					 * "no such device".  (That could
+					 * mean "no such USB bus" or
+					 * "monitoring not supported".)
 					 */
-					return PCAP_ERROR_PERM_DENIED;
+					ret = PCAP_ERROR_NO_SUCH_DEVICE;
 				}
-
-				/*
-				 * No - was the problem something other
-				 * than "it doesn't exist"?
-				 */
-				if (errno != ENOENT) {
+				else if (errno == EACCES)
+				{
 					/*
-					 * Yes - return *that* error.
+					 * The problem is that we don't
+					 * have sufficient permission to
+					 * open the file.  Report that.
 					 */
-					pcap_fmt_errmsg_for_errno(handle->errbuf,
-					    PCAP_ERRBUF_SIZE, errno,
-					    "Can't open USB bus file %s",
-					    full_path);
-					return PCAP_ERROR;
+					ret = PCAP_ERROR_PERM_DENIED;
 				}
-
-				/*
-				 * No.  Report that as "no such device".
-				 * (That could mean "no such USB bus"
-				 * or "monitoring not supported".)
-				 */
-				return PCAP_ERROR_NO_SUCH_DEVICE;
+				else
+				{
+					/*
+					 * Some other error.
+					 */
+					ret = PCAP_ERROR;
+				}
+				pcap_fmt_errmsg_for_errno(handle->errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "Can't open USB bus file %s",
+				    full_path);
+				return ret;
 			}
 		}
 
@@ -733,6 +863,7 @@
 	struct pcap_usb_linux *handlep = handle->priv;
 	unsigned timestamp;
 	int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
+	ssize_t read_ret;
 	char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
 	char *string = line;
 	u_char * rawdata = handle->buffer;
@@ -743,14 +874,14 @@
 
 	/* ignore interrupt system call errors */
 	do {
-		ret = read(handle->fd, line, USB_LINE_LEN - 1);
+		read_ret = read(handle->fd, line, USB_LINE_LEN - 1);
 		if (handle->break_loop)
 		{
 			handle->break_loop = 0;
 			return -2;
 		}
-	} while ((ret == -1) && (errno == EINTR));
-	if (ret < 0)
+	} while ((read_ret == -1) && (errno == EINTR));
+	if (read_ret < 0)
 	{
 		if (errno == EAGAIN)
 			return 0;	/* no data there */
@@ -762,15 +893,19 @@
 
 	/* read urb header; %n argument may increment return value, but it's
 	* not mandatory, so does not count on it*/
-	string[ret] = 0;
+	string[read_ret] = 0;
 	ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
 		&pipeid1, &pipeid2, &dev_addr, &ep_num, status,
 		&cnt);
 	if (ret < 8)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
-		    string, ret);
+		char string_truncated[181];
+
+		strncpy(string_truncated, string, sizeof(string_truncated));
+		string_truncated[sizeof(string_truncated) - 1] = 0;
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			 "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
+			 string_truncated, ret);
 		return -1;
 	}
 	uhdr->id = tag;
@@ -787,7 +922,7 @@
 		return -1;
 	}
 	uhdr->ts_sec = pkth.ts.tv_sec;
-	uhdr->ts_usec = pkth.ts.tv_usec;
+	uhdr->ts_usec = (int32_t)pkth.ts.tv_usec;
 
 	/* parse endpoint information */
 	if (pipeid1 == 'C')
@@ -833,7 +968,7 @@
 		str5, &cnt);
 		if (ret < 5)
 		{
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
 				string, ret);
 			return -1;
@@ -857,7 +992,7 @@
 	ret = sscanf(string, " %d%n", &urb_len, &cnt);
 	if (ret < 1)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		  "Can't parse urb length from '%s'", string);
 		return -1;
 	}
@@ -875,7 +1010,7 @@
 	/* check for data presence; data is present if and only if urb tag is '=' */
 	if (sscanf(string, " %c", &urb_tag) != 1)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't parse urb tag from '%s'", string);
 		return -1;
 	}
@@ -911,7 +1046,7 @@
 		pkth.caplen = (bpf_u_int32)handle->snapshot;
 
 	if (handle->fcode.bf_insns == NULL ||
-	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
+	    pcap_filter(handle->fcode.bf_insns, handle->buffer,
 	      pkth.len, pkth.caplen)) {
 		handlep->packets_read++;
 		callback(user, &pkth, handle->buffer);
@@ -921,10 +1056,10 @@
 }
 
 static int
-usb_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+usb_inject_linux(pcap_t *handle, const void *buf _U_, int size _U_)
 {
-	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
-		"USB devices");
+	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packet injection is not supported on USB devices");
 	return (-1);
 }
 
@@ -932,13 +1067,14 @@
 usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
 {
 	struct pcap_usb_linux *handlep = handle->priv;
-	int dummy, ret, consumed, cnt;
+	int dummy, cnt;
+	ssize_t ret, consumed;
 	char string[USB_LINE_LEN];
 	char token[USB_LINE_LEN];
 	char * ptr = string;
 	int fd;
 
-	pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
+	snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
 	fd = open(string, O_RDONLY, 0);
 	if (fd < 0)
 	{
@@ -948,7 +1084,7 @@
 			 * Not found at the new location; try the old
 			 * location.
 			 */
-			pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
+			snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
 			fd = open(string, O_RDONLY, 0);
 		}
 		if (fd < 0) {
@@ -967,12 +1103,16 @@
 
 	if (ret < 0)
 	{
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't read stats from fd %d ", fd);
 		return -1;
 	}
 	string[ret] = 0;
 
+	stats->ps_recv = handlep->packets_read;
+	stats->ps_drop = 0;	/* unless we find text_lost */
+	stats->ps_ifdrop = 0;
+
 	/* extract info on dropped urbs */
 	for (consumed=0; consumed < ret; ) {
 		/* from the sscanf man page:
@@ -989,24 +1129,26 @@
 			break;
 		consumed += cnt;
 		ptr += cnt;
-		if (strcmp(token, "nreaders") == 0)
-			ret = sscanf(ptr, "%d", &stats->ps_drop);
+		if (strcmp(token, "text_lost") == 0)
+			ntok = sscanf(ptr, "%d%n", &stats->ps_drop, &cnt);
 		else
-			ret = sscanf(ptr, "%d", &dummy);
-		if (ntok != 1)
+			ntok = sscanf(ptr, "%d%n", &dummy, &cnt);
+		if ((ntok != 1) || (cnt < 0))
 			break;
 		consumed += cnt;
 		ptr += cnt;
 	}
 
-	stats->ps_recv = handlep->packets_read;
-	stats->ps_ifdrop = 0;
 	return 0;
 }
 
 static int
 usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
 {
+	/*
+	 * It's guaranteed, at this point, that d is a valid
+	 * direction value.
+	 */
 	p->direction = d;
 	return 0;
 }
@@ -1069,18 +1211,49 @@
 		return -1;
 	}
 
-	/* we can get less that than really captured from kernel, depending on
-	 * snaplen, so adjust header accordingly */
+	/*
+	 * info.hdr->data_len is the number of bytes of isochronous
+	 * descriptors (if any) plus the number of bytes of data
+	 * provided.  There are no isochronous descriptors here,
+	 * because we're using the old 48-byte header.
+	 *
+	 * If info.hdr->data_flag is non-zero, there's no URB data;
+	 * info.hdr->urb_len is the size of the buffer into which
+	 * data is to be placed; it does not represent the amount
+	 * of data transferred.  If info.hdr->data_flag is zero,
+	 * there is URB data, and info.hdr->urb_len is the number
+	 * of bytes transmitted or received; it doesn't include
+	 * isochronous descriptors.
+	 *
+	 * The kernel may give us more data than the snaplen; if it did,
+	 * reduce the data length so that the total number of bytes we
+	 * tell our client we have is not greater than the snaplen.
+	 */
 	if (info.hdr->data_len < clen)
 		clen = info.hdr->data_len;
 	info.hdr->data_len = clen;
-	pkth.caplen = clen + sizeof(pcap_usb_header);
-	pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
-	pkth.ts.tv_sec = info.hdr->ts_sec;
+	pkth.caplen = sizeof(pcap_usb_header) + clen;
+	if (info.hdr->data_flag) {
+		/*
+		 * No data; just base the on-the-wire length on
+		 * info.hdr->data_len (so that it's >= the captured
+		 * length).
+		 */
+		pkth.len = sizeof(pcap_usb_header) + info.hdr->data_len;
+	} else {
+		/*
+		 * We got data; base the on-the-wire length on
+		 * info.hdr->urb_len, so that it includes data
+		 * discarded by the USB monitor device due to
+		 * its buffer being too small.
+		 */
+		pkth.len = sizeof(pcap_usb_header) + info.hdr->urb_len;
+	}
+	pkth.ts.tv_sec = (time_t)info.hdr->ts_sec;
 	pkth.ts.tv_usec = info.hdr->ts_usec;
 
 	if (handle->fcode.bf_insns == NULL ||
-	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
+	    pcap_filter(handle->fcode.bf_insns, handle->buffer,
 	      pkth.len, pkth.caplen)) {
 		handlep->packets_read++;
 		callback(user, &pkth, handle->buffer);
@@ -1102,12 +1275,12 @@
 	struct mon_bin_mfetch fetch;
 	int32_t vec[VEC_SIZE];
 	struct pcap_pkthdr pkth;
-	pcap_usb_header* hdr;
+	pcap_usb_header_mmapped* hdr;
 	int nflush = 0;
 	int packets = 0;
 	u_int clen, max_clen;
 
-	max_clen = handle->snapshot - sizeof(pcap_usb_header);
+	max_clen = handle->snapshot - sizeof(pcap_usb_header_mmapped);
 
 	for (;;) {
 		int i, ret;
@@ -1145,24 +1318,57 @@
 		nflush = fetch.nfetch;
 		for (i=0; i<fetch.nfetch; ++i) {
 			/* discard filler */
-			hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
+			hdr = (pcap_usb_header_mmapped*) &handlep->mmapbuf[vec[i]];
 			if (hdr->event_type == '@')
 				continue;
 
-			/* we can get less that than really captured from kernel, depending on
-	 		* snaplen, so adjust header accordingly */
+			/*
+			 * hdr->data_len is the number of bytes of
+			 * isochronous descriptors (if any) plus the
+			 * number of bytes of data provided.
+			 *
+			 * If hdr->data_flag is non-zero, there's no
+			 * URB data; hdr->urb_len is the size of the
+			 * buffer into which data is to be placed; it does
+			 * not represent the amount of data transferred.
+			 * If hdr->data_flag is zero, there is URB data,
+			 * and hdr->urb_len is the number of bytes
+			 * transmitted or received; it doesn't include
+			 * isochronous descriptors.
+			 *
+			 * The kernel may give us more data than the
+			 * snaplen; if it did, reduce the data length
+			 * so that the total number of bytes we
+			 * tell our client we have is not greater than
+			 * the snaplen.
+			 */
 			clen = max_clen;
 			if (hdr->data_len < clen)
 				clen = hdr->data_len;
-
-			/* get packet info from header*/
-			pkth.caplen = clen + sizeof(pcap_usb_header_mmapped);
-			pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped);
-			pkth.ts.tv_sec = hdr->ts_sec;
+			pkth.caplen = sizeof(pcap_usb_header_mmapped) + clen;
+			if (hdr->data_flag) {
+				/*
+				 * No data; just base the on-the-wire length
+				 * on hdr->data_len (so that it's >= the
+				 * captured length).
+				 */
+				pkth.len = sizeof(pcap_usb_header_mmapped) +
+				    hdr->data_len;
+			} else {
+				/*
+				 * We got data; base the on-the-wire length
+				 * on hdr->urb_len, so that it includes
+				 * data discarded by the USB monitor device
+				 * due to its buffer being too small.
+				 */
+				pkth.len = sizeof(pcap_usb_header_mmapped) +
+				    (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len;
+			}
+			pkth.ts.tv_sec = (time_t)hdr->ts_sec;
 			pkth.ts.tv_usec = hdr->ts_usec;
 
 			if (handle->fcode.bf_insns == NULL ||
-			    bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
+			    pcap_filter(handle->fcode.bf_insns, (u_char*) hdr,
 			      pkth.len, pkth.caplen)) {
 				handlep->packets_read++;
 				callback(user, &pkth, (u_char*) hdr);
@@ -1170,7 +1376,7 @@
 			}
 		}
 
-		/* with max_packets specifying "unlimited" we stop afer the first chunk*/
+		/* with max_packets specifying "unlimited" we stop after the first chunk*/
 		if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets))
 			break;
 	}
diff --git a/pcap.3pcap b/pcap.3pcap
deleted file mode 100644
index c6b8891..0000000
--- a/pcap.3pcap
+++ /dev/null
@@ -1,945 +0,0 @@
-.\" 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 "20 April 2018"
-.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 "packet buffer timeout"
-If, when capturing, packets are delivered as soon as they arrive, the
-application capturing the packets will be woken up for each packet as it
-arrives, and might have to make one or more calls to the operating
-system to fetch each packet.
-.IP
-If, instead, packets are not delivered as soon as they arrive, but are
-delivered after a short delay (called a "packet buffer timeout"), more
-than one packet can be accumulated before the packets are delivered, so
-that a single wakeup would be done for multiple packets, and each set of
-calls made to the operating system would supply multiple packets, rather
-than a single packet.  This reduces the per-packet CPU overhead if
-packets are arriving at a high rate, increasing the number of packets
-per second that can be captured.
-.IP
-The packet buffer timeout is required so that an application won't wait
-for the operating system's capture buffer to fill up before packets are
-delivered; if packets are arriving slowly, that wait could take an
-arbitrarily long period of time.
-.IP
-Not all platforms support a packet buffer timeout; on platforms that
-don't, the packet buffer timeout is ignored.  A zero value for the
-timeout, on platforms that support a packet buffer timeout, will cause a
-read to wait forever to allow enough packets to arrive, with no timeout.
-A negative value is invalid; the result of setting the timeout to a
-negative value is unpredictable.
-.IP
-.BR NOTE :
-the packet buffer timeout cannot be used to cause calls that read
-packets to return within a limited period of time, because, on some
-platforms, the packet buffer timeout isn't supported, and, on other
-platforms, the timer doesn't start until at least one packet arrives.
-This means that the packet buffer timeout should
-.B NOT
-be used, for example, in an interactive application to allow the packet
-capture loop to ``poll'' for user input periodically, as there's no
-guarantee that a call reading packets will return after the timeout
-expires even if no packets have arrived.
-.IP
-The packet buffer timeout is set with
-.BR pcap_set_timeout ().
-.IP "buffer size"
-Packets that arrive for a capture are stored in a buffer, so that they
-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 (8)
-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 macOS):
-You must have read access to
-.I /dev/bpf*
-on systems that don't have a cloning BPF device, or to
-.I /dev/bpf
-on systems that do.
-On BSDs with a devfs (this includes macOS), this might involve more
-than just having somebody with super-user access setting the ownership
-or permissions on the BPF devices - it might involve configuring devfs
-to set the ownership or permissions every time the system is booted,
-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 https://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_protocol_linux (3PCAP)
-set capture protocol for a not-yet-activated
-.B pcap_t
-for live capture (Linux only)
-.TP
-.BR pcap_set_rfmon (3PCAP)
-set monitor mode for a not-yet-activated
-.B pcap_t
-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 packet buffer 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 packet buffer timeout was specified, the wait will
-terminate after the packet buffer timeout expires; applications should
-be prepared for this, as it happens on some platforms, but should not
-rely on it, as it does not happen on other platforms.  Note that the
-wait might, or might not, terminate even if no packets are available;
-applications should be prepared for this to happen, but must not rely on
-it happening.
-.PP
-A handle can be put into ``non-blocking mode'', so that those routines
-will, rather than blocking, return an indication that no packets are
-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 packet buffer timeout expires, a
-.BR select (),
-.BR poll (),
-or other such call may, if the packet buffer timeout expires, indicate
-that a descriptor is ready to read even if there are no packets
-available to read.
-.TP
-.B Routines
-.RS
-.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(8)
-.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 https://www.tcpdump.org/
-.RE
-.SH BUGS
-To report a security issue please send an e-mail to security@tcpdump.org.
-.LP
-To report bugs and other problems, contribute patches, request a
-feature, provide generic feedback etc please see the file
-.I CONTRIBUTING
-in the libpcap source tree root.
diff --git a/pcap.3pcap.in b/pcap.3pcap.in
index 4a222c7..492c227 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 "20 April 2018"
+.TH PCAP 3PCAP "9 September 2020"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
@@ -35,12 +35,69 @@
 through this mechanism.
 It also supports saving captured packets to a ``savefile'', and reading
 packets from a ``savefile''.
+.SS Initializing
+.BR pcap_init ()
+initializes the library.  It takes an argument giving options;
+currently, the options are:
+.TP
+.B PCAP_CHAR_ENC_LOCAL
+Treat all strings supplied as arguments, and return all strings to the
+caller, as being in the local character encoding.
+.TP
+.B PCAP_CHAR_ENC_UTF_8
+Treat all strings supplied as arguments, and return all strings to the
+caller, as being in UTF-8.
+.PP
+On UNIX-like systems, the local character encoding is assumed to be
+UTF-8, so no character encoding transformations are done.
+.PP
+On Windows, the local character encoding is the local ANSI code page.
+.PP
+If
+.BR pcap_init ()
+is called, the deprecated
+.BR pcap_lookupdev ()
+routine always fails, so it should not be used, and, on Windows,
+.BR pcap_create ()
+does not attempt to handle UTF-16LE strings.
+.PP
+If
+.BR pcap_init ()
+is not called, strings are treated as being in the local ANSI code page
+on Windows,
+.BR pcap_lookupdev ()
+will succeed if there is a device on which to capture, and
+.BR pcap_create ()
+makes an attempt to check whether the string passed as an argument is a
+UTF-16LE string - note that this attempt is unsafe, as it may run past
+the end of the string - to handle
+.BR pcap_lookupdev ()
+returning a UTF-16LE string. Programs that don't call
+.BR pcap_init ()
+should, on Windows, call
+.BR pcap_wsockinit ()
+to initialize Winsock; this is not necessary if
+.BR pcap_init ()
+is called, as
+.BR pcap_init ()
+will initialize Winsock itself on Windows.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_init (3PCAP)
+initialize the library
+.RE
 .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 ().
+If
+.BR pcap_activate ()
+fails, the handle should be closed with
+.BR pcap_close ().
 .PP
 To obtain a list of devices that can be opened for a live capture, call
 .BR pcap_findalldevs ();
@@ -121,7 +178,9 @@
 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.
+or
+.B NULL
+is supplied, the setting of promiscuous mode is ignored.
 .IP
 Promiscuous mode is set with
 .BR pcap_set_promisc ().
@@ -191,6 +250,10 @@
 .IP
 The packet buffer timeout is set with
 .BR pcap_set_timeout ().
+.IP "immediate mode"
+In immediate mode, packets are always delivered as soon as they arrive,
+with no buffering.  Immediate mode is set with
+.BR pcap_set_immediate_mode ().
 .IP "buffer size"
 Packets that arrive for a capture are stored in a buffer, so that they
 do not have to be read by the application as soon as they arrive.  On
@@ -245,7 +308,7 @@
 that privilege to the user's
 .B defaultpriv
 key with the
-.B usermod (@MAN_ADMIN_COMMANDS@)
+.BR usermod (@MAN_ADMIN_COMMANDS@)
 command.
 .TP
 .B Under HP-UX with DLPI:
@@ -258,14 +321,11 @@
 .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
+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).
+which case you must have CAP_NET_RAW in order to capture.
 .TP
 .B Under ULTRIX and Digital UNIX/Tru64 UNIX:
 Any user may capture network traffic.
@@ -316,6 +376,8 @@
 for Ethernet.  For example, the "any" device on Linux will have a
 link-layer header type of
 .B DLT_LINUX_SLL
+or
+.B DLT_LINUX_SLL2
 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
@@ -416,6 +478,11 @@
 .B pcap_t
 for live capture
 .TP
+.BR pcap_set_immediate_mode (3PCAP)
+set immediate mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
 .BR pcap_set_buffer_size (3PCAP)
 set buffer size for a not-yet-activated
 .B pcap_t
@@ -506,7 +573,11 @@
 get name for a link-layer header type
 .TP
 .BR pcap_datalink_val_to_description (3PCAP)
+.PD 0
+.TP
+.BR pcap_datalink_val_to_description_or_dlt (3PCAP)
 get description for a link-layer header type
+.PD
 .TP
 .BR pcap_datalink_name_to_val (3PCAP)
 get link-layer header type corresponding to a name
@@ -576,7 +647,9 @@
 .I const u_char
 to the first
 .B caplen
-bytes of the packet on success, and NULL on error.
+bytes of the packet on success, and
+.B NULL
+on error.
 .PP
 .BR pcap_next_ex ()
 is passed two pointer arguments, one of which points to a
@@ -632,9 +705,30 @@
 descriptors to be ready to read.  To obtain, for a handle, a descriptor
 that can be used in those routines, call
 .BR pcap_get_selectable_fd ().
+If the routine indicates that data is
+available to read on the descriptor, an attempt should be made to read
+from the device.
+.PP
 Not all handles have such a descriptor available;
 .BR pcap_get_selectable_fd ()
-will return \-1 if no such descriptor exists.  In addition, for various
+will return
+.B \-1
+if no such descriptor is available.  If no such
+descriptor is available, this may be because the device must be polled
+periodically for packets; in that case,
+.BR pcap_get_required_select_timeout ()
+will return a pointer to a
+.B struct timeval
+whose value can be used as a timeout in those routines.  When the
+routine returns, an attmept should be made to read packets from the
+device.  If
+.BR pcap_get_required_select_timeout ()
+returns
+.BR NULL ,
+no such timeout is available, and those routines cannot be
+used with the device.
+.PP
+In addition, for various
 reasons, one or more of those routines will not work properly with the
 descriptor; the documentation for
 .BR pcap_get_selectable_fd ()
@@ -693,6 +787,14 @@
 .BR select (2)
 and
 .BR poll (2)
+.TP
+.BR pcap_get_required_select_timeout (3PCAP)
+attempt to get a timeout required for using a
+.B pcap_t
+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
@@ -856,8 +958,9 @@
 .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.)
+(The two routines exist for compatibility with both OpenBSD and
+WinPcap/Npcap; they perform the same function, but have different return
+values.)
 .TP
 .B Routines
 .RS
@@ -890,7 +993,7 @@
 .BR pcap_lib_version (3PCAP)
 get library version string
 .RE
-.SH BACKWARDS COMPATIBILITY
+.SH BACKWARD COMPATIBILITY
 .PP
 In versions of libpcap prior to 1.0, the
 .B pcap.h
@@ -921,8 +1024,12 @@
 script or some other configuration script to check whether the libpcap
 1.0 APIs are available and use them only if they are.
 .SH SEE ALSO
-autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8),
-usermod(@MAN_ADMIN_COMMANDS@)
+.BR autoconf (1),
+.BR tcpdump (1),
+.BR tcpslice (1),
+.BR pcap-filter (@MAN_MISC_INFO@),
+.BR pfconfig (8),
+.BR usermod (@MAN_ADMIN_COMMANDS@)
 .SH AUTHORS
 The original authors of libpcap are:
 .LP
@@ -941,5 +1048,5 @@
 .LP
 To report bugs and other problems, contribute patches, request a
 feature, provide generic feedback etc please see the file
-.I CONTRIBUTING
+.I CONTRIBUTING.md
 in the libpcap source tree root.
diff --git a/pcap.c b/pcap.c
index 942c472..ed8570a 100644
--- a/pcap.c
+++ b/pcap.c
@@ -53,7 +53,6 @@
 #include <netinet/in.h>
 #endif /* _WIN32 */
 
-#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -62,11 +61,9 @@
 #endif
 #include <fcntl.h>
 #include <errno.h>
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#else
-#define INT_MAX		2147483647
-#endif
+
+#include "diag-control.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -96,7 +93,7 @@
 #include "pcap-tc.h"
 #endif /* HAVE_TC_API */
 
-#ifdef PCAP_SUPPORT_USB
+#ifdef PCAP_SUPPORT_LINUX_USBMON
 #include "pcap-usb-linux.h"
 #endif
 
@@ -124,56 +121,201 @@
 #include "pcap-rdmasniff.h"
 #endif
 
+#ifdef PCAP_SUPPORT_DPDK
+#include "pcap-dpdk.h"
+#endif
+
+#ifdef HAVE_AIRPCAP_API
+#include "pcap-airpcap.h"
+#endif
+
 #ifdef _WIN32
 /*
  * DllMain(), required when built as a Windows DLL.
+ *
+ * To quote the WSAStartup() documentation:
+ *
+ *   The WSAStartup function typically leads to protocol-specific helper
+ *   DLLs being loaded. As a result, the WSAStartup function should not
+ *   be called from the DllMain function in a application DLL. This can
+ *   potentially cause deadlocks.
+ *
+ * and the WSACleanup() documentation:
+ *
+ *   The WSACleanup function typically leads to protocol-specific helper
+ *   DLLs being unloaded. As a result, the WSACleanup function should not
+ *   be called from the DllMain function in a application DLL. This can
+ *   potentially cause deadlocks.
+ *
+ * So we don't initialize Winsock here.  pcap_init() should be called
+ * to initialize pcap on both UN*X and Windows; it will initialize
+ * Winsock on Windows.  (It will also be initialized as needed if
+ * pcap_init() hasn't been called.)
  */
 BOOL WINAPI DllMain(
-  HANDLE hinstDLL,
-  DWORD dwReason,
-  LPVOID lpvReserved
+  HANDLE hinstDLL _U_,
+  DWORD dwReason _U_,
+  LPVOID lpvReserved _U_
 )
 {
 	return (TRUE);
 }
 
 /*
- * Start WinSock.
- * Exported in case some applications using WinPcap called it,
- * even though it wasn't exported.
+ * Start Winsock.
+ * Internal routine.
  */
-int
-wsockinit(void)
+static int
+internal_wsockinit(char *errbuf)
 {
 	WORD wVersionRequested;
 	WSADATA wsaData;
 	static int err = -1;
 	static int done = 0;
+	int status;
 
 	if (done)
 		return (err);
 
-	wVersionRequested = MAKEWORD( 1, 1);
-	err = WSAStartup( wVersionRequested, &wsaData );
-	atexit ((void(*)(void))WSACleanup);
+	/*
+	 * Versions of Windows that don't support Winsock 2.2 are
+	 * too old for us.
+	 */
+	wVersionRequested = MAKEWORD(2, 2);
+	status = WSAStartup(wVersionRequested, &wsaData);
 	done = 1;
-
-	if ( err != 0 )
-		err = -1;
+	if (status != 0) {
+		if (errbuf != NULL) {
+			pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+			    status, "WSAStartup() failed");
+		}
+		return (err);
+	}
+	atexit ((void(*)(void))WSACleanup);
+	err = 0;
 	return (err);
 }
 
 /*
+ * Exported in case some applications using WinPcap/Npcap called it,
+ * even though it wasn't exported.
+ */
+int
+wsockinit(void)
+{
+	return (internal_wsockinit(NULL));
+}
+
+/*
  * This is the exported function; new programs should call this.
+ * *Newer* programs should call pcap_init().
  */
 int
 pcap_wsockinit(void)
 {
-       return (wsockinit());
+	return (internal_wsockinit(NULL));
 }
 #endif /* _WIN32 */
 
 /*
+ * Do whatever initialization is needed for libpcap.
+ *
+ * The argument specifies whether we use the local code page or UTF-8
+ * for strings; on UN*X, we just assume UTF-8 in places where the encoding
+ * would matter, whereas, on Windows, we use the local code page for
+ * PCAP_CHAR_ENC_LOCAL and UTF-8 for PCAP_CHAR_ENC_UTF_8.
+ *
+ * On Windows, we also disable the hack in pcap_create() to deal with
+ * being handed UTF-16 strings, because if the user calls this they're
+ * explicitly declaring that they will either be passing local code
+ * page strings or UTF-8 strings, so we don't need to allow UTF-16LE
+ * strings to be passed.  For good measure, on Windows *and* UN*X,
+ * we disable pcap_lookupdev(), to prevent anybody from even
+ * *trying* to pass the result of pcap_lookupdev() - which might be
+ * UTF-16LE on Windows, for ugly compatibility reasons - to pcap_create()
+ * or pcap_open_live() or pcap_open().
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int pcap_new_api;		/* pcap_lookupdev() always fails */
+int pcap_utf_8_mode;		/* Strings should be in UTF-8. */
+
+int
+pcap_init(unsigned int opts, char *errbuf)
+{
+	static int initialized;
+
+	/*
+	 * Don't allow multiple calls that set different modes; that
+	 * may mean a library is initializing pcap in one mode and
+	 * a program using that library, or another library used by
+	 * that program, is initializing it in another mode.
+	 */
+	switch (opts) {
+
+	case PCAP_CHAR_ENC_LOCAL:
+		/* Leave "UTF-8 mode" off. */
+		if (initialized) {
+			if (pcap_utf_8_mode) {
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "Multiple pcap_init calls with different character encodings");
+				return (-1);
+			}
+		}
+		break;
+
+	case PCAP_CHAR_ENC_UTF_8:
+		/* Turn on "UTF-8 mode". */
+		if (initialized) {
+			if (!pcap_utf_8_mode) {
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "Multiple pcap_init calls with different character encodings");
+				return (-1);
+			}
+		}
+		pcap_utf_8_mode = 1;
+		break;
+
+	default:
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
+		return (-1);
+	}
+
+	/*
+	 * Turn the appropriate mode on for error messages; those routines
+	 * are also used in rpcapd, which has no access to pcap's internal
+	 * UTF-8 mode flag, so we have to call a routine to set its
+	 * UTF-8 mode flag.
+	 */
+	pcap_fmt_set_encoding(opts);
+
+	if (initialized) {
+		/*
+		 * Nothing more to do; for example, on Windows, we've
+		 * already initialized Winsock.
+		 */
+		return (0);
+	}
+
+#ifdef _WIN32
+	/*
+	 * Now set up Winsock.
+	 */
+	if (internal_wsockinit(errbuf) == -1) {
+		/* Failed. */
+		return (-1);
+	}
+#endif
+
+	/*
+	 * We're done.
+	 */
+	initialized = 1;
+	pcap_new_api = 1;
+	return (0);
+}
+
+/*
  * String containing the library version.
  * Not explicitly exported via a header file - the right API to use
  * is pcap_lib_version() - but some programs included it, so we
@@ -186,76 +328,166 @@
 PCAP_API char pcap_version[];
 PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
 
-static int
-pcap_not_initialized(pcap_t *pcap)
+static void
+pcap_set_not_initialized_message(pcap_t *pcap)
 {
 	if (pcap->activated) {
 		/* A module probably forgot to set the function pointer */
-		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+		(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 		    "This operation isn't properly handled by that device");
-		return (PCAP_ERROR);
+		return;
 	}
 	/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "This handle hasn't been activated yet");
+}
+
+static int
+pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
+    u_char *user _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, int size _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_getnonblock_not_initialized(pcap_t *pcap)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
+{
+	pcap_set_not_initialized_message(pcap);
 	/* this means 'not initialized' */
 	return (PCAP_ERROR_NOT_ACTIVATED);
 }
 
 #ifdef _WIN32
-static void *
-pcap_not_initialized_ptr(pcap_t *pcap)
+static struct pcap_stat *
+pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
 {
-	if (pcap->activated) {
-		/* A module probably forgot to set the function pointer */
-		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-		    "This operation isn't properly handled by that device");
-		return (NULL);
-	}
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-	    "This handle hasn't been activated yet");
+	pcap_set_not_initialized_message(pcap);
 	return (NULL);
 }
 
+static int
+pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	/* this means 'not initialized' */
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
 static HANDLE
 pcap_getevent_not_initialized(pcap_t *pcap)
 {
-	if (pcap->activated) {
-		/* A module probably forgot to set the function pointer */
-		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-		    "This operation isn't properly handled by that device");
-		return (INVALID_HANDLE_VALUE);
-	}
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-	    "This handle hasn't been activated yet");
+	pcap_set_not_initialized_message(pcap);
 	return (INVALID_HANDLE_VALUE);
 }
 
-static u_int
-pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
+static int
+pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+    void *data _U_, size_t *lenp _U_)
 {
-	if (pcap->activated) {
-		/* A module probably forgot to set the function pointer */
-		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-		    "This operation isn't properly handled by that device");
-		return (0);
-	}
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-	    "This handle hasn't been activated yet");
+	pcap_set_not_initialized_message(pcap);
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+    const void *data _U_, size_t *lenp _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static u_int
+pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue _U_,
+    int sync _U_)
+{
+	pcap_set_not_initialized_message(pcap);
 	return (0);
 }
 
+static int
+pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
+    int maxpacks _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
+{
+	pcap_set_not_initialized_message(pcap);
+	return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
 static PAirpcapHandle
 pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
 {
-	if (pcap->activated) {
-		/* A module probably forgot to set the function pointer */
-		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-		    "This operation isn't properly handled by that device");
-		return (NULL);
-	}
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
-	    "This handle hasn't been activated yet");
+	pcap_set_not_initialized_message(pcap);
 	return (NULL);
 }
 #endif
@@ -296,8 +528,17 @@
 	if (p->tstamp_type_count == 0) {
 		/*
 		 * We don't support multiple time stamp types.
+		 * That means the only type we support is PCAP_TSTAMP_HOST;
+		 * set up a list containing only that type.
 		 */
-		*tstamp_typesp = NULL;
+		*tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
+		if (*tstamp_typesp == NULL) {
+			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+			    errno, "malloc");
+			return (PCAP_ERROR);
+		}
+		**tstamp_typesp = PCAP_TSTAMP_HOST;
+		return (1);
 	} else {
 		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
 		    p->tstamp_type_count);
@@ -308,8 +549,8 @@
 		}
 		(void)memcpy(*tstamp_typesp, p->tstamp_type_list,
 		    sizeof(**tstamp_typesp) * p->tstamp_type_count);
+		return (p->tstamp_type_count);
 	}
-	return (p->tstamp_type_count);
 }
 
 /*
@@ -436,7 +677,7 @@
 #ifdef PCAP_SUPPORT_BT_MONITOR
 	{ bt_monitor_findalldevs, bt_monitor_create },
 #endif
-#ifdef PCAP_SUPPORT_USB
+#ifdef PCAP_SUPPORT_LINUX_USBMON
 	{ usb_findalldevs, usb_create },
 #endif
 #ifdef PCAP_SUPPORT_NETFILTER
@@ -451,6 +692,12 @@
 #ifdef PCAP_SUPPORT_RDMASNIFF
 	{ rdmasniff_findalldevs, rdmasniff_create },
 #endif
+#ifdef PCAP_SUPPORT_DPDK
+	{ pcap_dpdk_findalldevs, pcap_dpdk_create },
+#endif
+#ifdef HAVE_AIRPCAP_API
+	{ airpcap_findalldevs, airpcap_create },
+#endif
 	{ NULL, NULL }
 };
 
@@ -530,39 +777,26 @@
  *
  * 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.)
+ * below that set if the interface isn't up, the bit below that
+ * set if the interface is a loopback interface, and the bit below
+ * that set if it's the "any" interface.
+ *
+ * Note: we don't sort by unit number because 1) not all interfaces have
+ * a unit number (systemd, for example, might assign interface names
+ * based on the interface's MAC address or on the physical location of
+ * the adapter's connector), and 2) if the name does end with a simple
+ * unit number, it's not a global property of the interface, it's only
+ * useful as a sort key for device names with the same prefix, so xyz0
+ * shouldn't necessarily sort before abc2.  This means that interfaces
+ * with the same figure of merit will be sorted by the order in which
+ * the mechanism from which we're getting the interfaces supplies them.
  */
 static u_int
 get_figure_of_merit(pcap_if_t *dev)
 {
-	const char *cp;
 	u_int n;
 
-	if (strcmp(dev->name, "any") == 0) {
-		/*
-		 * Give the "any" device an artificially high instance
-		 * number, so it shows up after all other non-loopback
-		 * interfaces.
-		 */
-		n = 0x1FFFFFFF;	/* 29 all-1 bits */
-	} else {
-		/*
-		 * A number at the end of the device name string is
-		 * assumed to be an instance number.  Add 1 to the
-		 * instance number, and use 0 for "no instance
-		 * number", so we don't put "no instance number"
-		 * devices and "instance 0" devices together.
-		 */
-		cp = dev->name + strlen(dev->name) - 1;
-		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
-			cp--;
-		if (*cp >= '0' && *cp <= '9')
-			n = atoi(cp) + 1;
-		else
-			n = 0;
-	}
+	n = 0;
 	if (!(dev->flags & PCAP_IF_RUNNING))
 		n |= 0x80000000;
 	if (!(dev->flags & PCAP_IF_UP))
@@ -589,6 +823,13 @@
 	if (dev->flags & PCAP_IF_LOOPBACK)
 		n |= 0x10000000;
 
+	/*
+	 * Sort the "any" device before loopback and disconnected devices,
+	 * but after all other devices.
+	 */
+	if (strcmp(dev->name, "any") == 0)
+		n |= 0x08000000;
+
 	return (n);
 }
 
@@ -659,7 +900,7 @@
 	 * Get the description for the interface.
 	 */
 	memset(&ifrdesc, 0, sizeof ifrdesc);
-	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+	pcap_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
 	s = socket(AF_INET, SOCK_DGRAM, 0);
 	if (s >= 0) {
 #ifdef __FreeBSD__
@@ -710,7 +951,7 @@
 		}
 #endif /* __FreeBSD__ */
 		close(s);
-		if (description != NULL && strlen(description) == 0) {
+		if (description != NULL && description[0] == '\0') {
 			/*
 			 * Description is empty, so discard it.
 			 */
@@ -741,20 +982,13 @@
 				 * OK, it's a valid number that's not
 				 * bigger than INT_MAX.  Construct
 				 * a description from it.
+				 * (If that fails, we don't worry about
+				 * it, we just return NULL.)
 				 */
-				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);
+				if (pcap_asprintf(&description,
+				    "USB bus number %ld", busnum) == -1) {
+					/* Failed. */
+					description = NULL;
 				}
 			}
 		}
@@ -796,7 +1030,7 @@
 	 * see if it looks like a loopback device.
 	 */
 	if (name[0] == 'l' && name[1] == 'o' &&
-	    (isdigit((unsigned char)(name[2])) || name[2] == '\0')
+	    (PCAP_ISDIGIT(name[2]) || name[2] == '\0'))
 		pcap_flags |= PCAP_IF_LOOPBACK;
 #endif
 #ifdef IFF_UP
@@ -1277,6 +1511,22 @@
 	static char device[IF_NAMESIZE + 1];
 	char *ret;
 
+	/*
+	 * We disable this in "new API" mode, because 1) in WinPcap/Npcap,
+	 * it may return UTF-16 strings, for backwards-compatibility
+	 * reasons, and we're also disabling the hack to make that work,
+	 * for not-going-past-the-end-of-a-string reasons, and 2) we
+	 * want its behavior to be consistent.
+	 *
+	 * In addition, it's not thread-safe, so we've marked it as
+	 * deprecated.
+	 */
+	if (pcap_new_api) {
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "pcap_lookupdev() is deprecated and is not supported in programs calling pcap_init()");
+		return (NULL);
+	}
+
 	if (pcap_findalldevs(&alldevs, errbuf) == -1)
 		return (NULL);
 
@@ -1292,14 +1542,14 @@
 		 * on the list, there aren't any non-loopback devices,
 		 * so why not just supply it as the default device?
 		 */
-		(void)strlcpy(errbuf, "no suitable device found",
+		(void)pcap_strlcpy(errbuf, "no suitable device found",
 		    PCAP_ERRBUF_SIZE);
 		ret = NULL;
 	} else {
 		/*
 		 * Return the name of the first device on the list.
 		 */
-		(void)strlcpy(device, alldevs->name, sizeof(device));
+		(void)pcap_strlcpy(device, alldevs->name, sizeof(device));
 		ret = device;
 	}
 
@@ -1340,7 +1590,7 @@
 #ifdef PCAP_SUPPORT_BT
 	    || strstr(device, "bluetooth") != NULL
 #endif
-#ifdef PCAP_SUPPORT_USB
+#ifdef PCAP_SUPPORT_LINUX_USBMON
 	    || strstr(device, "usbmon") != NULL
 #endif
 #ifdef HAVE_SNF_API
@@ -1350,6 +1600,9 @@
 	    || strncmp(device, "netmap:", 7) == 0
 	    || strncmp(device, "vale", 4) == 0
 #endif
+#ifdef PCAP_SUPPORT_DPDK
+	    || strncmp(device, "dpdk:", 5) == 0
+#endif
 	    ) {
 		*netp = *maskp = 0;
 		return 0;
@@ -1366,10 +1619,10 @@
 	/* XXX Work around Linux kernel bug */
 	ifr.ifr_addr.sa_family = AF_INET;
 #endif
-	(void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
 		if (errno == EADDRNOTAVAIL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: no IPv4 address assigned", device);
 		} else {
 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
@@ -1385,7 +1638,7 @@
 	/* XXX Work around Linux kernel bug */
 	ifr.ifr_addr.sa_family = AF_INET;
 #endif
-	(void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "SIOCGIFNETMASK: %s", device);
@@ -1402,7 +1655,7 @@
 		else if (IN_CLASSC(*netp))
 			*maskp = IN_CLASSC_NET;
 		else {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "inet class for 0x%x unknown", *netp);
 			return (-1);
 		}
@@ -1575,13 +1828,14 @@
 	 * the pathname.
 	 */
 	if (pcap_strcasecmp(scheme, "file") == 0) {
-		*schemep = scheme;
 		*pathp = strdup(colonp + 3);
 		if (*pathp == NULL) {
 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 			    errno, "malloc");
+			free(scheme);
 			return (-1);
 		}
+		*schemep = scheme;
 		return (0);
 	}
 
@@ -1593,7 +1847,8 @@
 	 *
 	 * XXX - %-escaping?
 	 */
-	if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
+	if ((pcap_strcasecmp(scheme, "rpcap") == 0 ||
+	    pcap_strcasecmp(scheme, "rpcaps") == 0) &&
 	    strchr(colonp + 3, '/') == NULL) {
 		/*
 		 * Local device.
@@ -1684,14 +1939,19 @@
 			 * Treat verything up to the closing square
 			 * bracket as the IP-Literal; we don't worry
 			 * about whether it's a valid IPv6address or
-			 * IPvFuture.
+			 * IPvFuture (or an IPv4address, for that
+			 * matter, just in case we get handed a
+			 * URL with an IPv4 IP-Literal, of the sort
+			 * that pcap_createsrcstr() used to generate,
+			 * and that pcap_parsesrcstr(), in the original
+			 * WinPcap code, accepted).
 			 */
 			bracketp = strchr(parsep, ']');
 			if (bracketp == NULL) {
 				/*
 				 * There's no closing square bracket.
 				 */
-				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+				snprintf(ebuf, PCAP_ERRBUF_SIZE,
 				    "IP-literal in URL doesn't end with ]");
 				free(userinfo);
 				free(authority);
@@ -1704,7 +1964,7 @@
 				 * There's extra crud after the
 				 * closing square bracketn.
 				 */
-				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+				snprintf(ebuf, PCAP_ERRBUF_SIZE,
 				    "Extra text after IP-literal in URL");
 				free(userinfo);
 				free(authority);
@@ -1799,24 +2059,26 @@
 }
 
 int
-pcap_createsrcstr(char *source, int type, const char *host, const char *port,
-    const char *name, char *errbuf)
+pcap_createsrcstr_ex(char *source, int type, const char *host, const char *port,
+    const char *name, unsigned char uses_ssl, char *errbuf)
 {
 	switch (type) {
 
 	case PCAP_SRC_FILE:
-		strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+		pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
 		if (name != NULL && *name != '\0') {
-			strlcat(source, name, PCAP_BUF_SIZE);
+			pcap_strlcat(source, name, PCAP_BUF_SIZE);
 			return (0);
 		} else {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			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);
+		pcap_strlcpy(source,
+		    (uses_ssl ? "rpcaps://" : PCAP_SRC_IF_STRING),
+		    PCAP_BUF_SIZE);
 		if (host != NULL && *host != '\0') {
 			if (strchr(host, ':') != NULL) {
 				/*
@@ -1824,47 +2086,55 @@
 				 * probably an IPv6 address, and needs to
 				 * be included in square brackets.
 				 */
-				strlcat(source, "[", PCAP_BUF_SIZE);
-				strlcat(source, host, PCAP_BUF_SIZE);
-				strlcat(source, "]", PCAP_BUF_SIZE);
+				pcap_strlcat(source, "[", PCAP_BUF_SIZE);
+				pcap_strlcat(source, host, PCAP_BUF_SIZE);
+				pcap_strlcat(source, "]", PCAP_BUF_SIZE);
 			} else
-				strlcat(source, host, PCAP_BUF_SIZE);
+				pcap_strlcat(source, host, PCAP_BUF_SIZE);
 
 			if (port != NULL && *port != '\0') {
-				strlcat(source, ":", PCAP_BUF_SIZE);
-				strlcat(source, port, PCAP_BUF_SIZE);
+				pcap_strlcat(source, ":", PCAP_BUF_SIZE);
+				pcap_strlcat(source, port, PCAP_BUF_SIZE);
 			}
 
-			strlcat(source, "/", PCAP_BUF_SIZE);
+			pcap_strlcat(source, "/", PCAP_BUF_SIZE);
 		} else {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "The host name cannot be NULL.");
 			return (-1);
 		}
 
 		if (name != NULL && *name != '\0')
-			strlcat(source, name, PCAP_BUF_SIZE);
+			pcap_strlcat(source, name, PCAP_BUF_SIZE);
 
 		return (0);
 
 	case PCAP_SRC_IFLOCAL:
-		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+		pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
 
 		if (name != NULL && *name != '\0')
-			strlcat(source, name, PCAP_BUF_SIZE);
+			pcap_strlcat(source, name, PCAP_BUF_SIZE);
 
 		return (0);
 
 	default:
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		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)
+pcap_createsrcstr(char *source, int type, const char *host, const char *port,
+    const char *name, char *errbuf)
+{
+	return (pcap_createsrcstr_ex(source, type, host, port, name, 0, errbuf));
+}
+
+int
+pcap_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
+    char *name, unsigned char *uses_ssl, char *errbuf)
 {
 	char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
 
@@ -1875,6 +2145,8 @@
 		*port = '\0';
 	if (name)
 		*name = '\0';
+	if (uses_ssl)
+		*uses_ssl = 0;
 
 	/* Parse the source string */
 	if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
@@ -1890,7 +2162,7 @@
 		 * Local device.
 		 */
 		if (name && tmppath)
-			strlcpy(name, tmppath, PCAP_BUF_SIZE);
+			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
 		if (type)
 			*type = PCAP_SRC_IFLOCAL;
 		free(tmppath);
@@ -1900,24 +2172,32 @@
 		return (0);
 	}
 
-	if (strcmp(scheme, "rpcap") == 0) {
+	int is_rpcap = 0;
+	if (strcmp(scheme, "rpcaps") == 0) {
+		is_rpcap = 1;
+		if (uses_ssl) *uses_ssl = 1;
+	} else if (strcmp(scheme, "rpcap") == 0) {
+		is_rpcap = 1;
+	}
+
+	if (is_rpcap) {
 		/*
-		 * rpcap://
+		 * rpcap[s]://
 		 *
 		 * pcap_parse_source() has already handled the case of
-		 * rpcap://device
+		 * rpcap[s]://device
 		 */
 		if (host && tmphost) {
 			if (tmpuserinfo)
-				pcap_snprintf(host, PCAP_BUF_SIZE, "%s@%s",
+				snprintf(host, PCAP_BUF_SIZE, "%s@%s",
 				    tmpuserinfo, tmphost);
 			else
-				strlcpy(host, tmphost, PCAP_BUF_SIZE);
+				pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
 		}
 		if (port && tmpport)
-			strlcpy(port, tmpport, PCAP_BUF_SIZE);
+			pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
 		if (name && tmppath)
-			strlcpy(name, tmppath, PCAP_BUF_SIZE);
+			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
 		if (type)
 			*type = PCAP_SRC_IFREMOTE;
 		free(tmppath);
@@ -1933,7 +2213,7 @@
 		 * file://
 		 */
 		if (name && tmppath)
-			strlcpy(name, tmppath, PCAP_BUF_SIZE);
+			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
 		if (type)
 			*type = PCAP_SRC_FILE;
 		free(tmppath);
@@ -1949,7 +2229,7 @@
 	 * as a local device.
 	 */
 	if (name)
-		strlcpy(name, source, PCAP_BUF_SIZE);
+		pcap_strlcpy(name, source, PCAP_BUF_SIZE);
 	if (type)
 		*type = PCAP_SRC_IFLOCAL;
 	free(tmppath);
@@ -1959,6 +2239,13 @@
 	free(scheme);
 	return (0);
 }
+
+int
+pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
+    char *name, char *errbuf)
+{
+	return (pcap_parsesrcstr_ex(source, type, host, port, name, NULL, errbuf));
+}
 #endif
 
 pcap_t *
@@ -1981,13 +2268,42 @@
 	else {
 #ifdef _WIN32
 		/*
-		 * If the string appears to be little-endian UCS-2/UTF-16,
-		 * convert it to ASCII.
+		 * On Windows, for backwards compatibility reasons,
+		 * pcap_lookupdev() returns a pointer to a sequence of
+		 * pairs of UTF-16LE device names and local code page
+		 * description strings.
 		 *
-		 * XXX - to UTF-8 instead?  Or report an error if any
-		 * character isn't ASCII?
+		 * This means that if a program uses pcap_lookupdev()
+		 * to get a default device, and hands that to an API
+		 * that opens devices, we'll get handed a UTF-16LE
+		 * string, not a string in the local code page.
+		 *
+		 * To work around that, we check whether the string
+		 * looks as if it might be a UTF-16LE string and, if
+		 * so, convert it back to the local code page's
+		 * extended ASCII.
+		 *
+		 * We disable that check in "new API" mode, because:
+		 *
+		 *   1) You *cannot* reliably detect whether a
+		 *   string is UTF-16LE or not; "a" could either
+		 *   be a one-character ASCII string or the first
+		 *   character of a UTF-16LE string.
+		 *
+		 *   2) Doing that test can run past the end of
+		 *   the string, if it's a 1-character ASCII
+		 *   string
+		 *
+		 * This particular version of this heuristic dates
+		 * back to WinPcap 4.1.1; PacketOpenAdapter() does
+		 * uses the same heuristic, with the exact same
+		 * vulnerability.
+		 *
+		 * That's why we disable this in "new API" mode.
+		 * We keep it around in legacy mode for backwards
+		 * compatibility.
 		 */
-		if (device[0] != '\0' && device[1] == '\0') {
+		if (!pcap_new_api && device[0] != '\0' && device[1] == '\0') {
 			size_t length;
 
 			length = wcslen((wchar_t *)device);
@@ -1999,7 +2315,7 @@
 				return (NULL);
 			}
 
-			pcap_snprintf(device_str, length + 1, "%ws",
+			snprintf(device_str, length + 1, "%ws",
 			    (const wchar_t *)device);
 		} else
 #endif
@@ -2077,25 +2393,25 @@
 	 * an activated pcap_t to point to a routine that returns
 	 * a "this isn't activated" error.
 	 */
-	p->read_op = (read_op_t)pcap_not_initialized;
-	p->inject_op = (inject_op_t)pcap_not_initialized;
-	p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
-	p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
-	p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
-	p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
-	p->stats_op = (stats_op_t)pcap_not_initialized;
+	p->read_op = pcap_read_not_initialized;
+	p->inject_op = pcap_inject_not_initialized;
+	p->setfilter_op = pcap_setfilter_not_initialized;
+	p->setdirection_op = pcap_setdirection_not_initialized;
+	p->set_datalink_op = pcap_set_datalink_not_initialized;
+	p->getnonblock_op = pcap_getnonblock_not_initialized;
+	p->stats_op = pcap_stats_not_initialized;
 #ifdef _WIN32
-	p->stats_ex_op = (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->stats_ex_op = pcap_stats_ex_not_initialized;
+	p->setbuff_op = pcap_setbuff_not_initialized;
+	p->setmode_op = pcap_setmode_not_initialized;
+	p->setmintocopy_op = pcap_setmintocopy_not_initialized;
 	p->getevent_op = pcap_getevent_not_initialized;
-	p->oid_get_request_op = (oid_get_request_op_t)pcap_not_initialized;
-	p->oid_set_request_op = (oid_set_request_op_t)pcap_not_initialized;
+	p->oid_get_request_op = pcap_oid_get_request_not_initialized;
+	p->oid_set_request_op = pcap_oid_set_request_not_initialized;
 	p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
-	p->setuserbuffer_op = (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->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
+	p->live_dump_op = pcap_live_dump_not_initialized;
+	p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
 	p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
 #endif
 
@@ -2111,36 +2427,31 @@
 	 * be used for pcap_next()/pcap_next_ex().
 	 */
 	p->oneshot_callback = pcap_oneshot;
+
+	/*
+	 * Default breakloop operation - implementations can override
+	 * this, but should call pcap_breakloop_common() before doing
+	 * their own logic.
+	 */
+	p->breakloop_op = pcap_breakloop_common;
 }
 
 static pcap_t *
-pcap_alloc_pcap_t(char *ebuf, size_t size)
+pcap_alloc_pcap_t(char *ebuf, size_t total_size, size_t private_offset)
 {
 	char *chunk;
 	pcap_t *p;
 
 	/*
-	 * Allocate a chunk of memory big enough for a pcap_t
-	 * plus a structure following it of size "size".  The
-	 * structure following it is a private data structure
-	 * for the routines that handle this pcap_t.
-	 *
-	 * The structure following it must be aligned on
-	 * the appropriate alignment boundary for this platform.
-	 * We align on an 8-byte boundary as that's probably what
-	 * at least some platforms do, even with 32-bit integers,
-	 * and because we can't be sure that some values won't
-	 * require 8-byte alignment even on platforms with 32-bit
-	 * integers.
+	 * total_size is the size of a structure containing a pcap_t
+	 * followed by a private structure.
 	 */
-#define PCAP_T_ALIGNED_SIZE	((sizeof(pcap_t) + 7) & ~0x7)
-	chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
+	chunk = calloc(total_size, 1);
 	if (chunk == NULL) {
 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
 		    errno, "malloc");
 		return (NULL);
 	}
-	memset(chunk, 0, PCAP_T_ALIGNED_SIZE + size);
 
 	/*
 	 * Get a pointer to the pcap_t at the beginning.
@@ -2157,26 +2468,24 @@
 #endif /* MSDOS */
 #endif /* _WIN32 */
 
-	if (size == 0) {
-		/* No private data was requested. */
-		p->priv = NULL;
-	} else {
-		/*
-		 * Set the pointer to the private data; that's the structure
-		 * of size "size" following the pcap_t.
-		 */
-		p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
-	}
+	/*
+	 * private_offset is the offset, in bytes, of the private
+	 * data from the beginning of the structure.
+	 *
+	 * Set the pointer to the private data; that's private_offset
+	 * bytes past the pcap_t.
+	 */
+	p->priv = (void *)(chunk + private_offset);
 
 	return (p);
 }
 
 pcap_t *
-pcap_create_common(char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t total_size, size_t private_offset)
 {
 	pcap_t *p;
 
-	p = pcap_alloc_pcap_t(ebuf, size);
+	p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
 	if (p == NULL)
 		return (NULL);
 
@@ -2228,7 +2537,7 @@
 pcap_check_activated(pcap_t *p)
 {
 	if (p->activated) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
 			" operation on activated capture");
 		return (-1);
 	}
@@ -2436,7 +2745,7 @@
 			 * handle errors other than PCAP_ERROR, return the
 			 * error message corresponding to the status.
 			 */
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
 			    pcap_statustostr(status));
 		}
 
@@ -2461,6 +2770,16 @@
 	int srctype;
 
 	/*
+	 * A null device name is equivalent to the "any" device -
+	 * which might not be supported on this platform, but
+	 * this means that you'll get a "not supported" error
+	 * rather than, say, a crash when we try to dereference
+	 * the null pointer.
+	 */
+	if (device == NULL)
+		device = "any";
+
+	/*
 	 * Retrofit - we have to make older applications compatible with
 	 * remote capture.
 	 * So we're calling pcap_open_remote() from here; this is a very
@@ -2484,7 +2803,7 @@
 		    NULL, errbuf));
 	}
 	if (srctype == PCAP_SRC_FILE) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
 		return (NULL);
 	}
 	if (srctype == PCAP_SRC_IFLOCAL) {
@@ -2531,26 +2850,26 @@
 	return (p);
 fail:
 	if (status == PCAP_ERROR)
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
-		    p->errbuf);
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
+		    PCAP_ERRBUF_SIZE - 3, p->errbuf);
 	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
 	    status == PCAP_ERROR_PERM_DENIED ||
 	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", device,
-		    pcap_statustostr(status), p->errbuf);
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
+		    pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
 	else
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
 		    pcap_statustostr(status));
 	pcap_close(p);
 	return (NULL);
 }
 
 pcap_t *
-pcap_open_offline_common(char *ebuf, size_t size)
+pcap_open_offline_common(char *ebuf, size_t total_size, size_t private_offset)
 {
 	pcap_t *p;
 
-	p = pcap_alloc_pcap_t(ebuf, size);
+	p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
 	if (p == NULL)
 		return (NULL);
 
@@ -2601,7 +2920,7 @@
 void
 pcap_breakloop(pcap_t *p)
 {
-	p->break_loop = 1;
+	p->breakloop_op(p);
 }
 
 int
@@ -2724,11 +3043,11 @@
 unsupported:
 	dlt_name = pcap_datalink_val_to_name(dlt);
 	if (dlt_name != NULL) {
-		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) snprintf(p->errbuf, sizeof(p->errbuf),
 		    "%s is not one of the DLTs supported by this device",
 		    dlt_name);
 	} else {
-		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) snprintf(p->errbuf, sizeof(p->errbuf),
 		    "DLT %d is not one of the DLTs supported by this device",
 		    dlt);
 	}
@@ -2841,7 +3160,7 @@
 	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(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"),
@@ -2850,7 +3169,7 @@
 	DLT_CHOICE(FRELAY, "Frame Relay"),
 	DLT_CHOICE(LOOP, "OpenBSD loopback"),
 	DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
-	DLT_CHOICE(LINUX_SLL, "Linux cooked"),
+	DLT_CHOICE(LINUX_SLL, "Linux cooked v1"),
 	DLT_CHOICE(LTALK, "Localtalk"),
 	DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
 	DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
@@ -2884,7 +3203,7 @@
 	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_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"),
@@ -2908,10 +3227,11 @@
 	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(IPMB_KONTRON, "IPMB with Kontron pseudo-header"),
 	DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
 	DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
 	DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
+	DLT_CHOICE(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-header"),
 	DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
 	DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
 	DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
@@ -2968,6 +3288,19 @@
 	DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
 	DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
 	DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
+	DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
+	DLT_CHOICE(OPENVIZSLA, "OpenVizsla USB"),
+	DLT_CHOICE(EBHSCR, "Elektrobit High Speed Capture and Replay (EBHSCR)"),
+	DLT_CHOICE(VPP_DISPATCH, "VPP graph dispatch tracer"),
+	DLT_CHOICE(DSA_TAG_BRCM, "Broadcom tag"),
+	DLT_CHOICE(DSA_TAG_BRCM_PREPEND, "Broadcom tag (prepended)"),
+	DLT_CHOICE(IEEE802_15_4_TAP, "IEEE 802.15.4 with pseudo-header"),
+	DLT_CHOICE(DSA_TAG_DSA, "Marvell DSA"),
+	DLT_CHOICE(DSA_TAG_EDSA, "Marvell EDSA"),
+	DLT_CHOICE(ELEE, "ELEE lawful intercept packets"),
+	DLT_CHOICE(Z_WAVE_SERIAL, "Z-Wave serial frames between host and chip"),
+	DLT_CHOICE(USB_2_0, "USB 2.0/1.1/1.0 as transmitted over the cable"),
+	DLT_CHOICE(ATSC_ALP, "ATSC Link-Layer Protocol packets"),
 	DLT_CHOICE_SENTINEL
 };
 
@@ -3007,6 +3340,21 @@
 	return (NULL);
 }
 
+const char *
+pcap_datalink_val_to_description_or_dlt(int dlt)
+{
+        static char unkbuf[40];
+        const char *description;
+
+        description = pcap_datalink_val_to_description(dlt);
+        if (description != NULL) {
+                return description;
+        } else {
+                (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
+                return unkbuf;
+        }
+}
+
 struct tstamp_type_choice {
 	const char *name;
 	const char *description;
@@ -3019,6 +3367,7 @@
 	{ "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
 	{ "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
 	{ "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
+	{ "host_hiprec_unsynced", "Host, high precision, not synced with system time", PCAP_TSTAMP_HOST_HIPREC_UNSYNCED },
 	{ NULL, NULL, 0 }
 };
 
@@ -3104,18 +3453,33 @@
 	return (p->rfile);
 }
 
+#ifdef _WIN32
 int
 pcap_fileno(pcap_t *p)
 {
-#ifndef _WIN32
-	return (p->fd);
-#else
-	if (p->handle != INVALID_HANDLE_VALUE)
+	if (p->handle != INVALID_HANDLE_VALUE) {
+		/*
+		 * This is a bogus and now-deprecated API; we
+		 * squelch the narrowing warning for the cast
+		 * from HANDLE to DWORD.  If Windows programmmers
+		 * need to get at the HANDLE for a pcap_t, *if*
+		 * there is one, they should request such a
+		 * routine (and be prepared for it to return
+		 * INVALID_HANDLE_VALUE).
+		 */
+DIAG_OFF_NARROWING
 		return ((int)(DWORD)p->handle);
-	else
+DIAG_ON_NARROWING
+	} else
 		return (PCAP_ERROR);
-#endif
 }
+#else /* _WIN32 */
+int
+pcap_fileno(pcap_t *p)
+{
+	return (p->fd);
+}
+#endif /* _WIN32 */
 
 #if !defined(_WIN32) && !defined(MSDOS)
 int
@@ -3124,7 +3488,7 @@
 	return (p->selectable_fd);
 }
 
-struct timeval *
+const struct timeval *
 pcap_get_required_select_timeout(pcap_t *p)
 {
 	return (p->required_select_timeout);
@@ -3159,7 +3523,7 @@
 		 * We copy the error message to errbuf, so callers
 		 * can find it in either place.
 		 */
-		strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
+		pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
 	}
 	return (ret);
 }
@@ -3203,7 +3567,7 @@
 		 * We copy the error message to errbuf, so callers
 		 * can find it in either place.
 		 */
-		strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
+		pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
 	}
 	return (ret);
 }
@@ -3239,35 +3603,6 @@
 }
 #endif
 
-#ifdef _WIN32
-/*
- * Generate a string for a Win32-specific error (i.e. an error generated when
- * calling a Win32 API).
- * For errors occurred during standard C calls, we still use pcap_strerror()
- */
-void
-pcap_win32_err_to_str(DWORD error, char *errbuf)
-{
-	size_t errlen;
-	char *p;
-
-	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
-	    PCAP_ERRBUF_SIZE, NULL);
-
-	/*
-	 * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
-	 * message.  Get rid of it.
-	 */
-	errlen = strlen(errbuf);
-	if (errlen >= 2) {
-		errbuf[errlen - 1] = '\0';
-		errbuf[errlen - 2] = '\0';
-	}
-	p = strchr(errbuf, '\0');
-	pcap_snprintf (p, PCAP_ERRBUF_SIZE+1-(p-errbuf), " (%lu)", error);
-}
-#endif
-
 /*
  * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
  */
@@ -3323,7 +3658,7 @@
 	case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
 		return ("That device doesn't support that time stamp precision");
 	}
-	(void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
 	return(ebuf);
 }
 
@@ -3339,7 +3674,7 @@
 	errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
 
 	if (err != 0) /* err = 0 if successful */
-		strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
+		pcap_strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
 	return (errbuf);
 #else
 	return (strerror(errnum));
@@ -3351,7 +3686,7 @@
 
 	if ((unsigned int)errnum < sys_nerr)
 		return ((char *)sys_errlist[errnum]);
-	(void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
+	(void)snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
 	return (errbuf);
 #endif
 }
@@ -3372,11 +3707,29 @@
 pcap_setdirection(pcap_t *p, pcap_direction_t d)
 {
 	if (p->setdirection_op == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Setting direction is not implemented on this platform");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Setting direction is not supported on this device");
 		return (-1);
-	} else
-		return (p->setdirection_op(p, d));
+	} else {
+		switch (d) {
+
+		case PCAP_D_IN:
+		case PCAP_D_OUT:
+		case PCAP_D_INOUT:
+			/*
+			 * Valid direction.
+			 */
+			return (p->setdirection_op(p, d));
+
+		default:
+			/*
+			 * Invalid direction.
+			 */
+			snprintf(p->errbuf, sizeof(p->errbuf),
+			    "Invalid direction");
+			return (-1);
+		}
+	}
 }
 
 int
@@ -3508,7 +3861,7 @@
 
 	handle = p->get_airpcap_handle_op(p);
 	if (handle == NULL) {
-		(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+		(void)snprintf(p->errbuf, sizeof(p->errbuf),
 		    "This isn't an AirPcap device");
 	}
 	return (handle);
@@ -3545,8 +3898,28 @@
 {
 	struct pcap *handle;
 
-	while ((handle = pcaps_to_close) != NULL)
+	while ((handle = pcaps_to_close) != NULL) {
 		pcap_close(handle);
+
+		/*
+		 * If a pcap module adds a pcap_t to the "close all"
+		 * list by calling pcap_add_to_pcaps_to_close(), it
+		 * must have a cleanup routine that removes it from the
+		 * list, by calling pcap_remove_from_pcaps_to_close(),
+		 * and must make that cleanup routine the cleanup_op
+		 * for the pcap_t.
+		 *
+		 * That means that, after pcap_close() - which calls
+		 * the cleanup_op for the pcap_t - the pcap_t must
+		 * have been removed from the list, so pcaps_to_close
+		 * must not be equal to handle.
+		 *
+		 * We check for that, and abort if handle is still
+		 * at the head of the list, to prevent infinite loops.
+		 */
+		if (pcaps_to_close == handle)
+			abort();
+	}
 }
 
 int
@@ -3561,7 +3934,7 @@
 			/*
 			 * "atexit()" failed; let our caller know.
 			 */
-			strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
+			pcap_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
 			return (0);
 		}
 		did_atexit = 1;
@@ -3604,6 +3977,13 @@
 }
 
 void
+pcap_breakloop_common(pcap_t *p)
+{
+	p->break_loop = 1;
+}
+
+
+void
 pcap_cleanup_live_common(pcap_t *p)
 {
 	if (p->buffer != NULL) {
@@ -3644,6 +4024,12 @@
 int
 pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
 {
+	if (size <= 0) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "The number of bytes to be sent must be positive");
+		return (PCAP_ERROR);
+	}
+
 	if (p->inject_op(p, buf, size) == -1)
 		return (-1);
 	return (0);
@@ -3656,7 +4042,23 @@
 int
 pcap_inject(pcap_t *p, const void *buf, size_t size)
 {
-	return (p->inject_op(p, buf, size));
+	/*
+	 * We return the number of bytes written, so the number of
+	 * bytes to write must fit in an int.
+	 */
+	if (size > INT_MAX) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "More than %d bytes cannot be injected", INT_MAX);
+		return (PCAP_ERROR);
+	}
+
+	if (size == 0) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "The number of bytes to be injected must not be zero");
+		return (PCAP_ERROR);
+	}
+
+	return (p->inject_op(p, buf, (int)size));
 }
 
 void
@@ -3669,6 +4071,81 @@
 }
 
 /*
+ * Helpers for safely loding code at run time.
+ * Currently Windows-only.
+ */
+#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 modules from the application folder).
+// This solves the DLL Hijacking issue discovered in August 2010:
+//
+// https://blog.rapid7.com/2010/08/23/exploiting-dll-hijacking-flaws/
+// https://blog.rapid7.com/2010/08/23/application-dll-load-hijacking/
+// (the purported Rapid7 blog post link in the first of those two links
+// is broken; the second of those links works.)
+//
+// If any links there are broken from all the content shuffling Rapid&
+// did, see archived versions of the posts at their original homes, at
+//
+// https://web.archive.org/web/20110122175058/http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+// https://web.archive.org/web/20100828112111/http://blog.rapid7.com/?p=5325
+//
+pcap_code_handle_t
+pcap_load_code(const char *name)
+{
+	/*
+	 * XXX - should this work in UTF-16LE rather than in the local
+	 * ANSI code page?
+	 */
+	CHAR path[MAX_PATH];
+	CHAR fullFileName[MAX_PATH];
+	UINT res;
+	HMODULE hModule = NULL;
+
+	do
+	{
+		res = GetSystemDirectoryA(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 + strlen(name) + 1 < MAX_PATH) {
+			memcpy(fullFileName, path, res * sizeof(TCHAR));
+			fullFileName[res] = '\\';
+			memcpy(&fullFileName[res + 1], name, (strlen(name) + 1) * sizeof(TCHAR));
+
+			hModule = LoadLibraryA(fullFileName);
+		} else
+			SetLastError(ERROR_INSUFFICIENT_BUFFER);
+
+	} while(FALSE);
+
+	return hModule;
+}
+
+pcap_funcptr_t
+pcap_find_function(pcap_code_handle_t code, const char *func)
+{
+	return (GetProcAddress(code, func));
+}
+#endif
+
+/*
  * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
  * data for the packet, check whether the packet passes the filter.
  * Returns the return value of the filter program, which will be zero if
@@ -3681,7 +4158,7 @@
 	const struct bpf_insn *fcode = fp->bf_insns;
 
 	if (fcode != NULL)
-		return (bpf_filter(fcode, pkt, h->len, h->caplen));
+		return (pcap_filter(fcode, pkt, h->len, h->caplen));
 	else
 		return (0);
 }
@@ -3689,7 +4166,7 @@
 static int
 pcap_can_set_rfmon_dead(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
 	return (PCAP_ERROR);
 }
@@ -3698,15 +4175,15 @@
 pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
     u_char *user _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Packets aren't available from a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static int
-pcap_inject_dead(pcap_t *p, const void *buf _U_, size_t size _U_)
+pcap_inject_dead(pcap_t *p, const void *buf _U_, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Packets can't be sent on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -3714,7 +4191,7 @@
 static int
 pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "A filter cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -3722,7 +4199,7 @@
 static int
 pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The packet direction cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -3730,7 +4207,7 @@
 static int
 pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -3738,7 +4215,7 @@
 static int
 pcap_getnonblock_dead(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
 	return (-1);
 }
@@ -3746,7 +4223,7 @@
 static int
 pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
 	return (-1);
 }
@@ -3754,40 +4231,40 @@
 static int
 pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 #ifdef _WIN32
-struct pcap_stat *
+static struct pcap_stat *
 pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from a pcap_open_dead pcap_t");
 	return (NULL);
 }
 
 static int
-pcap_setbuff_dead(pcap_t *p, int dim)
+pcap_setbuff_dead(pcap_t *p, int dim _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static int
-pcap_setmode_dead(pcap_t *p, int mode)
+pcap_setmode_dead(pcap_t *p, int mode _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "impossible to set mode on a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static int
-pcap_setmintocopy_dead(pcap_t *p, int size)
+pcap_setmintocopy_dead(pcap_t *p, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -3795,7 +4272,7 @@
 static HANDLE
 pcap_getevent_dead(pcap_t *p)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "A pcap_open_dead pcap_t has no event handle");
 	return (INVALID_HANDLE_VALUE);
 }
@@ -3804,7 +4281,7 @@
 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,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "An OID get request cannot be performed on a pcap_open_dead pcap_t");
 	return (PCAP_ERROR);
 }
@@ -3813,45 +4290,47 @@
 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,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "An OID set request cannot be performed on a pcap_open_dead pcap_t");
 	return (PCAP_ERROR);
 }
 
 static u_int
-pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
+pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue _U_,
+    int sync _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Packets cannot be transmitted on a pcap_open_dead pcap_t");
 	return (0);
 }
 
 static int
-pcap_setuserbuffer_dead(pcap_t *p, int size)
+pcap_setuserbuffer_dead(pcap_t *p, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The user buffer cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static int
-pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
+pcap_live_dump_dead(pcap_t *p, char *filename _U_, int maxsize _U_,
+    int maxpacks _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static int
-pcap_live_dump_ended_dead(pcap_t *p, int sync)
+pcap_live_dump_ended_dead(pcap_t *p, int sync _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
 	return (-1);
 }
 
 static PAirpcapHandle
-pcap_get_airpcap_handle_dead(pcap_t *p)
+pcap_get_airpcap_handle_dead(pcap_t *p _U_)
 {
 	return (NULL);
 }
diff --git a/pcap/bpf.h b/pcap/bpf.h
index 1a953a9..ccb93cc 100644
--- a/pcap/bpf.h
+++ b/pcap/bpf.h
@@ -58,10 +58,21 @@
  * I don't have earlier versions available to check), or QNX-style
  * multiple-include protection (as per GitHub pull request #394).
  *
+ * We trust that they will define structures and macros and types in
+ * a fashion that's source-compatible and binary-compatible with our
+ * definitions.
+ *
  * We do not check for BPF_MAJOR_VERSION, as that's defined by
  * <linux/filter.h>, which is directly or indirectly included in some
  * programs that also include pcap.h, and <linux/filter.h> doesn't
- * define stuff we need.
+ * define stuff we need.  We *do* protect against <linux/filter.h>
+ * defining various macros for BPF code itself; <linux/filter.h> says
+ *
+ *	Try and keep these values and structures similar to BSD, especially
+ *	the BPF code definitions which need to match so you can share filters
+ *
+ * so we trust that it will define them in a fashion that's source-compatible
+ * and binary-compatible with our definitions.
  *
  * This also provides our own multiple-include protection.
  */
@@ -108,6 +119,8 @@
 
 #include <pcap/dlt.h>
 
+#ifndef __LINUX_FILTER_H__
+
 /*
  * The instruction encodings.
  *
@@ -228,6 +241,8 @@
 /*				0xf0	reserved */
 /*				0xf8	reserved */
 
+#endif /* __LINUX_FILTER_H__ */
+
 /*
  * The instruction data structure.
  */
@@ -238,15 +253,7 @@
 	bpf_u_int32 k;
 };
 
-/*
- * Auxiliary data, for use when interpreting a filter intended for the
- * Linux kernel when the kernel rejects the filter (requiring us to
- * run it in userland).  It contains VLAN tag information.
- */
-struct bpf_aux_data {
-	u_short vlan_tag_present;
-	u_short vlan_tag;
-};
+#ifndef __LINUX_FILTER_H__
 
 /*
  * Macros for insn array initializers.
@@ -254,9 +261,19 @@
 #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
 #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
 
-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 *);
+#endif /* __LINUX_FILTER_H__ */
+
+PCAP_AVAILABLE_0_4
+PCAP_API u_int	bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+
+PCAP_AVAILABLE_0_6
+PCAP_API int	bpf_validate(const struct bpf_insn *f, int len);
+
+PCAP_AVAILABLE_0_4
+PCAP_API char	*bpf_image(const struct bpf_insn *, int);
+
+PCAP_AVAILABLE_0_6
+PCAP_API void	bpf_dump(const struct bpf_program *, int);
 
 /*
  * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
diff --git a/pcap/compiler-tests.h b/pcap/compiler-tests.h
index 5e17853..a69c2b0 100644
--- a/pcap/compiler-tests.h
+++ b/pcap/compiler-tests.h
@@ -38,7 +38,7 @@
 /*
  * This was introduced by Clang:
  *
- *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *     https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
  *
  * in some version (which version?); it has been picked up by GCC 5.0.
  */
@@ -160,4 +160,4 @@
 	(__HP_aCC >= ((major)*10000 + (minor)*100))
 #endif
 
-#endif /* lib_pcap_funcattrs_h */
+#endif /* lib_pcap_compiler_tests_h */
diff --git a/pcap/dlt.h b/pcap/dlt.h
index 535fd50..eaba34f 100644
--- a/pcap/dlt.h
+++ b/pcap/dlt.h
@@ -136,7 +136,7 @@
 #define DLT_PFSYNC	18
 #endif
 
-#define DLT_ATM_CLIP	19	/* Linux Classical-IP over ATM */
+#define DLT_ATM_CLIP	19	/* Linux Classical IP over ATM */
 
 /*
  * Apparently Redback uses this for its SmartEdge 400/800.  I hope
@@ -246,7 +246,7 @@
  */
 
 /*
- * This is for Linux cooked sockets.
+ * Linux cooked sockets.
  */
 #define DLT_LINUX_SLL	113
 
@@ -465,7 +465,7 @@
 #define DLT_DOCSIS		143
 
 /*
- * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Linux-IrDA packets. Protocol defined at https://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.
@@ -473,7 +473,7 @@
  * 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
+ * decoding is dependent on the direction of the packet (incoming or
  * outgoing).
  * When/if other platform implement IrDA capture, we may revisit the
  * issue and define a real DLT_IRDA...
@@ -565,7 +565,7 @@
  * 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 first byte of the PPP header (0xff03) is modified to accommodate
  * the direction - 0x00 = IN, 0x01 = OUT.
  */
 #define DLT_PPP_PPPD		166
@@ -607,7 +607,7 @@
 /*
  * 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
+ * https://www.endace.com/support/EndaceRecordFormat.pdf) in front of
  * the link-layer header.
  */
 #define DLT_ERF_ETH		175	/* Ethernet */
@@ -750,7 +750,7 @@
 
 /*
  * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ * (https://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
  */
 #define DLT_SITA		196
 
@@ -769,11 +769,20 @@
 #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>.
+ * IPMB packet for IPMI, beginning with a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - this used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header.  We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value.  If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
  */
-#define DLT_IPMB		199
+#define DLT_IPMB_KONTRON	199
 
 /*
  * Juniper-private data link type, as per request from
@@ -805,15 +814,37 @@
 #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>.
+ * PPP, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host", non-zero (any non-zero value) means "sent by
+ * this host" - as per Will Barker <w.barker@zen.co.uk>.
+ *
+ * Don't confuse this with DLT_PPP_WITH_DIRECTION, which is an old
+ * name for what is now called DLT_PPP_PPPD.
  */
-#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 */
+#define DLT_PPP_WITH_DIR	204
+
+/*
+ * Cisco HDLC, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host", non-zero (any non-zero value) means
+ * "sent by this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_C_HDLC_WITH_DIR	205
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_FRELAY_WITH_DIR	206
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_LAPB_WITH_DIR	207
 
 /*
  * 208 is reserved for an as-yet-unspecified proprietary link-layer
@@ -834,7 +865,7 @@
 
 /*
  * Media Oriented Systems Transport (MOST) bus for multimedia
- * transport - http://www.mostcooperation.com/ - as requested
+ * transport - https://www.mostcooperation.com/ - as requested
  * by Hannes Kaelber <hannes.kaelber@x2e.de>.
  */
 #define DLT_MOST		211
@@ -1020,16 +1051,16 @@
 /*
  * Raw D-Bus:
  *
- *	http://www.freedesktop.org/wiki/Software/dbus
+ *	https://www.freedesktop.org/wiki/Software/dbus
  *
  * messages:
  *
- *	http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *	https://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
+ *	https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
  *
  * Requested by Martin Vidner <martin@vidner.net>.
  */
@@ -1047,7 +1078,7 @@
  * DVB-CI (DVB Common Interface for communication between a PC Card
  * module and a DVB receiver).  See
  *
- *	http://www.kaiser.cx/pcap-dvbci.html
+ *	https://www.kaiser.cx/pcap-dvbci.html
  *
  * for the specification.
  *
@@ -1336,9 +1367,9 @@
 
 /*
  * per: Stefanha at gmail.com for
- *   http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ *   https://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
  * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
- * for: http://qemu-project.org/Features/VirtioVsock
+ * for: https://qemu-project.org/Features/VirtioVsock
  */
 #define DLT_VSOCK               271
 
@@ -1350,7 +1381,7 @@
 /*
  * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
  *   per: bruno.verstuyft at excentis.com
- *        http://www.xra31.com/xra-header
+ *        https://www.xra31.com/xra-header
  */
 #define DLT_DOCSIS31_XRA31	273
 
@@ -1362,12 +1393,94 @@
 
 /*
  * DisplayPort AUX channel monitoring data as specified by VESA
- * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ * DisplayPort(DP) Standard preceded by a pseudo-header.
  *    per dirk.eibach at gdsys.cc
  */
 #define DLT_DISPLAYPORT_AUX	275
 
 /*
+ * Linux cooked sockets v2.
+ */
+#define DLT_LINUX_SLL2	276
+
+/*
+ * Sercos Monitor, per Manuel Jacob <manuel.jacob at steinbeis-stg.de>
+ */
+#define DLT_SERCOS_MONITOR 277
+
+/*
+ * OpenVizsla http://openvizsla.org is open source USB analyzer hardware.
+ * It consists of FPGA with attached USB phy and FTDI chip for streaming
+ * the data to the host PC.
+ *
+ * Current OpenVizsla data encapsulation format is described here:
+ * https://github.com/matwey/libopenvizsla/wiki/OpenVizsla-protocol-description
+ *
+ */
+#define DLT_OPENVIZSLA	        278
+
+/*
+ * The Elektrobit High Speed Capture and Replay (EBHSCR) protocol is produced
+ * by a PCIe Card for interfacing high speed automotive interfaces.
+ *
+ * The specification for this frame format can be found at:
+ *   https://www.elektrobit.com/ebhscr
+ *
+ * for Guenter.Ebermann at elektrobit.com
+ *
+ */
+#define DLT_EBHSCR	        279
+
+/*
+ * The https://fd.io vpp graph dispatch tracer produces pcap trace files
+ * in the format documented here:
+ * https://fdio-vpp.readthedocs.io/en/latest/gettingstarted/developers/vnet.html#graph-dispatcher-pcap-tracing
+ */
+#define DLT_VPP_DISPATCH	280
+
+/*
+ * Broadcom Ethernet switches (ROBO switch) 4 bytes proprietary tagging format.
+ */
+#define DLT_DSA_TAG_BRCM	281
+#define DLT_DSA_TAG_BRCM_PREPEND	282
+
+/*
+ * IEEE 802.15.4 with pseudo-header and optional meta-data TLVs, PHY payload
+ * exactly as it appears in the spec (no padding, no nothing), and FCS if
+ * specified by FCS Type TLV;  requested by James Ko <jck@exegin.com>.
+ * Specification at https://github.com/jkcko/ieee802.15.4-tap
+ */
+#define DLT_IEEE802_15_4_TAP    283
+
+/*
+ * Marvell (Ethertype) Distributed Switch Architecture proprietary tagging format.
+ */
+#define DLT_DSA_TAG_DSA		284
+#define DLT_DSA_TAG_EDSA	285
+
+/*
+ * Payload of lawful intercept packets using the ELEE protocol;
+ * https://socket.hr/draft-dfranusic-opsawg-elee-00.xml
+ * https://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://socket.hr/draft-dfranusic-opsawg-elee-00.xml&modeAsFormat=html/ascii
+ */
+#define DLT_ELEE		286
+
+/*
+ * Serial frames transmitted between a host and a Z-Wave chip.
+ */
+#define DLT_Z_WAVE_SERIAL	287
+
+/*
+ * USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
+ */
+#define DLT_USB_2_0		288
+
+/*
+ * ATSC Link-Layer Protocol (A/330) packets.
+ */
+#define DLT_ATSC_ALP		289
+
+/*
  * 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
@@ -1377,7 +1490,7 @@
 #ifdef DLT_MATCHING_MAX
 #undef DLT_MATCHING_MAX
 #endif
-#define DLT_MATCHING_MAX	275	/* highest value in the "matching" range */
+#define DLT_MATCHING_MAX	289	/* highest value in the "matching" range */
 
 /*
  * DLT and savefile link type values are split into a class and
diff --git a/pcap/funcattrs.h b/pcap/funcattrs.h
index a8b1932..cdc083d 100644
--- a/pcap/funcattrs.h
+++ b/pcap/funcattrs.h
@@ -147,6 +147,70 @@
 #define PCAP_API	PCAP_API_DEF extern
 
 /*
+ * Definitions to 1) indicate what version of libpcap first had a given
+ * API and 2) allow upstream providers whose build environments allow
+ * APIs to be designated as "first available in this release" to do so
+ * by appropriately defining them.
+ *
+ * Yes, that's you, Apple. :-)  Please define PCAP_AVAILABLE_MACOS()
+ * as necessary to make various APIs "weak exports" to make it easier
+ * for software that's distributed in binary form and that uses libpcap
+ * to run on multiple macOS versions and use new APIs when available.
+ * (Yes, such third-party software exists - Wireshark provides binary
+ * packages for macOS, for example.  tcpdump doesn't count, as that's
+ * provided by Apple, so each release can come with a version compiled
+ * to use the APIs present in that release.)
+ *
+ * We don't define it ourselves because, if you're building and
+ * installing libpcap on macOS yourself, the APIs will be available
+ * no matter what OS version you're installing it on.
+ *
+ * For other platforms, we don't define them, leaving it up to
+ * others to do so based on their OS versions, if appropriate.
+ *
+ * We start with libpcap 0.4, as that was the last LBL release, and
+ * I've never seen earlier releases.
+ */
+#ifdef __APPLE__
+#define PCAP_AVAILABLE_MACOS(v)	/* define to say "first appears in v" */
+#define PCAP_AVAILABLE_0_4	PCAP_AVAILABLE_MACOS(10.0) /* Did any version of Mac OS X ship with this? */
+#define PCAP_AVAILABLE_0_5	PCAP_AVAILABLE_MACOS(10.0) /* Did any version of Mac OS X ship with this? */
+#define PCAP_AVAILABLE_0_6	PCAP_AVAILABLE_MACOS(10.1)
+#define PCAP_AVAILABLE_0_7	PCAP_AVAILABLE_MACOS(10.4)
+#define PCAP_AVAILABLE_0_8	PCAP_AVAILABLE_MACOS(10.4)
+#define PCAP_AVAILABLE_0_9	PCAP_AVAILABLE_MACOS(10.5)
+#define PCAP_AVAILABLE_1_0	PCAP_AVAILABLE_MACOS(10.6)
+/* #define PCAP_AVAILABLE_1_1	no routines added to the API */
+#define PCAP_AVAILABLE_1_2	PCAP_AVAILABLE_MACOS(10.9)
+/* #define PCAP_AVAILABLE_1_3	no routines added to the API */
+/* #define PCAP_AVAILABLE_1_4	no routines added to the API */
+#define PCAP_AVAILABLE_1_5	PCAP_AVAILABLE_MACOS(10.10)
+/* #define PCAP_AVAILABLE_1_6	no routines added to the API */
+#define PCAP_AVAILABLE_1_7	PCAP_AVAILABLE_MACOS(10.12)
+#define PCAP_AVAILABLE_1_8	PCAP_AVAILABLE_MACOS(10.13) /* only Windows adds routines to the API; XXX - what version first had it? */
+#define PCAP_AVAILABLE_1_9	PCAP_AVAILABLE_MACOS(10.13)
+#define PCAP_AVAILABLE_1_10	/* not released yet, so not in macOS yet */
+#else /* __APPLE__ */
+#define PCAP_AVAILABLE_0_4
+#define PCAP_AVAILABLE_0_5
+#define PCAP_AVAILABLE_0_6
+#define PCAP_AVAILABLE_0_7
+#define PCAP_AVAILABLE_0_8
+#define PCAP_AVAILABLE_0_9
+#define PCAP_AVAILABLE_1_0
+/* #define PCAP_AVAILABLE_1_1	no routines added to the API */
+#define PCAP_AVAILABLE_1_2
+/* #define PCAP_AVAILABLE_1_3	no routines added to the API */
+/* #define PCAP_AVAILABLE_1_4	no routines added to the API */
+#define PCAP_AVAILABLE_1_5
+/* #define PCAP_AVAILABLE_1_6	no routines added to the API */
+#define PCAP_AVAILABLE_1_7
+#define PCAP_AVAILABLE_1_8
+#define PCAP_AVAILABLE_1_9
+#define PCAP_AVAILABLE_1_10
+#endif /* __APPLE__ */
+
+/*
  * PCAP_NORETURN, before a function declaration, means "this function
  * never returns".  (It must go before the function declaration, e.g.
  * "extern PCAP_NORETURN func(...)" rather than after the function
@@ -164,10 +228,11 @@
     || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
     || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
   /*
-   * Compiler with support for __attribute((noreturn)), or GCC 2.5 and
-   * later, or Solaris Studio 12 (Sun C 5.9) and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?), or
-   * HP aCC A.06.10 and later.
+   * Compiler with support for __attribute((noreturn)), or GCC 2.5 or
+   * later, or some compiler asserting compatibility with GCC 2.5 or
+   * later, or Solaris Studio 12 (Sun C 5.9) or later, or IBM XL C 10.1
+   * or later (do any earlier versions of XL C support this?), or HP aCC
+   * A.06.10 or later.
    */
   #define PCAP_NORETURN __attribute((noreturn))
   #define PCAP_NORETURN_DEF __attribute((noreturn))
@@ -193,7 +258,8 @@
     || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
     || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
   /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * Compiler with support for it, or GCC 2.3 or later, or some compiler
+   * asserting compatibility with GCC 2.3 or later, or IBM XL C 10.1
    * and later (do any earlier versions of XL C support this?),
    * or HP aCC A.06.10 and later.
    */
@@ -216,7 +282,7 @@
     || PCAP_IS_AT_LEAST_SUNC_VERSION(5,13)
   /*
    * Compiler that supports __has_attribute and __attribute__((deprecated)),
-   * or GCC 4.5 and later, or Sun/Oracle C 12.4 (Sun C 5.13) or later.
+   * or GCC 4.5 or later, or Sun/Oracle C 12.4 (Sun C 5.13) or later.
    *
    * Those support __attribute__((deprecated(msg))) (we assume, perhaps
    * incorrectly, that anything that supports __has_attribute() is
@@ -231,10 +297,10 @@
    * __attribute__((deprecated(msg))).
    */
   #define PCAP_DEPRECATED(func, msg)	__attribute__((deprecated))
-#elif (defined(_MSC_VER) && (_MSC_VER >= 1500)) && !defined(BUILDING_PCAP)
+#elif defined(_MSC_VER) && !defined(BUILDING_PCAP)
   /*
-   * MSVC from Visual Studio 2008 or later, and we're not building
-   * libpcap itself.
+   * MSVC, and we're not building libpcap itself; it's VS 2015
+   * or later, so we have the deprecated pragma.
    *
    * If we *are* building libpcap, we don't want this, as it'll warn
    * us even if we *define* the function.
@@ -249,11 +315,7 @@
  */
 #ifdef _MSC_VER
  #include <sal.h>
- #if _MSC_VER > 1400
-  #define PCAP_FORMAT_STRING(p) _Printf_format_string_ p
- #else
-  #define PCAP_FORMAT_STRING(p) __format_string p
- #endif
+ #define PCAP_FORMAT_STRING(p) _Printf_format_string_ p
 #else
  #define PCAP_FORMAT_STRING(p) p
 #endif
diff --git a/pcap/namedb.h b/pcap/namedb.h
index c66846d..34a0ae7 100644
--- a/pcap/namedb.h
+++ b/pcap/namedb.h
@@ -59,7 +59,8 @@
 PCAP_API u_char *pcap_ether_hostton(const char*);
 PCAP_API u_char *pcap_ether_aton(const char *);
 
-PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
+PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *)
+PCAP_DEPRECATED(pcap_nametoaddr, "this is not reentrant; use 'pcap_nametoaddrinfo' instead");
 PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
 PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
 
diff --git a/pcap/pcap-inttypes.h b/pcap/pcap-inttypes.h
index af2c23c..1cfa0bf 100644
--- a/pcap/pcap-inttypes.h
+++ b/pcap/pcap-inttypes.h
@@ -32,86 +32,49 @@
 #define pcap_pcap_inttypes_h
 
 /*
- * Get the integer types and PRi[doux]64 values from C99 <inttypes.h>
- * defined, by hook or by crook.
+ * If we're compiling with Visual Studio, make sure we have at least
+ * VS 2015 or later, so we have sufficient C99 support.
+ *
+ * XXX - verify that we have at least C99 support on UN*Xes?
+ *
+ * What about MinGW or various DOS toolchains?  We're currently assuming
+ * sufficient C99 support there.
  */
 #if defined(_MSC_VER)
   /*
-   * Compiler is MSVC.
+   * Compiler is MSVC.  Make sure we have VS 2015 or later.
    */
-  #if _MSC_VER >= 1800
-    /*
-     * VS 2013 or newer; we have <inttypes.h>.
-     */
-    #include <inttypes.h>
-  #else
-    /*
-     * Earlier VS; we have to define this stuff ourselves.
-     */
-    typedef unsigned char uint8_t;
-    typedef signed char int8_t;
-    typedef unsigned short uint16_t;
-    typedef signed short int16_t;
-    typedef unsigned int uint32_t;
-    typedef signed int int32_t;
-    #ifdef _MSC_EXTENSIONS
-      typedef unsigned _int64 uint64_t;
-      typedef _int64 int64_t;
-    #else /* _MSC_EXTENSIONS */
-      typedef unsigned long long uint64_t;
-      typedef long long int64_t;
-    #endif
+  #if _MSC_VER < 1900
+    #error "Building libpcap requires VS 2015 or later"
   #endif
-
-  /*
-   * These may be defined by <inttypes.h>.
-   *
-   * XXX - for MSVC, we always want the _MSC_EXTENSIONS versions.
-   * What about other compilers?  If, as the MinGW Web site says MinGW
-   * does, the other compilers just use Microsoft's run-time library,
-   * then they should probably use the _MSC_EXTENSIONS even if the
-   * compiler doesn't define _MSC_EXTENSIONS.
-   *
-   * XXX - we currently aren't using any of these, but this allows
-   * their use in the future.
-   */
-  #ifndef PRId64
-    #ifdef _MSC_EXTENSIONS
-      #define PRId64	"I64d"
-    #else
-      #define PRId64	"lld"
-    #endif
-  #endif /* PRId64 */
-
-  #ifndef PRIo64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIo64	"I64o"
-    #else
-      #define PRIo64	"llo"
-    #endif
-  #endif /* PRIo64 */
-
-  #ifndef PRIx64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIx64	"I64x"
-    #else
-      #define PRIx64	"llx"
-    #endif
-  #endif
-
-  #ifndef PRIu64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIu64	"I64u"
-    #else
-      #define PRIu64	"llu"
-    #endif
-  #endif
-#elif defined(__MINGW32__) || !defined(_WIN32)
-  /*
-   * Compiler is MinGW or target is UN*X or MS-DOS.  Just use
-   * <inttypes.h>.
-   */
-  #include <inttypes.h>
 #endif
 
+/*
+ * Include <inttypes.h> to get the integer types and PRi[doux]64 values
+ * defined.
+ *
+ * If the compiler is MSVC, we require VS 2015 or newer, so we
+ * have <inttypes.h> - and support for %zu in the formatted
+ * printing functions.
+ *
+ * If the compiler is MinGW, we assume we have <inttypes.h> - and
+ * support for %zu in the formatted printing functions.
+ *
+ * If the target is UN*X, we assume we have a C99-or-later development
+ * environment, and thus have <inttypes.h> - and support for %zu in
+ * the formatted printing functions.
+ *
+ * If the target is MS-DOS, we assume we have <inttypes.h> - and support
+ * for %zu in the formatted printing functions.
+ *
+ * I.e., assume we have <inttypes.h> and that it suffices.
+ */
+
+/*
+ * XXX - somehow make sure we have enough C99 support with other
+ * compilers and support libraries?
+ */
+
+#include <inttypes.h>
+
 #endif /* pcap/pcap-inttypes.h */
diff --git a/pcap/pcap.h b/pcap/pcap.h
index bc87b3f..8182bef 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -69,6 +69,49 @@
 #ifndef lib_pcap_pcap_h
 #define lib_pcap_pcap_h
 
+/*
+ * Some software that uses libpcap/WinPcap/Npcap defines _MSC_VER before
+ * includeing pcap.h if it's not defined - and it defines it to 1500.
+ * (I'm looking at *you*, lwIP!)
+ *
+ * Attempt to detect this, and undefine _MSC_VER so that we can *reliably*
+ * use it to know what compiler is being used and, if it's Visual Studio,
+ * what version is being used.
+ */
+#if defined(_MSC_VER)
+  /*
+   * We assume here that software such as that doesn't define _MSC_FULL_VER
+   * as well and that it defines _MSC_VER with a value > 1200.
+   *
+   * DO NOT BREAK THESE ASSUMPTIONS.  IF YOU FEEL YOU MUST DEFINE _MSC_VER
+   * WITH A COMPILER THAT'S NOT MICROSOFT'S C COMPILER, PLEASE CONTACT
+   * US SO THAT WE CAN MAKE IT SO THAT YOU DON'T HAVE TO DO THAT.  THANK
+   * YOU.
+   *
+   * OK, is _MSC_FULL_VER defined?
+   */
+  #if !defined(_MSC_FULL_VER)
+    /*
+     * According to
+     *
+     *    https://sourceforge.net/p/predef/wiki/Compilers/
+     *
+     * with "Visual C++ 6.0 Processor Pack"/Visual C++ 6.0 SP6 and
+     * later, _MSC_FULL_VER is defined, so either this is an older
+     * version of Visual C++ or it's not Visual C++ at all.
+     *
+     * For Visual C++ 6.0, _MSC_VER is defined as 1200.
+     */
+    #if _MSC_VER > 1200
+      /*
+       * If this is Visual C++, _MSC_FULL_VER should be defined, so we
+       * assume this isn't Visual C++, and undo the lie that it is.
+       */
+      #undef _MSC_VER
+    #endif
+  #endif
+#endif
+
 #include <pcap/funcattrs.h>
 
 #include <pcap/pcap-inttypes.h>
@@ -84,6 +127,8 @@
   #include <sys/time.h>
 #endif /* _WIN32/MSDOS/UN*X */
 
+#include <pcap/socket.h>	/* for SOCKET, as the active-mode rpcap APIs use it */
+
 #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
 #include <pcap/bpf.h>
 #endif
@@ -125,6 +170,7 @@
  * of the flags used in the printout phases of tcpdump.
  * Many fields here are 32 bit ints so compilers won't insert unwanted
  * padding; these files need to be interchangeable across architectures.
+ * Documentation: https://www.tcpdump.org/manpages/pcap-savefile.5.txt.
  *
  * Do not change the layout of this structure, in any way (this includes
  * changes that only affect the length of fields in this structure).
@@ -152,7 +198,7 @@
  *
  * Then supply the changes by forking the branch at
  *
- *	https://github.com/the-tcpdump-group/libpcap/issues
+ *	https://github.com/the-tcpdump-group/libpcap/tree/master
  *
  * and issuing a pull request, so that future versions of libpcap and
  * programs that use it (such as tcpdump) will be able to read your new
@@ -162,8 +208,8 @@
 	bpf_u_int32 magic;
 	u_short version_major;
 	u_short version_minor;
-	bpf_int32 thiszone;	/* gmt to local correction */
-	bpf_u_int32 sigfigs;	/* accuracy of timestamps */
+	bpf_int32 thiszone;	/* gmt to local correction; this is always 0 */
+	bpf_u_int32 sigfigs;	/* accuracy of timestamps; this is always 0 */
 	bpf_u_int32 snaplen;	/* max length saved portion of each pkt */
 	bpf_u_int32 linktype;	/* data link type (LINKTYPE_*) */
 };
@@ -199,7 +245,7 @@
 struct pcap_pkthdr {
 	struct timeval ts;	/* time stamp */
 	bpf_u_int32 caplen;	/* length of portion present */
-	bpf_u_int32 len;	/* length this packet (off wire) */
+	bpf_u_int32 len;	/* length of this packet (off wire) */
 };
 
 /*
@@ -319,35 +365,91 @@
 #define PCAP_NETMASK_UNKNOWN	0xffffffff
 
 /*
+ * Initialize pcap.  If this isn't called, pcap is initialized to
+ * a mode source-compatible and binary-compatible with older versions
+ * that lack this routine.
+ */
+
+/*
+ * Initialization options.
+ * All bits not listed here are reserved for expansion.
+ *
+ * On UNIX-like systems, the local character encoding is assumed to be
+ * UTF-8, so no character encoding transformations are done.
+ *
+ * On Windows, the local character encoding is the local ANSI code page.
+ */
+#define PCAP_CHAR_ENC_LOCAL	0x00000000U	/* strings are in the local character encoding */
+#define PCAP_CHAR_ENC_UTF_8	0x00000001U	/* strings are in UTF-8 */
+
+PCAP_AVAILABLE_1_10
+PCAP_API int	pcap_init(unsigned int, char *);
+
+/*
  * We're deprecating pcap_lookupdev() for various reasons (not
  * thread-safe, can behave weirdly with WinPcap).  Callers
  * should use pcap_findalldevs() and use the first device.
  */
+PCAP_AVAILABLE_0_4
 PCAP_API char	*pcap_lookupdev(char *)
 PCAP_DEPRECATED(pcap_lookupdev, "use 'pcap_findalldevs' and use the first device");
 
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
 
+PCAP_AVAILABLE_1_0
 PCAP_API pcap_t	*pcap_create(const char *, char *);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_set_snaplen(pcap_t *, int);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_set_promisc(pcap_t *, int);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_can_set_rfmon(pcap_t *);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_set_rfmon(pcap_t *, int);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_set_timeout(pcap_t *, int);
+
+PCAP_AVAILABLE_1_2
 PCAP_API int	pcap_set_tstamp_type(pcap_t *, int);
+
+PCAP_AVAILABLE_1_5
 PCAP_API int	pcap_set_immediate_mode(pcap_t *, int);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_set_buffer_size(pcap_t *, int);
+
+PCAP_AVAILABLE_1_5
 PCAP_API int	pcap_set_tstamp_precision(pcap_t *, int);
+
+PCAP_AVAILABLE_1_5
 PCAP_API int	pcap_get_tstamp_precision(pcap_t *);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_activate(pcap_t *);
 
+PCAP_AVAILABLE_1_2
 PCAP_API int	pcap_list_tstamp_types(pcap_t *, int **);
+
+PCAP_AVAILABLE_1_2
 PCAP_API void	pcap_free_tstamp_types(int *);
+
+PCAP_AVAILABLE_1_2
 PCAP_API int	pcap_tstamp_type_name_to_val(const char *);
+
+PCAP_AVAILABLE_1_2
 PCAP_API const char *pcap_tstamp_type_val_to_name(int);
+
+PCAP_AVAILABLE_1_2
 PCAP_API const char *pcap_tstamp_type_val_to_description(int);
 
 #ifdef __linux__
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_set_protocol_linux(pcap_t *, int);
 #endif
 
@@ -357,8 +459,7 @@
  *
  * A system that supports PCAP_TSTAMP_HOST is offering time stamps
  * provided by the host machine, rather than by the capture device,
- * but not committing to any characteristics of the time stamp;
- * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes.
+ * but not committing to any characteristics of the time stamp.
  *
  * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine,
  * that's low-precision but relatively cheap to fetch; it's normally done
@@ -366,10 +467,15 @@
  * fetch from system calls.
  *
  * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine,
- * that's high-precision; it might be more expensive to fetch.  It might
- * or might not be synchronized with the system clock, and might have
+ * that's high-precision; it might be more expensive to fetch.  It is
+ * synchronized with the system clock.
+ *
+ * PCAP_TSTAMP_HOST_HIPREC_UNSYNCED is a time stamp, provided by the host
+ * machine, that's high-precision; it might be more expensive to fetch.
+ * It is not synchronized with the system clock, and might have
  * problems with time stamps for packets received on different CPUs,
- * depending on the platform.
+ * depending on the platform.  It might be more likely to be strictly
+ * monotonic than PCAP_TSTAMP_HOST_HIPREC.
  *
  * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the
  * capture device; it's synchronized with the system clock.
@@ -389,11 +495,12 @@
  * the packet is received by the network adapter, due to batching
  * of interrupts for packet arrival, queueing delays, etc..
  */
-#define PCAP_TSTAMP_HOST		0	/* host-provided, unknown characteristics */
-#define PCAP_TSTAMP_HOST_LOWPREC	1	/* host-provided, low precision */
-#define PCAP_TSTAMP_HOST_HIPREC		2	/* host-provided, high precision */
-#define PCAP_TSTAMP_ADAPTER		3	/* device-provided, synced with the system clock */
-#define PCAP_TSTAMP_ADAPTER_UNSYNCED	4	/* device-provided, not synced with the system clock */
+#define PCAP_TSTAMP_HOST			0	/* host-provided, unknown characteristics */
+#define PCAP_TSTAMP_HOST_LOWPREC		1	/* host-provided, low precision, synced with the system clock */
+#define PCAP_TSTAMP_HOST_HIPREC			2	/* host-provided, high precision, synced with the system clock */
+#define PCAP_TSTAMP_ADAPTER			3	/* device-provided, synced with the system clock */
+#define PCAP_TSTAMP_ADAPTER_UNSYNCED		4	/* device-provided, not synced with the system clock */
+#define PCAP_TSTAMP_HOST_HIPREC_UNSYNCED	5	/* host-provided, high precision, not synced with the system clock */
 
 /*
  * Time stamp resolution types.
@@ -404,13 +511,25 @@
 #define PCAP_TSTAMP_PRECISION_MICRO	0	/* use timestamps with microsecond precision, default */
 #define PCAP_TSTAMP_PRECISION_NANO	1	/* use timestamps with nanosecond precision */
 
+PCAP_AVAILABLE_0_4
 PCAP_API pcap_t	*pcap_open_live(const char *, int, int, int, char *);
+
+PCAP_AVAILABLE_0_6
 PCAP_API pcap_t	*pcap_open_dead(int, int);
+
+PCAP_AVAILABLE_1_5
 PCAP_API pcap_t	*pcap_open_dead_with_tstamp_precision(int, int, u_int);
+
+PCAP_AVAILABLE_1_5
 PCAP_API pcap_t	*pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API pcap_t	*pcap_open_offline(const char *, char *);
+
 #ifdef _WIN32
+  PCAP_AVAILABLE_1_5
   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,
@@ -432,67 +551,200 @@
 	pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
   #endif
 #else /*_WIN32*/
+  PCAP_AVAILABLE_1_5
   PCAP_API pcap_t	*pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+
+  PCAP_AVAILABLE_0_9
   PCAP_API pcap_t	*pcap_fopen_offline(FILE *, char *);
 #endif /*_WIN32*/
 
+PCAP_AVAILABLE_0_4
 PCAP_API void	pcap_close(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int 	pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+
+PCAP_AVAILABLE_0_8
 PCAP_API void	pcap_breakloop(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_stats(pcap_t *, struct pcap_stat *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_setfilter(pcap_t *, struct bpf_program *);
+
+PCAP_AVAILABLE_0_9
 PCAP_API int 	pcap_setdirection(pcap_t *, pcap_direction_t);
+
+PCAP_AVAILABLE_0_7
 PCAP_API int	pcap_getnonblock(pcap_t *, char *);
+
+PCAP_AVAILABLE_0_7
 PCAP_API int	pcap_setnonblock(pcap_t *, int, char *);
+
+PCAP_AVAILABLE_0_9
 PCAP_API int	pcap_inject(pcap_t *, const void *, size_t);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int	pcap_sendpacket(pcap_t *, const u_char *, int);
+
+PCAP_AVAILABLE_1_0
 PCAP_API const char *pcap_statustostr(int);
+
+PCAP_AVAILABLE_0_4
 PCAP_API const char *pcap_strerror(int);
+
+PCAP_AVAILABLE_0_4
 PCAP_API char	*pcap_geterr(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API void	pcap_perror(pcap_t *, const char *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
 	    bpf_u_int32);
+
+PCAP_AVAILABLE_0_5
 PCAP_API int	pcap_compile_nopcap(int, int, struct bpf_program *,
 	    const char *, int, bpf_u_int32);
+
+/* XXX - this took two arguments in 0.4 and 0.5 */
+PCAP_AVAILABLE_0_6
 PCAP_API void	pcap_freecode(struct bpf_program *);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_offline_filter(const struct bpf_program *,
 	    const struct pcap_pkthdr *, const u_char *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_datalink(pcap_t *);
+
+PCAP_AVAILABLE_1_0
 PCAP_API int	pcap_datalink_ext(pcap_t *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int	pcap_list_datalinks(pcap_t *, int **);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int	pcap_set_datalink(pcap_t *, int);
+
+PCAP_AVAILABLE_0_8
 PCAP_API void	pcap_free_datalinks(int *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int	pcap_datalink_name_to_val(const char *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API const char *pcap_datalink_val_to_name(int);
+
+PCAP_AVAILABLE_0_8
 PCAP_API const char *pcap_datalink_val_to_description(int);
+
+PCAP_AVAILABLE_1_10
+PCAP_API const char *pcap_datalink_val_to_description_or_dlt(int);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_snapshot(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_is_swapped(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_major_version(pcap_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_minor_version(pcap_t *);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_bufsize(pcap_t *);
 
 /* XXX */
+PCAP_AVAILABLE_0_4
 PCAP_API FILE	*pcap_file(pcap_t *);
+
+#ifdef _WIN32
+/*
+ * This probably shouldn't have been kept in WinPcap; most if not all
+ * UN*X code that used it won't work on Windows.  We deprecate it; if
+ * anybody really needs access to whatever HANDLE may be associated
+ * with a pcap_t (there's no guarantee that there is one), we can add
+ * a Windows-only pcap_handle() API that returns the HANDLE.
+ */
+PCAP_AVAILABLE_0_4
+PCAP_API int	pcap_fileno(pcap_t *)
+PCAP_DEPRECATED(pcap_fileno, "use 'pcap_handle'");
+#else /* _WIN32 */
+PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_fileno(pcap_t *);
+#endif /* _WIN32 */
 
 #ifdef _WIN32
   PCAP_API int	pcap_wsockinit(void);
 #endif
 
+PCAP_AVAILABLE_0_4
 PCAP_API pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
-PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+
+#ifdef _WIN32
+  PCAP_AVAILABLE_0_9
+  PCAP_API pcap_dumper_t *pcap_dump_hopen(pcap_t *, intptr_t);
+
+  /*
+   * If we're building libpcap, this is an internal routine in sf-pcap.c, so
+   * we must not define it as a macro.
+   *
+   * If we're not building libpcap, given that the version of the C runtime
+   * with which libpcap was built might be different from the version
+   * of the C runtime with which an application using libpcap was built,
+   * and that a FILE structure may differ between the two versions of the
+   * C runtime, calls to _fileno() must use the version of _fileno() in
+   * the C runtime used to open the FILE *, not the version in the C
+   * runtime with which libpcap was built.  (Maybe once the Universal CRT
+   * rules the world, this will cease to be a problem.)
+   */
+  #ifndef BUILDING_PCAP
+    #define pcap_dump_fopen(p,f) \
+	pcap_dump_hopen(p, _get_osfhandle(_fileno(f)))
+  #endif
+#else /*_WIN32*/
+  PCAP_AVAILABLE_0_9
+  PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+#endif /*_WIN32*/
+
+PCAP_AVAILABLE_1_7
 PCAP_API pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API FILE	*pcap_dump_file(pcap_dumper_t *);
+
+PCAP_AVAILABLE_0_9
 PCAP_API long	pcap_dump_ftell(pcap_dumper_t *);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int64_t	pcap_dump_ftell64(pcap_dumper_t *);
+
+PCAP_AVAILABLE_0_8
 PCAP_API int	pcap_dump_flush(pcap_dumper_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API void	pcap_dump_close(pcap_dumper_t *);
+
+PCAP_AVAILABLE_0_4
 PCAP_API void	pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
 
+PCAP_AVAILABLE_0_7
 PCAP_API int	pcap_findalldevs(pcap_if_t **, char *);
+
+PCAP_AVAILABLE_0_7
 PCAP_API void	pcap_freealldevs(pcap_if_t *);
 
 /*
@@ -500,7 +752,7 @@
  * 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
+ * a 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,
@@ -510,22 +762,9 @@
  *
  * On Windows, the string is constructed at run time.
  */
+PCAP_AVAILABLE_0_8
 PCAP_API const char *pcap_lib_version(void);
 
-/*
- * On at least some versions of NetBSD and QNX, we don't want to declare
- * bpf_filter() here, as it's also be declared in <net/bpf.h>, with a
- * different signature, but, on other BSD-flavored UN*Xes, it's not
- * declared in <net/bpf.h>, so we *do* want to declare it here, so it's
- * declared when we build pcap-bpf.c.
- */
-#if !defined(__NetBSD__) && !defined(__QNX__)
-  PCAP_API u_int	bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
-#endif
-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)
 
   /*
@@ -559,7 +798,10 @@
 
   PCAP_API HANDLE pcap_getevent(pcap_t *p);
 
+  PCAP_AVAILABLE_1_8
   PCAP_API int pcap_oid_get_request(pcap_t *, bpf_u_int32, void *, size_t *);
+
+  PCAP_AVAILABLE_1_8
   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);
@@ -602,8 +844,11 @@
    * UN*X definitions
    */
 
+  PCAP_AVAILABLE_0_8
   PCAP_API int	pcap_get_selectable_fd(pcap_t *);
-  PCAP_API struct timeval *pcap_get_required_select_timeout(pcap_t *);
+
+  PCAP_AVAILABLE_1_9
+  PCAP_API const struct timeval *pcap_get_required_select_timeout(pcap_t *);
 
 #endif /* _WIN32/MSDOS/UN*X */
 
@@ -636,14 +881,17 @@
  * - 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]
+ * - adaptername [to open a local adapter; kept for compatibility, but it is strongly discouraged]
+ * - (NULL) [to open the first local adapter; kept for compatibility, 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]
  *
+ * In all the above, "rpcaps://" can be substituted for "rpcap://" to enable
+ * SSL (if it has been compiled in).
+ *
  * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
  * IPv6 is fully supported, these are the allowed formats:
  *
@@ -704,7 +952,7 @@
 #define PCAP_OPENFLAG_DATATX_UDP		0x00000002
 
 /*
- * Specifies wheether the remote probe will capture its own generated
+ * Specifies whether the remote probe will capture its own generated
  * traffic.
  *
  * In case the remote probe uses the same interface to capture traffic
@@ -773,7 +1021,7 @@
 #define RPCAP_RMTAUTH_PWD 1
 
 /*
- * This structure keeps the information needed to autheticate the user
+ * This structure keeps the information needed to authenticate the user
  * on a remote machine.
  *
  * The remote machine can either grant or refuse the access according
@@ -832,10 +1080,15 @@
  * For opening a remote capture, pcap_open() is currently the only
  * API available.
  */
+PCAP_AVAILABLE_1_9
 PCAP_API pcap_t	*pcap_open(const char *source, int snaplen, int flags,
 	    int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_createsrcstr(char *source, int type, const char *host,
 	    const char *port, const char *name, char *errbuf);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_parsesrcstr(const char *source, int *type, char *host,
 	    char *port, char *name, char *errbuf);
 
@@ -858,8 +1111,9 @@
  * For listing remote capture devices, pcap_findalldevs_ex() is currently
  * the only API available.
  */
-PCAP_API int	pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth,
-	    pcap_if_t **alldevs, char *errbuf);
+PCAP_AVAILABLE_1_9
+PCAP_API int	pcap_findalldevs_ex(const char *source,
+	    struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
 
 /*
  * Sampling methods.
@@ -928,6 +1182,7 @@
 /*
  * New functions.
  */
+PCAP_AVAILABLE_1_9
 PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
 
 /*
@@ -937,33 +1192,24 @@
 /* Maximum length of an host name (needed for the RPCAP active mode) */
 #define RPCAP_HOSTLIST_SIZE 1024
 
-/*
- * Some minor differences between UN*X sockets and and Winsock sockets.
- */
-#ifndef _WIN32
-  /*!
-   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
-   * a file descriptor, and therefore a signed integer.
-   * We define SOCKET to be a signed integer on UN*X, so that it can
-   * be used on both platforms.
-   */
-  #define SOCKET int
-
-  /*!
-   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
-   * in UN*X, it's -1.
-   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
-   * both platforms.
-   */
-  #define INVALID_SOCKET -1
-#endif
-
+PCAP_AVAILABLE_1_9
 PCAP_API SOCKET	pcap_remoteact_accept(const char *address, const char *port,
 	    const char *hostlist, char *connectinghost,
 	    struct pcap_rmtauth *auth, char *errbuf);
+
+PCAP_AVAILABLE_1_10
+PCAP_API SOCKET	pcap_remoteact_accept_ex(const char *address, const char *port,
+	    const char *hostlist, char *connectinghost,
+	    struct pcap_rmtauth *auth, int uses_ssl, char *errbuf);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_remoteact_list(char *hostlist, char sep, int size,
 	    char *errbuf);
+
+PCAP_AVAILABLE_1_9
 PCAP_API int	pcap_remoteact_close(const char *host, char *errbuf);
+
+PCAP_AVAILABLE_1_9
 PCAP_API void	pcap_remoteact_cleanup(void);
 
 #ifdef __cplusplus
diff --git a/pcap/sll.h b/pcap/sll.h
index c4d0886..392faae 100644
--- a/pcap/sll.h
+++ b/pcap/sll.h
@@ -74,27 +74,44 @@
 #ifndef lib_pcap_sll_h
 #define lib_pcap_sll_h
 
+#include <pcap/pcap-inttypes.h>
+
 /*
  * A DLT_LINUX_SLL fake link-layer header.
  */
 #define SLL_HDR_LEN	16		/* total header length */
 #define SLL_ADDRLEN	8		/* length of address field */
 
-#include <pcap/pcap-inttypes.h>
-
 struct sll_header {
 	uint16_t sll_pkttype;		/* packet type */
 	uint16_t sll_hatype;		/* link-layer address type */
 	uint16_t sll_halen;		/* link-layer address length */
-	uint8_t sll_addr[SLL_ADDRLEN];	/* link-layer address */
+	uint8_t  sll_addr[SLL_ADDRLEN];	/* link-layer address */
 	uint16_t sll_protocol;		/* protocol */
 };
 
 /*
- * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
- * PACKET_ values on Linux, but are defined here so that they're
- * available even on systems other than Linux, and so that they
- * don't change even if the PACKET_ values change.
+ * A DLT_LINUX_SLL2 fake link-layer header.
+ */
+#define SLL2_HDR_LEN	20		/* total header length */
+
+struct sll2_header {
+	uint16_t sll2_protocol;			/* protocol */
+	uint16_t sll2_reserved_mbz;		/* reserved - must be zero */
+	uint32_t sll2_if_index;			/* 1-based interface index */
+	uint16_t sll2_hatype;			/* link-layer address type */
+	uint8_t  sll2_pkttype;			/* packet type */
+	uint8_t  sll2_halen;			/* link-layer address length */
+	uint8_t  sll2_addr[SLL_ADDRLEN];	/* link-layer address */
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype" and LINUX_SLL2_ values for
+ * "sll2_pkttype"; these correspond to the PACKET_ values on Linux,
+ * which are defined by a header under include/uapi in the current
+ * kernel source, and are thus not going to change on Linux.  We
+ * define them here so that they're available even on systems other
+ * than Linux.
  */
 #define LINUX_SLL_HOST		0
 #define LINUX_SLL_BROADCAST	1
@@ -103,10 +120,11 @@
 #define LINUX_SLL_OUTGOING	4
 
 /*
- * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
- * ETH_P_ values on Linux, but are defined here so that they're
- * available even on systems other than Linux.  We assume, for now,
- * that the ETH_P_ values won't change in Linux; if they do, then:
+ * The LINUX_SLL_ values for "sll_protocol" and LINUX_SLL2_ values for
+ * "sll2_protocol"; these correspond to the ETH_P_ values on Linux, but
+ * are defined here so that they're available even on systems other than
+ * Linux.  We assume, for now, that the ETH_P_ values won't change in
+ * Linux; if they do, then:
  *
  *	if we don't translate them in "pcap-linux.c", capture files
  *	won't necessarily be readable if captured on a system that
diff --git a/pcap/socket.h b/pcap/socket.h
new file mode 100644
index 0000000..ee2e393
--- /dev/null
+++ b/pcap/socket.h
@@ -0,0 +1,84 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_socket_h
+#define lib_pcap_socket_h
+
+/*
+ * Some minor differences between sockets on various platforms.
+ * We include whatever sockets are needed for Internet-protocol
+ * socket access on UN*X and Windows.
+ */
+#ifdef _WIN32
+  /* Need windef.h for defines used in winsock2.h under MingW32 */
+  #ifdef __MINGW32__
+    #include <windef.h>
+  #endif
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+
+  /*
+   * Winsock doesn't have this POSIX type; it's used for the
+   * tv_usec value of struct timeval.
+   */
+  typedef long suseconds_t;
+#else /* _WIN32 */
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netdb.h>		/* for struct addrinfo/getaddrinfo() */
+  #include <netinet/in.h>	/* for sockaddr_in, in BSD at least */
+  #include <arpa/inet.h>
+
+  /*!
+   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+   * a file descriptor, and therefore a signed integer.
+   * We define SOCKET to be a signed integer on UN*X, so that it can
+   * be used on both platforms.
+   */
+  #ifndef SOCKET
+    #define SOCKET int
+  #endif
+
+  /*!
+   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+   * in UN*X, it's -1.
+   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+   * both platforms.
+   */
+  #ifndef INVALID_SOCKET
+    #define INVALID_SOCKET -1
+  #endif
+#endif /* _WIN32 */
+
+#endif /* lib_pcap_socket_h */
diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap
index ceb2aa7..169a756 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 "31 July 2016"
+.TH PCAP_ACTIVATE 3PCAP "24 November 2019"
 .SH NAME
 pcap_activate \- activate a capture handle
 .SH SYNOPSIS
@@ -31,13 +31,15 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_activate()
+.BR pcap_activate ()
 is used to activate a packet capture handle to look
 at packets on the network, with the options that were set on the handle
 being in effect.
 .SH RETURN VALUE
-.B pcap_activate()
-returns 0 on success without warnings, a non-zero positive value on
+.BR pcap_activate ()
+returns
+.B 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.
@@ -50,15 +52,15 @@
 .TP
 .B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
 The time stamp type specified in a previous
-.B pcap_set_tstamp_type()
+.BR pcap_set_tstamp_type (3PCAP)
 call isn't supported by the capture source (the time stamp type is
 left as the default),
 .TP
 .B PCAP_WARNING
 Another warning condition occurred;
-.B pcap_geterr()
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display a message describing the warning
@@ -89,9 +91,9 @@
 .TP
 .B PCAP_ERROR
 Another error occurred.
-.B pcap_geterr()
+.BR pcap_geterr ()
 or
-.B pcap_perror()
+.BR pcap_perror ()
 may be called with
 .I p
 as an argument to fetch or display a message describing the error.
@@ -102,9 +104,9 @@
 or
 .B PCAP_ERROR_PERM_DENIED
 is returned,
-.B pcap_geterr()
+.BR pcap_geterr ()
 or
-.B pcap_perror()
+.BR pcap_perror ()
 may be called with
 .I p
 as an argument to fetch or display an message giving additional details
@@ -115,8 +117,15 @@
 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()
+.BR pcap_statustostr (3PCAP)
 can be called, with a warning or error code as an argument, to fetch a
 message describing the warning or error code.
+.LP
+If
+.BR pcap_activate ()
+fails, the
+.I pcap_t *
+is not closed and freed; it should be closed using
+.BR pcap_close ().
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_breakloop.3pcap b/pcap_breakloop.3pcap
index 03b8d8d..996290f 100644
--- a/pcap_breakloop.3pcap
+++ b/pcap_breakloop.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_BREAKLOOP 3PCAP "8 November 2017"
+.TH PCAP_BREAKLOOP 3PCAP "25 July 2018"
 .SH NAME
 pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
 .SH SYNOPSIS
@@ -31,14 +31,15 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_breakloop()
+.BR pcap_breakloop ()
 sets a flag that will force
-.B pcap_dispatch()
+.BR pcap_dispatch (3PCAP)
 or
-.B pcap_loop()
+.BR pcap_loop (3PCAP)
 to return rather than looping; they will return the number of packets
-that have been processed so far, or \-2 if no packets have been
-processed so far.
+that have been processed so far, or
+.B PCAP_ERROR_BREAK
+if no packets have been processed so far.
 .PP
 This routine is safe to use inside a signal handler on UNIX or a console
 control handler on Windows, as it merely sets a flag that is checked
@@ -60,7 +61,7 @@
 .PP
 .ft B
 Note also that, in a multi-threaded application, if one thread is
-blocked in pcap_dispatch(), pcap_loop(), pcap_next(), or pcap_next_ex(),
+blocked in pcap_dispatch(), pcap_loop(), pcap_next(3PCAP), or pcap_next_ex(3PCAP),
 a call to pcap_breakloop() in a different thread will not unblock that
 thread.
 .ft R
@@ -68,9 +69,9 @@
 breaking a thread out of blocking calls in order to unblock the thread,
 such as thread cancellation or thread signalling in systems that support
 POSIX threads, or
-.B SetEvent()
+.BR SetEvent ()
 on the result of
-.B pcap_getevent()
+.BR pcap_getevent ()
 on a
 .B pcap_t
 on which the thread is blocked on Windows.  Asynchronous procedure calls
@@ -80,31 +81,35 @@
 .ft R
 .PP
 Note that
-.B pcap_next()
+.BR pcap_next ()
 and
-.B pcap_next_ex()
+.BR pcap_next_ex ()
 will, on some platforms, loop reading packets from the OS; that loop
 will not necessarily be terminated by a signal, so
-.B pcap_breakloop()
+.BR pcap_breakloop ()
 should be used to terminate packet processing even if
-.B pcap_next()
+.BR pcap_next ()
 or
-.B pcap_next_ex()
+.BR pcap_next_ex ()
 is being used.
 .PP
-.B pcap_breakloop()
+.BR pcap_breakloop ()
 does not guarantee that no further packets will be processed by
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 or
-.B pcap_loop()
+.BR pcap_loop ()
 after it is called; at most one more packet might be processed.
 .PP
-If \-2 is returned from
-.B pcap_dispatch()
+If
+.B PCAP_ERROR_BREAK
+is returned from
+.BR pcap_dispatch ()
 or
-.BR pcap_loop() ,
+.BR pcap_loop (),
 the flag is cleared, so a subsequent call will resume reading packets.
 If a positive number is returned, the flag is not cleared, so a
-subsequent call will return \-2 and clear the flag.
+subsequent call will return
+.B PCAP_ERROR_BREAK
+and clear the flag.
 .SH SEE ALSO
-pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_can_set_rfmon.3pcap b/pcap_can_set_rfmon.3pcap
index eee004d..be03956 100644
--- a/pcap_can_set_rfmon.3pcap
+++ b/pcap_can_set_rfmon.3pcap
@@ -31,13 +31,16 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_can_set_rfmon()
+.BR pcap_can_set_rfmon ()
 checks whether monitor mode could be set on a capture handle when
 the handle is activated.
 .SH RETURN VALUE
-.B pcap_can_set_rfmon()
-returns 0 if monitor mode could not be set,
-1 if monitor mode could be set, and a negative value on error.
+.BR pcap_can_set_rfmon ()
+returns
+.B 0
+if monitor mode could not be set,
+.B 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
@@ -54,19 +57,24 @@
 .TP
 .B PCAP_ERROR
 Another error occurred.
-.B pcap_geterr()
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR \%pcap_perror (3PCAP)
 may be called with
 .I p
 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
+check for
+.BR 0 ,
+.BR 1 ,
+and negative, return codes, and treat all negative
 return codes as errors.
-.B pcap_statustostr()
+.BR pcap_statustostr (3PCAP)
 can be called, with a warning or error code as an argument, to fetch a
 message describing the warning or error code.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_set_rfmon(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP),
+.BR pcap_set_rfmon (3PCAP)
diff --git a/pcap_close.3pcap b/pcap_close.3pcap
index e2316a4..c4ac3fa 100644
--- a/pcap_close.3pcap
+++ b/pcap_close.3pcap
@@ -31,9 +31,9 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_close()
+.BR pcap_close ()
 closes the files associated with
 .I p
 and deallocates resources.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_compile.3pcap b/pcap_compile.3pcap
deleted file mode 100644
index 181814b..0000000
--- a/pcap_compile.3pcap
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" 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 "24 March 2017"
-.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.
-.LP
-NOTE: in libpcap 1.8.0 and later,
-.B pcap_compile()
-can be used in multiple threads within a single process.  However, in
-earlier versions of libpcap, it is
-.I not
-safe to use
-.B pcap_compile()
-in multiple threads in a single process without some form of mutual
-exclusion allowing only one thread to call it at any given time.
-.SH RETURN VALUE
-.B pcap_compile()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
-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 29ae8f8..8238e54 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 "24 March 2017"
+.TH PCAP_COMPILE 3PCAP "22 August 2018"
 .SH NAME
 pcap_compile \- compile a filter expression
 .SH SYNOPSIS
@@ -33,7 +33,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_compile()
+.BR pcap_compile ()
 is used to compile the string
 .I str
 into a filter program.  See
@@ -43,7 +43,7 @@
 is a pointer to a
 .I bpf_program
 struct and is filled in by
-.BR pcap_compile() .
+.BR pcap_compile ().
 .I optimize
 controls whether optimization on the resulting code is performed.
 .I netmask
@@ -52,29 +52,42 @@
 the filter program.  If the netmask of the network on which packets are
 being captured isn't known to the program, or if packets are being
 captured on the Linux "any" pseudo-interface that can capture on more
-than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied; tests
+than one network, a value of
+.B PCAP_NETMASK_UNKNOWN
+can be supplied; tests
 for IPv4 broadcast addresses will fail to compile, but all other tests in
 the filter program will be OK.
 .LP
 NOTE: in libpcap 1.8.0 and later,
-.B pcap_compile()
+.BR pcap_compile ()
 can be used in multiple threads within a single process.  However, in
 earlier versions of libpcap, it is
 .I not
 safe to use
-.B pcap_compile()
+.BR pcap_compile ()
 in multiple threads in a single process without some form of mutual
 exclusion allowing only one thread to call it at any given time.
 .SH RETURN VALUE
-.B pcap_compile()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+.BR pcap_compile ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_NETMASK_UNKNOWN
+constant became available in libpcap release 1.1.0.
 .SH SEE ALSO
-pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
-pcap_geterr(3PCAP), pcap-filter(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_setfilter (3PCAP),
+.BR pcap_freecode (3PCAP)
diff --git a/pcap_create.3pcap b/pcap_create.3pcap
index 3040b3b..bd42d73 100644
--- a/pcap_create.3pcap
+++ b/pcap_create.3pcap
@@ -36,7 +36,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_create()
+.BR pcap_create ()
 is used to create a packet capture handle to look
 at packets on the network.
 .I source
@@ -48,12 +48,12 @@
 can be used to capture packets from all interfaces.
 .PP
 The returned handle must be activated with
-.B pcap_activate()
+.BR pcap_activate (3PCAP)
 before packets can be captured
 with it; options for the capture, such as promiscuous mode, can be set
 on the handle before activating it.
 .SH RETURN VALUE
-.B pcap_create()
+.BR pcap_create ()
 returns a
 .I pcap_t *
 on success and
@@ -69,4 +69,4 @@
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_activate(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_datalink.3pcap b/pcap_datalink.3pcap
deleted file mode 100644
index 50508f8..0000000
--- a/pcap_datalink.3pcap
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" 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 https://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 a32f15e..abb7375 100644
--- a/pcap_datalink.3pcap.in
+++ b/pcap_datalink.3pcap.in
@@ -31,19 +31,19 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_datalink()
+.BR 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()
+.BR \%pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate (3PCAP).
 .PP
 .I https://www.tcpdump.org/linktypes.html
 lists the values
-.B pcap_datalink()
+.BR pcap_datalink ()
 can return and describes the packet formats that
 correspond to those values.
 .PP
@@ -55,14 +55,17 @@
 for Ethernet.  For example, the "any" device on Linux will have a
 link-layer header type of
 .B DLT_LINUX_SLL
+or
+.B DLT_LINUX_SLL2
 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()
+.BR pcap_datalink ()
 returns the link-layer header type on success and
 .B PCAP_ERROR_NOT_ACTIVATED
 if called on a capture handle that has been created but not activated.
 .SH SEE ALSO
-pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap-linktype (@MAN_MISC_INFO@)
diff --git a/pcap_datalink_name_to_val.3pcap b/pcap_datalink_name_to_val.3pcap
index e6419f2..d2cb103 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 "12 October 2016"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "25 July 2018"
 .SH NAME
 pcap_datalink_name_to_val \- get the link-layer header type value
 corresponding to a header type name
@@ -32,7 +32,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_datalink_name_to_val()
+.BR pcap_datalink_name_to_val ()
 translates a link-layer header type name, which is a
 .B DLT_
 name with the
@@ -40,8 +40,10 @@
 removed, to the corresponding link-layer header type value.  The
 translation is case-insensitive.
 .SH RETURN VALUE
-.B pcap_datalink_name_to_val()
-returns the type value on success and \-1 if the name is not a known
-type name..
+.BR pcap_datalink_name_to_val ()
+returns the type value on success and
+.B PCAP_ERROR
+if the name is not a known
+type name.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_datalink_val_to_name.3pcap b/pcap_datalink_val_to_name.3pcap
index fad350f..bbfa3f8 100644
--- a/pcap_datalink_val_to_name.3pcap
+++ b/pcap_datalink_val_to_name.3pcap
@@ -17,9 +17,10 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "12 October 2016"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "15 April 2019"
 .SH NAME
-pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
+pcap_datalink_val_to_name, pcap_datalink_val_to_description,
+pcap_datalink_val_to_description_or_dlt \- get a
 name or description for a link-layer header type value
 .SH SYNOPSIS
 .nf
@@ -30,10 +31,11 @@
 .ft B
 const char *pcap_datalink_val_to_name(int dlt);
 const char *pcap_datalink_val_to_description(int dlt);
+const char *pcap_datalink_val_to_description_or_dlt(int dlt);
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_datalink_val_to_name()
+.BR pcap_datalink_val_to_name ()
 translates a link-layer header type value to the corresponding
 link-layer header type name, which is the
 .B DLT_
@@ -45,10 +47,30 @@
 .B DLT_
 value.
 .PP
-.B pcap_datalink_val_to_description()
+.BR 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 if the type value does not correspond to a known
 .B DLT_
 value.
+.PP
+.BR pcap_datalink_val_to_description_or_dlt ()
+translates a link-layer header type value to a short description of that
+link-layer header type just like
+.BR pcap_datalink_val_to_description ().
+If the type value does not correspond to a known
+.B DLT_
+value, the string "DLT n" is returned, where n is the value of
+the dlt argument.
+.SH BACKWARD COMPATIBILITY
+The
+.BR pcap_datalink_val_to_description_or_dlt ()
+function first became available in libpcap release 1.10.0.  In previous
+releases,
+.BR pcap_datalink_val_to_description ()
+would have to be called and, if it returned
+.BR NULL ,
+a default string would have to be constructed.
+.SH SEE ALSO
+.BR pcap (3PCAP)
diff --git a/pcap_dump.3pcap b/pcap_dump.3pcap
index 6402b4b..ba7f75a 100644
--- a/pcap_dump.3pcap
+++ b/pcap_dump.3pcap
@@ -33,19 +33,18 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump()
+.BR pcap_dump ()
 outputs a packet to the ``savefile'' opened with
-.BR pcap_dump_open() .
+.BR pcap_dump_open (3PCAP).
 Note that its calling arguments are suitable for use with
-.B pcap_dispatch()
+.BR pcap_dispatch (3PCAP)
 or
-.BR pcap_loop() .
+.BR pcap_loop (3PCAP).
 If called directly, the
 .I user
 parameter is of type
 .B pcap_dumper_t
 as returned by
-.BR pcap_dump_open() .
+.BR pcap_dump_open ().
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dispatch(3PCAP),
-pcap_loop(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_dump_close.3pcap b/pcap_dump_close.3pcap
index bd95a52..a62eb34 100644
--- a/pcap_dump_close.3pcap
+++ b/pcap_dump_close.3pcap
@@ -31,7 +31,9 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump_close()
+.BR pcap_dump_close ()
 closes the ``savefile.''
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_dump_open (3PCAP),
+.BR pcap_dump (3PCAP)
diff --git a/pcap_dump_file.3pcap b/pcap_dump_file.3pcap
index 8fea610..9fd6c7e 100644
--- a/pcap_dump_file.3pcap
+++ b/pcap_dump_file.3pcap
@@ -31,8 +31,8 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump_file()
+.BR pcap_dump_file ()
 returns the standard I/O stream of the ``savefile'' opened by
-.BR pcap_dump_open() .
+.BR pcap_dump_open (3PCAP).
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_dump_flush.3pcap b/pcap_dump_flush.3pcap
index c8f110b..c6e0f86 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 "3 January 2014"
+.TH PCAP_DUMP_FLUSH 3PCAP "25 July 2018"
 .SH NAME
 pcap_dump_flush \- flush to a savefile packets dumped
 .SH SYNOPSIS
@@ -31,13 +31,18 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump_flush()
+.BR pcap_dump_flush ()
 flushes the output buffer to the ``savefile,'' so that any packets
 written with
-.B pcap_dump()
+.BR pcap_dump (3PCAP)
 but not yet written to the ``savefile'' will be written.
 .SH RETURN VALUE
-.B pcap_dump_flush()
-returns 0 on success and \-1 on failure.
+.BR pcap_dump_flush ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure.
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_dump_open (3PCAP)
diff --git a/pcap_dump_ftell.3pcap b/pcap_dump_ftell.3pcap
index ec621fb..062d609 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 "29 September 2017"
+.TH PCAP_DUMP_FTELL 3PCAP "25 July 2018"
 .SH NAME
 pcap_dump_ftell, pcap_dump_ftell64 \- get the current file offset for a savefile being written
 .SH SYNOPSIS
@@ -33,18 +33,18 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump_ftell()
+.BR pcap_dump_ftell ()
 returns the current file position for the ``savefile'', representing the
 number of bytes written by
-.B pcap_dump_open()
+.BR pcap_dump_open (3PCAP)
 and
-.BR pcap_dump() .
-\-1 is returned on error.
-If the current file position does not fit in a
+.BR pcap_dump (3PCAP).
+.B PCAP_ERROR
+is returned on error. If the current file position does not fit in a
 .BR long ,
 it will be truncated; this can happen on 32-bit UNIX-like systems with
 large file support and on Windows.
-.B pcap_dump_ftell64()
+.BR pcap_dump_ftell64 ()
 returns the current file position in a
 .BR int64_t ,
 so if file offsets that don't fit in a
@@ -52,6 +52,13 @@
 but that fit in a
 .B int64_t
 are supported, this will return the file offset without truncation.
-\-1 is returned on error.
+.B PCAP_ERROR
+is returned on error.
+.SH BACKWARD COMPATIBILITY
+The function
+.BR pcap_dump_ftell64 ()
+became available in libpcap release 1.9.0.  In previous releases, there
+was no mechanism to obtain a file offset that is too large to fit in a
+.BR long .
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_dump_open.3pcap b/pcap_dump_open.3pcap
deleted file mode 100644
index 03956ba..0000000
--- a/pcap_dump_open.3pcap
+++ /dev/null
@@ -1,98 +0,0 @@
-.\" 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 "22 June 2018"
-.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 ;
-this stream will be closed by a subsequent call to
-.BR pcap_dump_close() .
-Note that on Windows, that stream should be opened in binary mode.
-.PP
-.I p
-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 5b37b47..fddecb8 100644
--- a/pcap_dump_open.3pcap.in
+++ b/pcap_dump_open.3pcap.in
@@ -17,9 +17,10 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_OPEN 3PCAP "22 June 2018"
+.TH PCAP_DUMP_OPEN 3PCAP "3 July 2020"
 .SH NAME
-pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+pcap_dump_open, pcap_dump_open_append, pcap_dump_fopen \- open a file to
+which to write packets
 .SH SYNOPSIS
 .nf
 .ft B
@@ -34,7 +35,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_dump_open()
+.BR 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
@@ -42,57 +43,66 @@
 .BR tcpdump (1)
 and
 .BR tcpslice (1).
+If the file does not exist, it will be created; if the file exists, it
+will be truncated and overwritten.
 The name "-" is a synonym
 for
 .BR stdout .
 .PP
-.B pcap_dump_fopen()
+.BR pcap_dump_fopen ()
 is called to write data to an existing open stream
 .IR fp ;
 this stream will be closed by a subsequent call to
-.BR pcap_dump_close() .
+.BR pcap_dump_close (3PCAP).
+The stream is assumed to be at the beginning of a file that has been
+newly created or truncated, so that writes will start at the beginning
+of the file.
 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()
+.BR pcap_create (3PCAP)
 and activated by an earlier call to
-.BR pcap_activate() ,
+.BR \%pcap_activate (3PCAP),
 or returned by an earlier call to
-.BR pcap_open_offline() ,
-.BR pcap_open_live() ,
+.BR \%pcap_open_offline (3PCAP),
+.BR pcap_open_live (3PCAP),
 or
-.BR pcap_open_dead() .
+.BR pcap_open_dead (3PCAP).
 The time stamp precision, link-layer type, and snapshot length from
 .I p
 are used as the link-layer type and snapshot length of the output file.
 .PP
-.B pcap_dump_open_append()
+.BR 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
+.BR pcap_dump_open ()
+but, if the file already exists, 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()
+.BR pcap_dump (3PCAP)
 and
-.B pcap_dump_close()
+.BR pcap_dump_close (3PCAP)
 calls is returned on success.
 .B NULL
 is returned on failure.
 If
 .B NULL
 is returned,
-.B pcap_geterr(\fIp\fB)
+.BR pcap_geterr (3PCAP)
 can be used to get the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.BR pcap_dump_open_append ()
+function became available in libpcap release 1.7.2.  In previous
+releases, there is no support for appending packets to an existing
+savefile.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-\%pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP),
-pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
-\%pcap-savefile(@MAN_FILE_FORMATS@)
+.BR pcap (3PCAP),
+.BR \%pcap-savefile (@MAN_FILE_FORMATS@)
diff --git a/pcap_file.3pcap b/pcap_file.3pcap
index cd6b06b..7402973 100644
--- a/pcap_file.3pcap
+++ b/pcap_file.3pcap
@@ -31,27 +31,29 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_file()
+.BR pcap_file ()
 returns the standard I/O stream of the ``savefile,'' if a ``savefile''
 was opened with
-.BR pcap_open_offline() ,
-or NULL, if a network device was opened with
-.B pcap_create()
+.BR pcap_open_offline (3PCAP),
+or
+.BR NULL ,
+if a network device was opened with
+.BR pcap_create (3PCAP)
 and
-.BR pcap_activate() ,
+.BR \%pcap_activate (3PCAP),
 or with
-.BR pcap_open_live() .
+.BR pcap_open_live (3PCAP).
 .PP
 Note that the Packet Capture library is usually built with large file
 support, so the standard I/O stream of the ``savefile'' might refer to
 a file larger than 2 gigabytes; applications that use
-.B pcap_file()
+.BR pcap_file ()
 should, if possible, use calls that support large files on the return
 value of
-.B pcap_file()
+.BR pcap_file ()
 or the value returned by
-.B fileno()
+.BR fileno (3)
 when passed the return value of
-.BR pcap_file() .
+.BR pcap_file ().
 .SH SEE ALSO
-pcap(3PCAP), pcap_open_offline(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_fileno.3pcap b/pcap_fileno.3pcap
index e8c9ac4..6d0edf8 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 "7 April 2014"
+.TH PCAP_FILENO 3PCAP "25 July 2018"
 .SH NAME
 pcap_fileno \- get the file descriptor for a live capture
 .SH SYNOPSIS
@@ -35,32 +35,31 @@
 .I p
 refers to a network device that was opened for a live capture using
 a combination of
-.B pcap_create()
+.BR pcap_create (3PCAP)
 and
-.BR pcap_activate() ,
+.BR pcap_activate (3PCAP),
 or using
-.BR pcap_open_live() ,
-.B pcap_fileno()
+.BR pcap_open_live (3PCAP),
+.BR pcap_fileno ()
 returns the file descriptor from which captured packets are read.
 .LP
 If
 .I p
 refers to a ``savefile'' that was opened using functions such as
-.BR pcap_open_offline()
+.BR pcap_open_offline (3PCAP)
 or
-.BR pcap_fopen_offline() ,
+.BR pcap_fopen_offline (3PCAP),
 a ``dead''
 .B pcap_t
 opened using
-.BR pcap_open_dead() ,
+.BR pcap_open_dead (3PCAP),
 or a
 .B pcap_t
 that was created with
-.B pcap_create()
+.BR pcap_create ()
 but that has not yet been activated with
-.BR pcap_activate() ,
-it returns \-1.
+.BR pcap_activate (),
+it returns
+.BR PCAP_ERROR .
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP), pcap_open_offline(3PCAP),
-\%pcap_fopen_offline(3PCAP), pcap_open_dead(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_findalldevs.3pcap b/pcap_findalldevs.3pcap
index 14825ad..41c98fe 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 "29 April 2018"
+.TH PCAP_FINDALLDEVS 3PCAP "23 August 2018"
 .SH NAME
 pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
 free that list
@@ -38,21 +38,21 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_findalldevs()
+.BR pcap_findalldevs ()
 constructs a list of network devices that can be opened with
-.B pcap_create()
+.BR pcap_create (3PCAP)
 and
-.B pcap_activate()
+.BR pcap_activate (3PCAP)
 or with
-.BR pcap_open_live() .
+.BR pcap_open_live (3PCAP).
 (Note that there may be network devices that cannot be opened by the
 process calling
-.BR pcap_findalldevs() ,
+.BR pcap_findalldevs (),
 because, for example, that process does not have sufficient privileges
 to open them for capturing; if so, those devices will not appear on the
 list.)
 If
-.B pcap_findalldevs()
+.BR pcap_findalldevs ()
 succeeds, the pointer pointed to by
 .I alldevsp
 is set to point to the first element of the list, or to
@@ -72,7 +72,7 @@
 .TP
 .B name
 a pointer to a string giving a name for the device to pass to
-.B pcap_open_live()
+.BR pcap_open_live ()
 .TP
 .B description
 if not
@@ -194,21 +194,40 @@
 .BR "struct sockaddr_in6".
 .PP
 The list of devices must be freed with
-.BR pcap_freealldevs() ,
+.BR pcap_freealldevs (3PCAP),
 which frees the list pointed to by
 .IR alldevs .
 .SH RETURN VALUE
-.B pcap_findalldevs()
-returns 0 on success and \-1 on failure; as indicated, finding no
+.BR pcap_findalldevs ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure; as indicated, finding no
 devices is considered success, rather than failure, so 0 will be
-returned in that case.
-If \-1 is returned,
+returned in that case. If
+.B PCAP_ERROR
+is returned,
 .I errbuf
 is filled in with an appropriate error message.
 .I errbuf
 is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_IF_UP
+and
+.B PCAP_IF_RUNNING
+constants became available in libpcap release 1.6.1.  The
+.BR PCAP_IF_WIRELESS ,
+.BR PCAP_IF_CONNECTION_STATUS ,
+.BR PCAP_IF_CONNECTION_STATUS_UNKNOWN ,
+.BR PCAP_IF_CONNECTION_STATUS_CONNECTED ,
+.BR PCAP_IF_CONNECTION_STATUS_DISCONNECTED ,
+and
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+constants became available in libpcap release 1.9.0.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_freecode.3pcap b/pcap_freecode.3pcap
index fac4b3d..65915fa 100644
--- a/pcap_freecode.3pcap
+++ b/pcap_freecode.3pcap
@@ -31,13 +31,13 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_freecode()
+.BR pcap_freecode ()
 is used to free up allocated memory pointed to by a
 .I bpf_program
 struct generated by
-.B pcap_compile()
+.BR pcap_compile (3PCAP)
 when that BPF program is no longer needed, for example after it
 has been made the filter program for a pcap structure by a call to
-.BR pcap_setfilter() .
+.BR pcap_setfilter (3PCAP).
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_setfilter(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_get_required_select_timeout.3pcap b/pcap_get_required_select_timeout.3pcap
index bc33e5d..0256a6a 100644
--- a/pcap_get_required_select_timeout.3pcap
+++ b/pcap_get_required_select_timeout.3pcap
@@ -17,10 +17,10 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_GET_REQUIRED_SELECT_TIMEOUT 3PCAP "20 January 2018"
+.TH PCAP_GET_REQUIRED_SELECT_TIMEOUT 3PCAP "29 January 2020"
 .SH NAME
-pcap_get_required_select_timeout \- get a file descriptor on which a
-select() can be done for a live capture
+pcap_get_required_select_timeout \- get a timeout to be used when doing
+select() for a live capture
 .SH SYNOPSIS
 .nf
 .ft B
@@ -28,50 +28,98 @@
 .ft
 .LP
 .ft B
-struct timeval *pcap_get_required_select_timeout(pcap_t *p);
+const struct timeval *pcap_get_required_select_timeout(pcap_t *p);
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_get_required_select_timeout()
+.BR pcap_get_required_select_timeout ()
 returns, on UNIX, a pointer to a
 .B struct timeval
 containing a value that must be used as the minimum timeout in
-.BR select() ,
-.BR poll() ,
-.BR epoll_wait() ,
+.BR select (2),
+.BR poll (2),
+.BR epoll_wait (2),
 and
-.B kevent()
-calls if
-.B pcap_get_selectable_fd()
-returns \-1.
-.PP
-The timeout that should be used in those calls must be no larger than
-the smallest of all timeouts returned by
-.B pcap_get_required_select_timeout()
-for devices from which packets will be captured.
-.PP
-The device for which
-.B pcap_get_selectable_fd()
-returned \-1 must be put in non-blocking mode with
-.BR pcap_setnonblock() ,
-and an attempt must always be made to read packets from the device
-when the
-.BR select() ,
-.BR poll() ,
-.BR epoll_wait() ,
+.BR kevent (2)
+calls, or
+.B NULL
+if there is no such timeout.
+If a
+.RB non- NULL
+value is returned, it must be used regardless of whether
+.BR pcap_get_selectable_fd (3PCAP)
+returns
+.B \-1
+for any descriptor on which those calls are being done.
+.BR pcap_get_required_select_timeout ()
+should be called for all
+.BR pcap_t s
+before a call to
+.BR select (),
+.BR poll (),
+.BR epoll_wait (),
 or
-.B kevent()
-call returns.
+.BR kevent (),
+and any timeouts used for those calls should be updated as appropriate
+given the new value of the timeout.
+.PP
+For
+.BR kevent (),
+one
+.B EVFILT_TIMER
+filter per selectable descriptor can be used, rather than using the
+timeout argument to
+.BR kevent ();
+if the
+.B EVFILT_TIMER
+event for a particular selectable descriptor signals an event,
+.BR pcap_dispatch (3PCAP)
+should be called for the corresponding
+.BR pcap_t .
+.PP
+On Linux systems with
+.BR timerfd_create (2),
+one timer object created by
+.BR timerfd_create ()
+per selectable descriptor can be used, rather than using the timeout
+argument to
+.BR epoll_wait ();
+if the
+timer object for a particular selectable descriptor signals an event,
+.BR pcap_dispatch (3PCAP)
+should be called for the corresponding
+.BR pcap_t .
+.PP
+Otherwise, a timeout value no larger than
+the smallest of all timeouts returned by
+.BR \%pcap_get_required_select_timeout ()
+for devices from which packets will be captured and any other timeouts
+to be used in the call should be used as the timeout for the call, and,
+when the call returns,
+.BR pcap_dispatch (3PCAP)
+should be called for all
+.BR pcap_t s
+for which a
+.RB non- NULL
+timeout was returned, regardless of whether it's indicated as having
+anything to read from it or not.
+.PP
+All devices with a
+.RB non- NULL
+timeout must be put in non-blocking mode with
+.BR pcap_setnonblock (3PCAP).
 .PP
 Note that a device on which a read can be done without blocking may,
 on some platforms, not have any packets to read if the packet buffer
 timeout has expired.  A call to
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 or
-.B pcap_next_ex()
-will return 0 in this case, but will not block.
+.BR pcap_next_ex (3PCAP)
+will return
+.B 0
+in this case, but will not block.
 .PP
-.B pcap_get_required_select_timeout()
+.BR pcap_get_required_select_timeout ()
 is not available on Windows.
 .SH RETURN VALUE
 A pointer to a
@@ -79,6 +127,53 @@
 is returned if the timeout is required; otherwise
 .B NULL
 is returned.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.  In previous
+releases,
+.BR select (),
+.BR poll (),
+.BR epoll_wait (),
+and
+.BR kevent ()
+cannot be used on any capture source for which
+.BR pcap_get_selectable_fd ()
+returns
+.BR \-1 .
+.PP
+In libpcap release 1.10.0 and later, the timeout value can change from
+call to call, so
+.BR pcap_get_required_select_timeout ()
+must be called before each call to
+.BR select (),
+.BR poll (),
+.BR epoll_wait (),
+or
+.BR kevent (),
+and the new value must be used to calculate timeouts for the call.  Code
+that does that will also work with libpcap 1.9.x releases, so code
+using
+.BR pcap_get_required_select_timeout ()
+should be changed to call it for each call to
+.BR select (),
+.BR poll (),
+.BR epoll_wait (),
+or
+.BR kevent ()
+even if the code must also work with libpcap 1.9.x.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.  In previous
+releases,
+.BR select (),
+.BR poll (),
+.BR epoll_wait (),
+and
+.BR kevent ()
+could not be used for devices that don't provide a selectable file
+descriptor.
 .SH SEE ALSO
-pcap(3PCAP), pcap_get_selectable_fd(3PCAP), select(2), poll(2),
-epoll_wait(2), kqueue(2)
+.BR pcap (3PCAP),
+.BR pcap_get_selectable_fd (3PCAP),
+.BR select (2),
+.BR poll (2),
+.BR epoll_wait (2),
+.BR kqueue (2)
diff --git a/pcap_get_selectable_fd.3pcap b/pcap_get_selectable_fd.3pcap
index f1ddfe2..ed33303 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 "20 January 2018"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "29 January 2020"
 .SH NAME
 pcap_get_selectable_fd \- get a file descriptor on which a select() can
 be done for a live capture
@@ -32,36 +32,42 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_get_selectable_fd()
+.BR pcap_get_selectable_fd ()
 returns, on UNIX, a file descriptor number for a file descriptor on
 which one can
 do a
-.BR select() ,
-.BR poll() ,
-.BR epoll_wait() ,
-.BR kevent() ,
+.BR select (2),
+.BR poll (2),
+.BR epoll_wait (2),
+.BR kevent (2),
 or other such call
 to wait for it to be possible to read packets without blocking, if such
-a descriptor exists, or \-1, if no such descriptor exists.
+a descriptor exists, or
+.BR \-1 ,
+if no such descriptor exists.
 .PP
 Some network devices opened with
-.B pcap_create()
+.BR pcap_create (3PCAP)
 and
-.BR pcap_activate() ,
+.BR pcap_activate (3PCAP),
 or with
-.BR pcap_open_live() ,
+.BR pcap_open_live (3PCAP),
 do not support those calls (for example, regular network devices on
-FreeBSD 4.3 and 4.4, and Endace DAG devices), so \-1 is returned for
+FreeBSD 4.3 and 4.4, and Endace DAG devices), so
+.B \-1
+is returned for
 those devices.  In that case, those calls must be given a timeout less
 than or equal to the timeout returned by
-.B pcap_get_required_select_timeout()
+.BR pcap_get_required_select_timeout (3PCAP)
 for the device for which
-.B pcap_get_selectable_fd()
-returned \-1, the device must be put in non-blocking mode with a call to
-.BR pcap_setnonblock() ,
+.BR pcap_get_selectable_fd ()
+returned
+.BR \-1 ,
+the device must be put in non-blocking mode with a call to
+.BR \%pcap_setnonblock (3PCAP),
 and an attempt must always be made to read packets from the device
 when the call returns.  If
-.B pcap_get_required_select_timeout()
+.BR \%pcap_get_required_select_timeout ()
 returns
 .BR NULL ,
 it is not possible to wait for packets to arrive on the device in an
@@ -70,9 +76,9 @@
 Note that a device on which a read can be done without blocking may,
 on some platforms, not have any packets to read if the packet buffer
 timeout has expired.  A call to
-.B pcap_dispatch()
+.BR pcap_dispatch (3PCAP)
 or
-.B pcap_next_ex()
+.BR pcap_next_ex (3PCAP)
 will return 0 in this case, but will not block.
 .PP
 Note that in:
@@ -85,18 +91,18 @@
 .IP
 Mac OS X prior to Mac OS X 10.7;
 .PP
-.BR select() ,
-.BR poll() ,
+.BR select (),
+.BR poll (),
 and
-.B kevent()
+.BR kevent ()
 do not work correctly on BPF devices;
-.B pcap_get_selectable_fd()
+.BR pcap_get_selectable_fd ()
 will return a file descriptor on most of those versions (the exceptions
 being FreeBSD 4.3 and 4.4), but a simple
-.BR select() ,
-.BR poll() ,
+.BR select (),
+.BR poll (),
 or
-.B kevent()
+.BR kevent ()
 call will not indicate that the descriptor is readable until a full
 buffer's worth of packets is received, even if the packet timeout
 expires before then.  To work around this, code that uses
@@ -113,33 +119,34 @@
 although it does no harm.)
 .PP
 Note also that
-.B poll()
+.BR poll ()
 and
-.B kevent()
+.BR kevent ()
 doesn't work on character special files, including BPF devices, in Mac
 OS X 10.4 and 10.5, so, while
-.B select()
+.BR select ()
 can be used on the descriptor returned by
-.BR pcap_get_selectable_fd() ,
-.B poll()
+.BR pcap_get_selectable_fd (),
+.BR poll ()
 and
-.B kevent()
+.BR kevent ()
 cannot be used on it those versions of Mac OS X.
-.BR poll() ,
+.BR poll (),
 but not
-.BR kevent() ,
+.BR kevent (),
 works on that descriptor in Mac OS X releases prior to
 10.4;
-.B poll()
+.BR poll ()
 and
-.B kevent()
+.BR kevent ()
 work on that descriptor in Mac OS X 10.6 and later.
 .PP
-.B pcap_get_selectable_fd()
+.BR pcap_get_selectable_fd ()
 is not available on Windows.
 .SH RETURN VALUE
-A selectable file descriptor is returned if one exists; otherwise, \-1
+A selectable file descriptor is returned if one exists; otherwise,
+.B \-1
 is returned.
 .SH SEE ALSO
-pcap(3PCAP), pcap_get_required_select_timeout(3PCAP),
-pcap_setnonblock(3PCAP), select(2), poll(2), epoll_wait(2), kqueue(2)
+.BR pcap (3PCAP),
+.BR kqueue (2)
diff --git a/pcap_get_tstamp_precision.3pcap b/pcap_get_tstamp_precision.3pcap
deleted file mode 100644
index 709147a..0000000
--- a/pcap_get_tstamp_precision.3pcap
+++ /dev/null
@@ -1,52 +0,0 @@
-.\"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 285e770..7dbb569 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 "18 December 2013"
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "23 August 2018"
 .SH NAME
 pcap_get_tstamp_precision \- get the time stamp precision returned in
 captures
@@ -34,11 +34,11 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_get_tstamp_precision()
+.BR 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()
+.BR pcap_get_tstamp_precision ()
 returns
 .B PCAP_TSTAMP_PRECISION_MICRO
 or
@@ -46,7 +46,11 @@
 which indicates
 that pcap captures contains time stamps in microseconds or nanoseconds
 respectively.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1.  In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
 .SH SEE ALSO
-pcap(3PCAP),
-pcap_set_tstamp_precision(3PCAP),
-pcap-tstamp(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_set_tstamp_precision (3PCAP),
+.BR pcap-tstamp (@MAN_MISC_INFO@)
diff --git a/pcap_geterr.3pcap b/pcap_geterr.3pcap
index ee681c8..72e23e3 100644
--- a/pcap_geterr.3pcap
+++ b/pcap_geterr.3pcap
@@ -32,7 +32,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_geterr()
+.BR pcap_geterr ()
 returns the error text pertaining to the last pcap library error.
 .BR NOTE :
 the pointer it returns will no longer point to a valid error message
@@ -42,10 +42,10 @@
 the
 .BR pcap_t .
 .PP
-.B pcap_perror()
+.BR pcap_perror ()
 prints the text of the last pcap library error on
 .BR stderr ,
 prefixed by
 .IR prefix .
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_init.3pcap b/pcap_init.3pcap
new file mode 100644
index 0000000..543f083
--- /dev/null
+++ b/pcap_init.3pcap
@@ -0,0 +1,99 @@
+.\" 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_INIT 3PCAP "11 April 2020"
+.SH NAME
+pcap_init \- initialize the library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_init(unsigned int opts, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.BR pcap_init ()
+is used to initialize the Packet Capture library.
+.I opts
+specifies options for the library;
+currently, the options are:
+.TP
+.B PCAP_CHAR_ENC_LOCAL
+Treat all strings supplied as arguments, and return all strings to the
+caller, as being in the local character encoding.
+.TP
+.B PCAP_CHAR_ENC_UTF_8
+Treat all strings supplied as arguments, and return all strings to the
+caller, as being in UTF-8.
+.PP
+On UNIX-like systems, the local character encoding is assumed to be
+UTF-8, so no character encoding transformations are done.
+.PP
+On Windows, the local character encoding is the local ANSI code page.
+.PP
+If
+.BR pcap_init ()
+is not called, strings are treated as being in the local ANSI code page
+on Windows,
+.BR pcap_lookupdev (3PCAP)
+will succeed if there is a device on which to capture, and
+.BR pcap_create (3PCAP)
+makes an attempt to check whether the string passed as an argument is a
+UTF-16LE string - note that this attempt is unsafe, as it may run past
+the end of the string - to handle
+.BR pcap_lookupdev ()
+returning a UTF-16LE string. Programs that don't call
+.BR pcap_init ()
+should, on Windows, call
+.BR pcap_wsockinit ()
+to initialize Winsock; this is not necessary if
+.BR pcap_init ()
+is called, as
+.BR pcap_init ()
+will initialize Winsock itself on Windows.
+.SH RETURN VALUE
+.BR pcap_init ()
+returns
+.B 0
+on success and
+.B \-1
+on failure.
+If
+.B \-1
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.10.0.  In previous
+releases, on Windows, all strings supplied as arguments, and all strings
+returned to the caller, are in the local character encoding.
+.SH SEE ALSO
+.BR pcap (3PCAP)
diff --git a/pcap_inject.3pcap b/pcap_inject.3pcap
index ff9792d..6b4554e 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 "3 January 2014"
+.TH PCAP_INJECT 3PCAP "25 July 2018"
 .SH NAME
 pcap_inject, pcap_sendpacket \- transmit a packet
 .SH SYNOPSIS
@@ -32,7 +32,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_inject()
+.BR pcap_inject ()
 sends a raw packet through the network interface;
 .I buf
 points to the data of the packet, including the link-layer header, and
@@ -42,7 +42,7 @@
 Note that, even if you successfully open the network interface, you
 might not have permission to send packets on it, or it might not support
 sending packets; as
-.I pcap_open_live()
+.BR pcap_open_live (3PCAP)
 doesn't have a flag to indicate whether to open for capturing, sending,
 or capturing and sending, you cannot request an open that supports
 sending and be notified at open time whether sending will be possible.
@@ -51,7 +51,7 @@
 Note that, on some platforms, the link-layer header of the packet that's
 sent might not be the same as the link-layer header of the packet
 supplied to
-.BR pcap_inject() ,
+.BR pcap_inject (),
 as the source link-layer address, if the header contains such an
 address, might be changed to be the address assigned to the interface on
 which the packet it sent, if the platform doesn't support sending
@@ -61,28 +61,38 @@
 .I do
 nominally support sending completely raw and unchanged packets.
 .PP
-.B pcap_sendpacket()
+.BR pcap_sendpacket ()
 is like
-.BR pcap_inject() ,
-but it returns 0 on success, rather than returning the number of bytes
+.BR pcap_inject (),
+but it returns
+.B 0
+on success, rather than returning the number of bytes
 written.
-.RB ( pcap_inject()
+.RB ( pcap_inject ()
 comes from OpenBSD;
-.B pcap_sendpacket()
-comes from WinPcap.  Both are provided for compatibility.)
+.BR pcap_sendpacket ()
+comes from WinPcap/Npcap.  Both are provided for compatibility.)
 .SH RETURN VALUE
-.B pcap_inject()
-returns the number of bytes written on success and \-1 on failure.
+.BR pcap_inject ()
+returns the number of bytes written on success and
+.B PCAP_ERROR
+on failure.
 .PP
-.B pcap_sendpacket()
-returns 0 on success and \-1 on failure.
+.BR pcap_sendpacket ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure.
 .PP
-If \-1 is returned,
-.B pcap_geterr()
+If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_is_swapped.3pcap b/pcap_is_swapped.3pcap
index 36691d3..260601a 100644
--- a/pcap_is_swapped.3pcap
+++ b/pcap_is_swapped.3pcap
@@ -31,21 +31,21 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_is_swapped()
-returns true (1) if
+.BR pcap_is_swapped ()
+returns true (\fB1\fP) if
 .I p
 refers to a ``savefile'' that uses a different byte order
 than the current system.  For a live capture, it always returns false
-(0).
+(\fB0\fP).
 .PP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.BR \%pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate (3PCAP).
 .SH RETURN VALUE
-.B pcap_is_swapped()
-returns true (1) or false (0) on success and
+.BR pcap_is_swapped ()
+returns true (\fB1\fP) or false (\fB0\fP) 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)
+.BR pcap (3PCAP)
diff --git a/pcap_lib_version.3pcap b/pcap_lib_version.3pcap
index 4b86b2d..73ed2b8 100644
--- a/pcap_lib_version.3pcap
+++ b/pcap_lib_version.3pcap
@@ -31,9 +31,9 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_lib_version()
+.BR pcap_lib_version ()
 returns a pointer to a string giving information about the version of
 the libpcap library being used; note that it contains more information
 than just a version number.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_list_datalinks.3pcap b/pcap_list_datalinks.3pcap
deleted file mode 100644
index 1fde73d..0000000
--- a/pcap_list_datalinks.3pcap
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" 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 9f52b63..d6e3149 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 "8 March 2015"
+.TH PCAP_LIST_DATALINKS 3PCAP "25 July 2018"
 .SH NAME
 pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
 types supported by a capture device, and free that list
@@ -33,41 +33,41 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_list_datalinks()
+.BR 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()
+.BR 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() ,
+.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()
+.BR \%pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate (3PCAP).
 .SH RETURN VALUE
-.B pcap_list_datalinks()
+.BR 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.
+on other errors.
 If
 .B PCAP_ERROR
 is returned,
-.B pcap_geterr()
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR \%pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP),
-pcap_datalink_val_to_name(3PCAP),
-pcap-linktype(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_datalink_val_to_name (3PCAP),
+.BR pcap-linktype (@MAN_MISC_INFO@)
diff --git a/pcap_list_tstamp_types.3pcap b/pcap_list_tstamp_types.3pcap
deleted file mode 100644
index 4afa36f..0000000
--- a/pcap_list_tstamp_types.3pcap
+++ /dev/null
@@ -1,70 +0,0 @@
-.\"
-.\" 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 a139324..74ef00a 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 "22 August 2010"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "8 September 2019"
 .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
@@ -34,10 +34,10 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_list_tstamp_types()
+.BR 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()
+.BR pcap_list_tstamp_types ()
 allocates an array to hold the list and sets
 .I *tstamp_typesp
 to point to the array.
@@ -46,25 +46,37 @@
 for a list of all the time stamp types.
 .PP
 The caller is responsible for freeing the array with
-.BR pcap_free_tstamp_types() ,
+.BR pcap_free_tstamp_types (),
 which frees the list pointed to by
 .IR tstamp_types .
 .SH RETURN VALUE
-.B pcap_list_tstamp_types()
+.BR 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.
+A return value of one means that the only time stamp type supported is
+the one in the list, which is the capture device's default time stamp
+type.  A return value of zero means that the only time stamp type
+supported is
+.BR PCAP_TSTAMP_HOST ,
+which is the capture device's default time stamp type (only older
+versions of libpcap will return that; newer versions will always return
+one or more types).
 If
 .B PCAP_ERROR
 is returned,
-.B pcap_geterr()
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1.  In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
-pcap-tstamp(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_tstamp_type_val_to_name (3PCAP),
+.BR pcap-tstamp (@MAN_MISC_INFO@)
diff --git a/pcap_lookupdev.3pcap b/pcap_lookupdev.3pcap
index eb493ba..b5d548f 100644
--- a/pcap_lookupdev.3pcap
+++ b/pcap_lookupdev.3pcap
@@ -39,22 +39,30 @@
 .B This interface is obsoleted by
 .BR pcap_findalldevs (3PCAP).
 To find a default device on which to capture, call
-.B pcap_findalldevs()
+.BR pcap_findalldevs ()
 and, if the list it returns is not empty, use the first device in the
 list.  (If the list is empty, there are no devices on which capture is
 possible.)
 .LP
-.B pcap_lookupdev()
+.B If
+.BR pcap_init (3PCAP)
+.B has been called, this interface always returns
+.BR NULL .
+.LP
+.BR pcap_lookupdev ()
 returns a pointer to a string giving the name of a network device
 suitable for use with
-.B pcap_create()
+.BR pcap_create (3PCAP)
 and
-.BR pcap_activate() ,
+.BR \%pcap_activate (3PCAP),
 or with
-.BR pcap_open_live() ,
+.BR pcap_open_live (3PCAP),
 and with
-.BR pcap_lookupnet() .
+.BR pcap_lookupnet (3PCAP).
 If there is an error,
+or if
+.BR pcap_init (3PCAP)
+has been called,
 .B NULL
 is returned and
 .I errbuf
@@ -64,17 +72,15 @@
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP), pcap_lookupnet(3PCAP)
+.BR pcap (3PCAP)
 .SH BUGS
 The pointer returned by
-.B pcap_lookupdev()
+.BR pcap_lookupdev ()
 points to a static buffer; subsequent calls to
-.B pcap_lookupdev()
+.BR pcap_lookupdev ()
 in the same thread, or calls to
-.B pcap_lookupdev()
+.BR pcap_lookupdev ()
 in another thread, may overwrite that buffer.
 .LP
-In WinPcap, this function may return a UTF-16 string rather than an
-ASCII or UTF-8 string.
-
+In WinPcap and Npcap, this function may return a UTF-16 string rather
+than an ASCII or UTF-8 string.
diff --git a/pcap_lookupnet.3pcap b/pcap_lookupnet.3pcap
index c38ff3a..c12fa55 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 "3 January 2014"
+.TH PCAP_LOOKUPNET 3PCAP "25 July 2018"
 .SH NAME
 pcap_lookupnet \- find the IPv4 network number and netmask for a device
 .SH SYNOPSIS
@@ -38,7 +38,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_lookupnet()
+.BR pcap_lookupnet ()
 is used to determine the IPv4 network number and mask
 associated with the network device
 .IR device .
@@ -50,9 +50,14 @@
 .I bpf_u_int32
 pointers.
 .SH RETURN VALUE
-.B pcap_lookupnet()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
+.BR pcap_lookupnet ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
 .I errbuf
 is filled in with an appropriate error message.
 .I errbuf
@@ -60,4 +65,4 @@
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_loop.3pcap b/pcap_loop.3pcap
index 4679b46..3d741ef 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 "20 January 2017"
+.TH PCAP_LOOP 3PCAP "22 August 2020"
 .SH NAME
 pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
 .SH SYNOPSIS
@@ -42,28 +42,32 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_loop()
+.BR pcap_loop ()
 processes packets from a live capture or ``savefile'' until
 .I cnt
 packets are processed, the end of the ``savefile'' is
 reached when reading from a ``savefile'',
-.B pcap_breakloop()
+.BR pcap_breakloop (3PCAP)
 is called, or an error occurs.
 It does
 .B not
 return when live packet buffer timeouts occur.
-A value of \-1 or 0 for
+A value of
+.B \-1
+or
+.B 0
+for
 .I cnt
 is equivalent to infinity, so that packets are processed until another
 ending condition occurs.
 .PP
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 processes packets from a live capture or ``savefile'' until
 .I cnt
 packets are processed, the end of the current bufferful of packets is
 reached when doing a live capture, the end of the ``savefile'' is
 reached when reading from a ``savefile'',
-.B pcap_breakloop()
+.BR pcap_breakloop ()
 is called, or an error occurs.
 Thus, when doing a live capture,
 .I cnt
@@ -71,7 +75,11 @@
 a minimum number; when reading a live capture, only one
 bufferful of packets is read at a time, so fewer than
 .I cnt
-packets may be processed. A value of \-1 or 0 for
+packets may be processed. A value of
+.B \-1
+or
+.B 0
+for
 .I cnt
 causes all the packets received in one buffer to be processed when
 reading a live capture, and causes all the packets in the file to be
@@ -79,20 +87,11 @@
 .PP
 Note that, when doing a live capture on some platforms, if the read
 timeout expires when there are no packets available,
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 will return 0, even when not in non-blocking mode, as there are no
 packets to process.  Applications should be prepared for this to happen,
 but must not rely on it happening.
 .PP
-.ft B
-(In older versions of libpcap, the behavior when
-\fIcnt\fP
-was 0 was undefined; different platforms and devices behaved
-differently, so code that must work with older versions of libpcap
-should use \-1, not 0, as the value of
-\fIcnt\fP.)
-.ft R
-.PP
 .I callback
 specifies a
 .I pcap_handler
@@ -102,9 +101,9 @@
 pointer which is passed in the
 .I user
 argument to
-.B pcap_loop()
+.BR pcap_loop ()
 or
-.BR pcap_dispatch() ,
+.BR pcap_dispatch (),
 a
 .I const struct pcap_pkthdr
 pointer pointing to the packet time stamp and lengths, and a
@@ -123,25 +122,25 @@
 .PP
 The bytes of data from the packet begin with a link-layer header.  The
 format of the link-layer header is indicated by the return value of the
-.B pcap_datalink()
+.BR pcap_datalink (3PCAP)
 routine when handed the
 .B pcap_t
 value also passed to
-.B pcap_loop()
+.BR pcap_loop ()
 or
-.BR pcap_dispatch() .
+.BR pcap_dispatch ().
 .I https://www.tcpdump.org/linktypes.html
 lists the values
-.B pcap_datalink()
+.BR pcap_datalink ()
 can return and describes the packet formats that
 correspond to those values.  The value it returns will be valid for all
 packets received unless and until
-.B pcap_set_datalink()
+.BR pcap_set_datalink (3PCAP)
 is called; after a successful call to
-.BR pcap_set_datalink() ,
+.BR pcap_set_datalink (),
 all subsequent packets will have a link-layer header of the type
 specified by the link-layer header type value passed to
-.BR pcap_set_datalink() .
+.BR pcap_set_datalink ().
 .PP
 Do
 .B NOT
@@ -151,25 +150,32 @@
 for Ethernet.  For example, the "any" device on Linux will have a
 link-layer header type of
 .B DLT_LINUX_SLL
+or
+.B DLT_LINUX_SLL2
 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_loop()
-returns 0 if
+.BR pcap_loop ()
+returns
+.B 0
+if
 .I cnt
 is exhausted or if, when reading from a ``savefile'', no more packets
-are available.  It returns \-1 if an error occurs or \-2 if the loop
-terminated due to a call to
-.B pcap_breakloop()
+are available.  It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
+.BR pcap_breakloop ()
 before any packets were processed.
 It does
 .B not
 return when live packet buffer timeouts occur; instead, it attempts to
 read more packets.
 .PP
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 returns the number of packets processed on success; this can be 0 if no
 packets were read from a live capture (if, for example, they were
 discarded because they didn't pass the packet filter, or if, on
@@ -177,23 +183,40 @@
 packets arrive, the timeout expires before any packets arrive, or if the
 file descriptor for the capture device is in non-blocking mode and no
 packets were available to be read) or if no more packets are available
-in a ``savefile.'' It returns \-1 if an error occurs or \-2 if the loop
-terminated due to a call to
-.B pcap_breakloop()
+in a ``savefile.'' It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
+.BR pcap_breakloop ()
 before any packets were processed.
 .ft B
 If your application uses pcap_breakloop(),
-make sure that you explicitly check for \-1 and \-2, rather than just
-checking for a return value < 0.
+make sure that you explicitly check for PCAP_ERROR and PCAP_ERROR_BREAK,
+rather than just checking for a return value < 0.
 .ft R
 .PP
-If \-1 is returned,
-.B pcap_geterr()
+If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+In libpcap versions before 1.5.0, the behavior when
+.I cnt
+was
+.B 0
+was undefined; different platforms and devices behaved differently,
+so code that must work with these versions of libpcap should use
+.BR \-1 ,
+not
+.BR 0 ,
+as the value of
+.IR cnt .
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP),
-pcap_datalink(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_major_version.3pcap b/pcap_major_version.3pcap
index 2fedfd2..393705b 100644
--- a/pcap_major_version.3pcap
+++ b/pcap_major_version.3pcap
@@ -35,9 +35,9 @@
 If
 .I p
 refers to a ``savefile'',
-.B pcap_major_version()
+.BR pcap_major_version ()
 returns the major number of the file format of the ``savefile'' and
-.B pcap_minor_version()
+.BR pcap_minor_version ()
 returns the minor number of the file format of the ``savefile''.  The
 version number is stored in the ``savefile''; note that the meaning of
 its values depends on the type of ``savefile'' (for example, pcap or
@@ -46,9 +46,9 @@
 If
 .I p
 refers to a live capture, the values returned by
-.B pcap_major_version()
+.BR pcap_major_version ()
 and
-.B pcap_minor_version()
+.BR pcap_minor_version ()
 are not meaningful.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_next_ex.3pcap b/pcap_next_ex.3pcap
index 88e8314..2bd1a42 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 "20 January 2017"
+.TH PCAP_NEXT_EX 3PCAP "25 July 2018"
 .SH NAME
 pcap_next_ex, pcap_next \- read the next packet from a pcap_t
 .SH SYNOPSIS
@@ -34,7 +34,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_next_ex()
+.BR pcap_next_ex ()
 reads the next packet and returns a success/failure indication.
 If the packet was read without problems, the pointer pointed to by the
 .I pkt_header
@@ -47,16 +47,16 @@
 .I struct pcap_pkthdr
 and the packet data are not to be freed by the caller, and are not
 guaranteed to be valid after the next call to
-.BR pcap_next_ex() ,
-.BR pcap_next() ,
-.BR pcap_loop() ,
+.BR pcap_next_ex (),
+.BR pcap_next (),
+.BR pcap_loop (3PCAP),
 or
-.BR pcap_dispatch() ;
+.BR pcap_dispatch (3PCAP);
 if the code needs them to remain valid, it must make a copy of them.
 .PP
-.B pcap_next()
+.BR pcap_next ()
 reads the next packet (by calling
-.B pcap_dispatch()
+.BR pcap_dispatch ()
 with a
 .I cnt
 of 1) and returns a
@@ -64,11 +64,11 @@
 pointer to the data in that packet.  The
 packet data is not to be freed by the caller, and is not
 guaranteed to be valid after the next call to
-.BR pcap_next_ex() ,
-.BR pcap_next() ,
-.BR pcap_loop() ,
+.BR pcap_next_ex (),
+.BR pcap_next (),
+.BR pcap_loop (),
 or
-.BR pcap_dispatch() ;
+.BR pcap_dispatch ();
 if the code needs it to remain valid, it must make a copy of it.
 The
 .I pcap_pkthdr
@@ -78,25 +78,25 @@
 .PP
 The bytes of data from the packet begin with a link-layer header.  The
 format of the link-layer header is indicated by the return value of the
-.B pcap_datalink()
+.BR pcap_datalink (3PCAP)
 routine when handed the
 .B pcap_t
 value also passed to
-.B pcap_loop()
+.BR pcap_loop ()
 or
-.BR pcap_dispatch() .
+.BR pcap_dispatch ().
 .I https://www.tcpdump.org/linktypes.html
 lists the values
-.B pcap_datalink()
+.BR pcap_datalink ()
 can return and describes the packet formats that
 correspond to those values.  The value it returns will be valid for all
 packets received unless and until
-.B pcap_set_datalink()
+.BR pcap_set_datalink (3PCAP)
 is called; after a successful call to
-.BR pcap_set_datalink() ,
+.BR pcap_set_datalink (),
 all subsequent packets will have a link-layer header of the type
 specified by the link-layer header type value passed to
-.BR pcap_set_datalink() .
+.BR pcap_set_datalink ().
 .PP
 Do
 .B NOT
@@ -106,25 +106,36 @@
 for Ethernet.  For example, the "any" device on Linux will have a
 link-layer header type of
 .B DLT_LINUX_SLL
+or
+.B DLT_LINUX_SLL2
 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_next_ex()
-returns 1 if the packet was read without problems, 0 if packets are
+.BR pcap_next_ex ()
+returns
+.B 1
+if the packet was read without problems,
+.B 0
+if packets are
 being read from a live capture and the packet buffer timeout expired,
-\-1 if an error occurred while reading the packet, and \-2 if packets
+.B PCAP_ERROR
+if an error occurred while reading the packet, and
+.B PCAP_ERROR_BREAK
+if packets
 are being read from a ``savefile'' and there are no more packets to read
-from the savefile.  If \-1 is returned,
-.B pcap_geterr()
+from the savefile.  If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .PP
-.B pcap_next()
+.BR pcap_next ()
 returns a pointer to the packet data on success, and returns
 .B NULL
 if an error occurred, or if no packets were read from a live capture
@@ -136,5 +147,4 @@
 more packets are available in a ``savefile.'' Unfortunately, there is no
 way to determine whether an error occurred or not.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP),
-pcap_datalink(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_offline_filter.3pcap b/pcap_offline_filter.3pcap
index 08c0b66..dbb6e96 100644
--- a/pcap_offline_filter.3pcap
+++ b/pcap_offline_filter.3pcap
@@ -33,13 +33,13 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_offline_filter()
+.BR pcap_offline_filter ()
 checks whether a filter matches a packet.
 .I fp
 is a pointer to a
 .I bpf_program
 struct, usually the result of a call to
-.BR pcap_compile() .
+.BR pcap_compile (3PCAP).
 .I h
 points to the
 .I pcap_pkthdr
@@ -47,9 +47,9 @@
 .I pkt
 points to the data in the packet.
 .SH RETURN VALUE
-.B pcap_offline_filter()
+.BR pcap_offline_filter ()
 returns the return value of the filter program.  This will be zero if
 the packet doesn't match the filter and non-zero if the packet matches
 the filter.
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_open_dead.3pcap b/pcap_open_dead.3pcap
deleted file mode 100644
index 118c533..0000000
--- a/pcap_open_dead.3pcap
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" 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 621e75b..ced7d6c 100644
--- a/pcap_open_dead.3pcap.in
+++ b/pcap_open_dead.3pcap.in
@@ -35,18 +35,18 @@
 .fi
 .SH DESCRIPTION
 .PP
-.B pcap_open_dead()
+.BR pcap_open_dead ()
 and
-.B pcap_open_dead_with_tstamp_precision()
+.BR 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() ,
+.BR pcap_dump_open (3PCAP),
+.BR pcap_dump (3PCAP),
 and
-.B pcap_dump_close()
+.BR pcap_dump_close (3PCAP)
 to write a savefile if there is no
 .B pcap_t
 that supplies the packets to be written.
@@ -60,11 +60,11 @@
 .BR pcap_t .
 .PP
 When
-.BR pcap_open_dead_with_tstamp_precision() ,
+.BR pcap_open_dead_with_tstamp_precision (),
 is used to create a
 .B pcap_t
 for use with
-.BR pcap_dump_open() ,
+.BR pcap_dump_open (),
 .I precision
 specifies the time stamp precision for packets;
 .B PCAP_TSTAMP_PRECISION_MICRO
@@ -73,7 +73,13 @@
 .B PCAP_TSTAMP_PRECISION_NANO
 should be specified if the packets to be written have time stamps in
 seconds and nanoseconds.  Its value does not affect
-.BR pcap_compile() .
+.BR pcap_compile (3PCAP).
+.SH BACKWARD COMPATIBILITY
+The
+.BR pcap_open_dead_with_tstamp_precision ()
+function became available in libpcap release 1.5.1.  In previous
+releases, there was no mechanism to open a savefile for writing with
+time stamps given in seconds and nanoseconds.
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
-\%pcap-linktype(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR \%pcap-linktype (@MAN_MISC_INFO@)
diff --git a/pcap_open_live.3pcap b/pcap_open_live.3pcap
index 942d4fc..b8c1729 100644
--- a/pcap_open_live.3pcap
+++ b/pcap_open_live.3pcap
@@ -38,7 +38,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_open_live()
+.BR pcap_open_live ()
 is used to obtain a packet capture handle to look
 at packets on the network.
 .I device
@@ -53,7 +53,10 @@
 specifies the snapshot length to be set on the handle.
 .PP
 .I promisc
-specifies if the interface is to be put into promiscuous mode.
+specifies whether the interface is to be put into promiscuous mode.
+If
+.I promisc
+is non-zero, promiscuous mode will be set, otherwise it will not be set.
 .PP
 .I to_ms
 specifies the packet buffer timeout, as a non-negative value, in
@@ -61,7 +64,7 @@
 .BR pcap (3PCAP)
 for an explanation of the packet buffer timeout.)
 .SH RETURN VALUE
-.B pcap_open_live()
+.BR pcap_open_live ()
 returns a
 .I pcap_t *
 on success and
@@ -74,11 +77,11 @@
 is filled in with an appropriate error message.
 .I errbuf
 may also be set to warning text when
-.B pcap_open_live()
+.BR pcap_open_live ()
 succeeds; to detect this case the caller should store a zero-length string in
 .I errbuf
 before calling
-.B pcap_open_live()
+.BR pcap_open_live ()
 and display the warning to the user if
 .I errbuf
 is no longer a zero-length string.
@@ -87,4 +90,5 @@
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_open_offline.3pcap b/pcap_open_offline.3pcap
deleted file mode 100644
index 3c59372..0000000
--- a/pcap_open_offline.3pcap
+++ /dev/null
@@ -1,109 +0,0 @@
-.\" 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 "8 January 2018 "
-.SH NAME
-pcap_open_offline, pcap_open_offline_with_tstamp_precision,
-pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
-.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 pcapng file format, although not all pcapng 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 d0cd161..5e878fe 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 "8 January 2018 "
+.TH PCAP_OPEN_OFFLINE 3PCAP "23 August 2018"
 .SH NAME
 pcap_open_offline, pcap_open_offline_with_tstamp_precision,
 pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
@@ -42,9 +42,9 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_open_offline()
+.BR pcap_open_offline ()
 and
-.B pcap_open_offline_with_tstamp_precision()
+.BR pcap_open_offline_with_tstamp_precision ()
 are called to open a ``savefile'' for reading.
 .PP
 .I fname
@@ -60,7 +60,7 @@
 The name "-" is a synonym for
 .BR stdin .
 .PP
-.B pcap_open_offline_with_tstamp_precision()
+.BR pcap_open_offline_with_tstamp_precision ()
 takes an additional
 .I precision
 argument specifying the time stamp precision desired;
@@ -76,21 +76,22 @@
 necessary before being supplied.
 .PP
 Alternatively, you may call
-.B pcap_fopen_offline()
+.BR pcap_fopen_offline ()
 or
-.B pcap_fopen_offline_with_tstamp_precision()
+.BR 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
+.BR 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() ,
+.BR pcap_open_offline (),
+.BR pcap_open_offline_with_tstamp_precision (),
+.BR pcap_fopen_offline (),
 and
-.B pcap_fopen_offline_with_tstamp_precision()
+.BR pcap_fopen_offline_with_tstamp_precision ()
 return a
 .I pcap_t *
 on success and
@@ -105,5 +106,12 @@
 is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
+.SH BACKWARD COMPATIBILITY
+.BR pcap_open_offline_with_tstamp_precision ()
+and
+.BR pcap_fopen_offline_with_tstamp_precision ()
+became available in libpcap release 1.5.1.  In previous releases, time
+stamps from a savefile are always given in seconds and microseconds.
 .SH SEE ALSO
-pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@)
+.BR pcap (3PCAP),
+.BR pcap-savefile (@MAN_FILE_FORMATS@)
diff --git a/pcap_set_buffer_size.3pcap b/pcap_set_buffer_size.3pcap
index 684f739..49492c0 100644
--- a/pcap_set_buffer_size.3pcap
+++ b/pcap_set_buffer_size.3pcap
@@ -31,15 +31,19 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_buffer_size()
+.BR pcap_set_buffer_size ()
 sets the buffer size that will be used on a capture handle when
 the handle is activated to
 .IR buffer_size ,
 which is in units of bytes.
 .SH RETURN VALUE
-.B pcap_set_buffer_size()
-returns 0 on success or
+.BR pcap_set_buffer_size ()
+returns
+.B 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)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_set_datalink.3pcap b/pcap_set_datalink.3pcap
index 24d57a5..14e9d20 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 "3 January 2014"
+.TH PCAP_SET_DATALINK 3PCAP "25 July 2018"
 .SH NAME
 pcap_set_datalink \- set the link-layer header type to be used by a
 capture device
@@ -32,20 +32,25 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_datalink()
+.BR pcap_set_datalink ()
 is used to set the current link-layer header type of the pcap descriptor
 to the type specified by
 .IR dlt .
 .SH RETURN VALUE
-.B pcap_set_datalink()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+.BR pcap_set_datalink ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP),
-pcap_datalink_name_to_val(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_datalink_name_to_val (3PCAP)
diff --git a/pcap_set_immediate_mode.3pcap b/pcap_set_immediate_mode.3pcap
deleted file mode 100644
index b3ad243..0000000
--- a/pcap_set_immediate_mode.3pcap
+++ /dev/null
@@ -1,47 +0,0 @@
-.\"
-.\" 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_IMMEDIATE_MODE 3PCAP "5 December 2013"
-.SH NAME
-pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
-handle
-.SH SYNOPSIS
-.nf
-.ft B
-#include <pcap/pcap.h>
-.LP
-.ft B
-int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
-.ft
-.fi
-.SH DESCRIPTION
-.B pcap_set_immediate_mode()
-sets whether immediate mode should be set on a capture handle when
-the handle is activated.
-If
-.I immediate_mode
-is non-zero, immediate mode will be set, otherwise it will not be set.
-.SH RETURN VALUE
-.B pcap_set_immediate_mode()
-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)
diff --git a/pcap_set_immediate_mode.3pcap.in b/pcap_set_immediate_mode.3pcap.in
new file mode 100644
index 0000000..e493d55
--- /dev/null
+++ b/pcap_set_immediate_mode.3pcap.in
@@ -0,0 +1,99 @@
+.\"
+.\" 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_IMMEDIATE_MODE 3PCAP "23 August 2018"
+.SH NAME
+pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
+.ft
+.fi
+.SH DESCRIPTION
+.BR pcap_set_immediate_mode ()
+sets whether immediate mode should be set on a capture handle when
+the handle is activated.  In immediate mode, packets are always
+delivered as soon as they arrive, with no buffering.
+If
+.I immediate_mode
+is non-zero, immediate mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.BR pcap_set_immediate_mode ()
+returns
+.B 0
+on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.5.0.  In previous
+releases, if immediate delivery of packets is required:
+.IP
+on FreeBSD, NetBSD, OpenBSD, DragonFly BSD, macOS, and Solaris 11,
+immediate mode must be turned on with a
+.B BIOCIMMEDIATE
+.BR ioctl (2),
+as documented in
+.BR bpf (@MAN_DEVICES@),
+on the descriptor returned by
+.BR pcap_fileno (3PCAP),
+after
+.BR pcap_activate (3PCAP)
+is called;
+.IP
+on Solaris 10 and earlier versions of Solaris, immediate mode must be
+turned on by using a read timeout of 0 when opening the device (this
+will not provide immediate delivery of packets on other platforms, so
+don't assume it's sufficient);
+.IP
+on Digital UNIX/Tru64 UNIX, immediate mode must be turned on by doing a
+.B BIOCMBIC
+.BR ioctl ,
+as documented in
+.BR packetfilter (7),
+to clear the
+.B ENBATCH
+flag on the descriptor returned by
+.BR pcap_fileno (3PCAP),
+after
+.BR pcap_activate (3PCAP)
+is called;
+.IP
+on Windows, immediate mode must be turned on by calling
+.BR pcap_setmintocopy ()
+with a size of 0.
+.PP
+On Linux, with previous releases of libpcap, capture devices are always
+in immediate mode; however, in 1.5.0 and later, they are, by default,
+.B not
+in immediate mode, so if
+.BR pcap_set_immediate_mode ()
+is available, it should be used.
+.PP
+On other platforms, capture devices are always in immediate mode.
+.SH SEE ALSO
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_set_promisc.3pcap b/pcap_set_promisc.3pcap
index fcd797a..cfc6cdd 100644
--- a/pcap_set_promisc.3pcap
+++ b/pcap_set_promisc.3pcap
@@ -31,16 +31,20 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_promisc()
+.BR pcap_set_promisc ()
 sets whether promiscuous mode should be set on a capture handle when
 the handle is activated.
 If
 .I promisc
 is non-zero, promiscuous mode will be set, otherwise it will not be set.
 .SH RETURN VALUE
-.B pcap_set_promisc()
-returns 0 on success or
+.BR pcap_set_promisc ()
+returns
+.B 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)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_set_protocol_linux.3pcap b/pcap_set_protocol_linux.3pcap
index 40eb8d2..a891d74 100644
--- a/pcap_set_protocol_linux.3pcap
+++ b/pcap_set_protocol_linux.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_PROTOCOL_LINUX 3PCAP "24 August 2017"
+.TH PCAP_SET_PROTOCOL_LINUX 3PCAP "22 August 2018"
 .SH NAME
 pcap_set_protocol_linux \- set capture protocol for a not-yet-activated
 capture handle
@@ -32,7 +32,7 @@
 .fi
 .SH DESCRIPTION
 On network interface devices on Linux,
-.B pcap_set_protocol_linux()
+.BR pcap_set_protocol_linux ()
 sets the protocol to be used in the
 .BR socket (2)
 call to create a capture socket when the handle is activated.  The
@@ -48,20 +48,25 @@
 .LP
 It should not be used in portable code; instead, a filter should be
 specified with
-.BR pcap_setfilter() .
+.BR pcap_setfilter (3PCAP).
 .LP
 If a given network interface provides a standard link-layer header, with
 a standard packet type, but provides some packet types with a different
 socket-layer protocol type from the one in the link-layer header, that
 packet type cannot be filtered with a filter specified with
-.B pcap_setfilter()
+.BR pcap_setfilter ()
 but can be filtered by specifying the socket-layer protocol type using
-.BR pcap_set_protocol_linux() .
+.BR pcap_set_protocol_linux ().
 .SH RETURN VALUE
-.B pcap_set_protocol_linux()
-returns 0 on success or
+.BR pcap_set_protocol_linux ()
+returns
+.B 0
+on success or
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), socket(2),
-pcap_setfilter(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_set_rfmon.3pcap b/pcap_set_rfmon.3pcap
index 691518a..2b104c2 100644
--- a/pcap_set_rfmon.3pcap
+++ b/pcap_set_rfmon.3pcap
@@ -31,17 +31,21 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_rfmon()
+.BR pcap_set_rfmon ()
 sets whether monitor mode should be set on a capture handle when
 the handle is activated.
 If
 .I rfmon
 is non-zero, monitor mode will be set, otherwise it will not be set.
 .SH RETURN VALUE
-.B pcap_set_rfmon()
-returns 0 on success or
+.BR pcap_set_rfmon ()
+returns
+.B 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_can_set_rfmon(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP),
+.BR pcap_can_set_rfmon (3PCAP)
diff --git a/pcap_set_snaplen.3pcap b/pcap_set_snaplen.3pcap
index 44eb154..e3acff1 100644
--- a/pcap_set_snaplen.3pcap
+++ b/pcap_set_snaplen.3pcap
@@ -31,14 +31,18 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_snaplen()
+.BR pcap_set_snaplen ()
 sets the snapshot length to be used on a capture handle when the handle
 is activated to
 .IR snaplen .
 .SH RETURN VALUE
-.B pcap_set_snaplen()
-returns 0 on success or
+.BR pcap_set_snaplen ()
+returns
+.B 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)
+.BR pcap (3PCAP),
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP)
diff --git a/pcap_set_timeout.3pcap b/pcap_set_timeout.3pcap
index cacf603..d909b2c 100644
--- a/pcap_set_timeout.3pcap
+++ b/pcap_set_timeout.3pcap
@@ -31,7 +31,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_timeout()
+.BR pcap_set_timeout ()
 sets the packet buffer timeout that will be used on a capture handle
 when the handle is activated to
 .IR to_ms ,
@@ -44,10 +44,13 @@
 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
+.BR pcap_set_timeout ()
+returns
+.B 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_set_immediate_mode(3PCAP)
+.BR pcap_create (3PCAP),
+.BR pcap_activate (3PCAP),
+.BR \%pcap_set_immediate_mode (3PCAP)
diff --git a/pcap_set_tstamp_precision.3pcap b/pcap_set_tstamp_precision.3pcap
deleted file mode 100644
index 773aa32..0000000
--- a/pcap_set_tstamp_precision.3pcap
+++ /dev/null
@@ -1,61 +0,0 @@
-.\"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 57c4ea3..eb449d5 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 "5 February 2015"
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "23 August 2018"
 .SH NAME
 pcap_set_tstamp_precision \- set the time stamp precision returned in
 captures
@@ -34,28 +34,35 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_tstamp_precision()
+.BR 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()
+.BR pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR pcap_activate (3PCAP).
 Two time stamp precisions are supported, microseconds and nanoseconds. One can
 use options
 .B PCAP_TSTAMP_PRECISION_MICRO and
 .B PCAP_TSTAMP_PRECISION_NANO
 to request desired precision. By default, time stamps are in microseconds.
 .SH RETURN VALUE
-.B pcap_set_tstamp_precision()
-returns 0 on success if the specified time stamp precision is expected to be
-supported by the operating system,
+.BR pcap_set_tstamp_precision ()
+returns
+.B 0
+on success if the specified time stamp precision is expected to be
+supported by the capture device,
 .B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
-if operating system does not support requested time stamp precision,
+if the capture device does not support the requested time stamp
+precision,
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1.  In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
 .SH SEE ALSO
-pcap(3PCAP),
-pcap_get_tstamp_precision(3PCAP),
-pcap-tstamp(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_get_tstamp_precision (3PCAP),
+.BR pcap-tstamp (@MAN_MISC_INFO@)
diff --git a/pcap_set_tstamp_type.3pcap b/pcap_set_tstamp_type.3pcap
deleted file mode 100644
index b797c1a..0000000
--- a/pcap_set_tstamp_type.3pcap
+++ /dev/null
@@ -1,65 +0,0 @@
-.\"
-.\" 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 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 7899da3..e19d6e5 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 "5 December 2014"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "8 September 2019"
 .SH NAME
 pcap_set_tstamp_type \- set the time stamp type to be used by a
 capture device
@@ -33,23 +33,25 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_set_tstamp_type()
+.BR pcap_set_tstamp_type ()
 sets the type of time stamp desired for packets captured on the pcap
 descriptor to the type specified by
 .IR tstamp_type .
 It must be called on a pcap descriptor created by
-.B pcap_create()
+.BR pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
-.B pcap_list_tstamp_types()
+.BR pcap_activate (3PCAP).
+.BR pcap_list_tstamp_types (3PCAP)
 will give a list of the time stamp types supported by a given capture
 device.
 See
 .BR pcap-tstamp (@MAN_MISC_INFO@)
 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
+.BR pcap_set_tstamp_type ()
+returns
+.B 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
@@ -57,9 +59,14 @@
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated, and
 .B PCAP_ERROR_CANTSET_TSTAMP_TYPE
-if the capture device doesn't support setting the time stamp type.
+if the capture device doesn't support setting the time stamp type (only
+older versions of libpcap will return that; newer versions will always
+allow the time stamp type to be set to the default type).
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1.  In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
 .SH SEE ALSO
-pcap(3PCAP),
-pcap_list_tstamp_types(3PCAP),
-pcap_tstamp_type_name_to_val(3PCAP),
-pcap-tstamp(@MAN_MISC_INFO@)
+.BR pcap (3PCAP),
+.BR pcap_tstamp_type_name_to_val (3PCAP)
diff --git a/pcap_setdirection.3pcap b/pcap_setdirection.3pcap
index 11945f5..7b38845 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 "8 March 2015"
+.TH PCAP_SETDIRECTION 3PCAP "25 July 2018"
 .SH NAME
 pcap_setdirection \- set the direction for which packets will be captured
 .SH SYNOPSIS
@@ -31,7 +31,7 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_setdirection()
+.BR pcap_setdirection ()
 is used to specify a direction that packets will be captured.
 .I d
 is one of the constants
@@ -48,7 +48,7 @@
 .B PCAP_D_INOUT
 is the default setting if this function is not called.
 .PP
-.B pcap_setdirection()
+.BR pcap_setdirection ()
 isn't necessarily fully supported on all platforms; some platforms might
 return an error for all values, and some other platforms might not
 support
@@ -56,14 +56,19 @@
 .PP
 This operation is not supported if a ``savefile'' is being read.
 .SH RETURN VALUE
-.B pcap_setdirection()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+.BR pcap_setdirection ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_setfilter.3pcap b/pcap_setfilter.3pcap
index 6efd253..1e3c5a5 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 "7 April 2014"
+.TH PCAP_SETFILTER 3PCAP "25 July 2018"
 .SH NAME
 pcap_setfilter \- set the filter
 .SH SYNOPSIS
@@ -31,22 +31,27 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_setfilter()
+.BR pcap_setfilter ()
 is used to specify a filter program.
 .I fp
 is a pointer to a
 .I bpf_program
 struct, usually the result of a call to
-.BR pcap_compile() .
+.BR \%pcap_compile (3PCAP).
 .SH RETURN VALUE
-.B pcap_setfilter()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+.BR pcap_setfilter ()
+returns
+.B 0
+on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_geterr(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_setnonblock.3pcap b/pcap_setnonblock.3pcap
index 6959127..65cfea2 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 "18 October 2014"
+.TH PCAP_SETNONBLOCK 3PCAP "25 July 2018"
 .SH NAME
 pcap_setnonblock, pcap_getnonblock \- set or get the state of
 non-blocking mode on a capture device
@@ -38,38 +38,58 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_setnonblock()
+.BR pcap_setnonblock ()
 puts a capture handle into ``non-blocking'' mode, or takes it out
 of ``non-blocking'' mode, depending on whether the
 .I nonblock
 argument is non-zero or zero.  It has no effect on ``savefiles''.
-If there is an error, \-1 is returned and
+If there is an error,
+.B PCAP_ERROR
+is returned and
 .I errbuf
-is filled in with an appropriate error message; otherwise, 0 is
-returned.
+is filled in with an appropriate error message; otherwise,
+.B 0
+is returned.
+.PP
 In
 ``non-blocking'' mode, an attempt to read from the capture descriptor
 with
-.B pcap_dispatch()
-will, if no packets are currently available to be read, return 0
-immediately rather than blocking waiting for packets to arrive.
-.B pcap_loop()
+.BR pcap_dispatch (3PCAP)
 and
-.B pcap_next()
-will not work in ``non-blocking'' mode.
+.BR pcap_next_ex (3PCAP)
+will, if no packets are currently available to be read, return
+.B 0
+immediately rather than blocking waiting for packets to arrive.
+.PP
+.BR pcap_loop (3PCAP)
+will loop forever, consuming CPU time when no packets are currently
+available;
+.BR pacp_dispatch ()
+should be used instead.
+.BR pcap_next (3PCAP)
+will return
+.B NULL
+if there are no packets currently available to read;
+this is indistinguishable from an error, so
+.BR pcap_next_ex ()
+should be used instead.
 .PP
 When first activated with
-.B pcap_activate()
+.BR pcap_activate (3PCAP)
 or opened with
-.B pcap_open_live() ,
+.BR pcap_open_live (3PCAP) ,
 a capture handle is not in ``non-blocking mode''; a call to
-.B pcap_setnonblock()
+.BR pcap_setnonblock ()
 is required in order to put it into ``non-blocking'' mode.
 .SH RETURN VALUE
-.B pcap_getnonblock()
+.BR pcap_getnonblock ()
 returns the current ``non-blocking'' state of the capture descriptor; it
-always returns 0 on ``savefiles''.
-If there is an error, \-1 is returned and
+always returns
+.B 0
+on ``savefiles''.
+If there is an error,
+.B PCAP_ERROR
+is returned and
 .I errbuf
 is filled in with an appropriate error message.
 .PP
@@ -78,4 +98,6 @@
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_next_ex (3PCAP),
+.BR pcap_geterr (3PCAP)
diff --git a/pcap_snapshot.3pcap b/pcap_snapshot.3pcap
index 7af8c33..25f6e03 100644
--- a/pcap_snapshot.3pcap
+++ b/pcap_snapshot.3pcap
@@ -31,22 +31,22 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_snapshot()
+.BR pcap_snapshot ()
 returns the snapshot length specified when
-.B pcap_set_snapshot()
+.BR pcap_set_snaplen (3PCAP)
 or
-.B pcap_open_live()
+.BR pcap_open_live (3PCAP)
 was called, for a live capture, or the snapshot length from the capture
 file, for a ``savefile''.
 .PP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.BR \%pcap_create (3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate (3PCAP).
 .SH RETURN VALUE
-.B pcap_snapshot()
+.BR pcap_snapshot ()
 returns the snapshot length 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)
+.BR pcap (3PCAP)
diff --git a/pcap_stats.3pcap b/pcap_stats.3pcap
index 2dce4b5..aa03013 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 "3 January 2014"
+.TH PCAP_STATS 3PCAP "25 July 2018"
 .SH NAME
 pcap_stats \- get capture statistics
 .SH SYNOPSIS
@@ -31,13 +31,13 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_stats()
+.BR pcap_stats ()
 fills in the
 .B struct pcap_stat
 pointed to by its second argument.  The values represent
 packet statistics from the start of the run to the time of the call.
 .PP
-.B pcap_stats()
+.BR pcap_stats ()
 is supported only on live captures, not on ``savefiles''; no statistics
 are stored in ``savefiles'', so no statistics are available when reading
 from a ``savefile''.
@@ -82,16 +82,21 @@
 statistic is unavailable, so it should not be treated as an indication
 that the interface did not drop any packets.
 .SH RETURN VALUE
-.B pcap_stats()
-returns 0 on success and returns \-1 if there is an error or if
+.BR pcap_stats ()
+returns
+.B 0
+on success and returns
+.B PCAP_ERROR
+if there is an error or if
 .I p
-doesn't support packet statistics.
-If \-1 is returned,
-.B pcap_geterr()
+doesn't support packet statistics. If
+.B PCAP_ERROR
+is returned,
+.BR pcap_geterr (3PCAP)
 or
-.B pcap_perror()
+.BR pcap_perror (3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_statustostr.3pcap b/pcap_statustostr.3pcap
index 9c2057a..c679e36 100644
--- a/pcap_statustostr.3pcap
+++ b/pcap_statustostr.3pcap
@@ -31,11 +31,11 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_statustostr()
+.BR pcap_statustostr ()
 converts a
 .B PCAP_ERROR_
 or
 .B PCAP_WARNING_
 value returned by a libpcap routine to an error string.
 .SH SEE ALSO
-pcap(3PCAP)
+.BR pcap (3PCAP)
diff --git a/pcap_strerror.3pcap b/pcap_strerror.3pcap
index 7c7d53f..dedfa40 100644
--- a/pcap_strerror.3pcap
+++ b/pcap_strerror.3pcap
@@ -31,10 +31,10 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_strerror()
+.BR pcap_strerror ()
 is provided in case
 .BR strerror (3)
 isn't available.  It returns an error message string corresponding to
 .IR error .
 .SH SEE ALSO
-strerror(3)
+.BR pcap (3PCAP)
diff --git a/pcap_tstamp_type_name_to_val.3pcap b/pcap_tstamp_type_name_to_val.3pcap
index ac2e35d..f60516e 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 "5 December 2014"
+.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "22 August 2018"
 .SH NAME
 pcap_tstamp_type_name_to_val \- get the time stamp type value
 corresponding to a time stamp type name
@@ -33,13 +33,17 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_tstamp_type_name_to_val()
+.BR pcap_tstamp_type_name_to_val ()
 translates a time stamp type name to the corresponding time stamp type
 value.  The translation is case-insensitive.
 .SH RETURN VALUE
-.B pcap_tstamp_type_name_to_val()
+.BR pcap_tstamp_type_name_to_val ()
 returns time stamp type value on success and
 .B PCAP_ERROR
 on failure.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1.
 .SH SEE ALSO
-pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_tstamp_type_val_to_name (3PCAP)
diff --git a/pcap_tstamp_type_val_to_name.3pcap b/pcap_tstamp_type_val_to_name.3pcap
index 261554e..5958e81 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 "12 December 2013"
+.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "22 August 2018"
 .SH NAME
 pcap_tstamp_type_val_to_name, pcap_tstamp_type_val_to_description \- get
 a name or description for a time stamp type value
@@ -34,16 +34,20 @@
 .ft
 .fi
 .SH DESCRIPTION
-.B pcap_tstamp_type_val_to_name()
+.BR pcap_tstamp_type_val_to_name ()
 translates a time stamp type value to the corresponding time stamp type
 name.
 .B NULL
 is returned on failure.
 .PP
-.B pcap_tstamp_type_val_to_description()
+.BR pcap_tstamp_type_val_to_description ()
 translates a time stamp type value to a short description of that time
 stamp type.
 .B NULL
 is returned on failure.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1.
 .SH SEE ALSO
-pcap(3PCAP), pcap_tstamp_type_name_to_val(3PCAP)
+.BR pcap (3PCAP),
+.BR pcap_tstamp_type_name_to_val (3PCAP)
diff --git a/portability.h b/portability.h
index b361254..d606368 100644
--- a/portability.h
+++ b/portability.h
@@ -38,6 +38,7 @@
  * Helpers for portability between Windows and UN*X and between different
  * flavors of UN*X.
  */
+#include <stdarg.h>	/* we declare varargs functions on some platforms */
 
 #include "pcap/funcattrs.h"
 
@@ -45,46 +46,40 @@
 extern "C" {
 #endif
 
-#ifndef HAVE_STRLCPY
- /*
-  * Macro that does the same thing as strlcpy().
-  */
- #if defined(_MSC_VER) || defined(__MINGW32__)
-  /*
-   * 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
+#ifdef HAVE_STRLCAT
+  #define pcap_strlcat	strlcat
+#else
+  #if defined(_MSC_VER) || defined(__MINGW32__)
+    /*
+     * strncat_s() is supported at least back to Visual
+     * Studio 2005; we require Visual Studio 2015 or later.
+     */
+    #define pcap_strlcat(x, y, z) \
+	strncat_s((x), (z), (y), _TRUNCATE)
+  #else
+    /*
+     * Define it ourselves.
+     */
+    extern size_t pcap_strlcat(char * restrict dst, const char * restrict src, size_t dstsize);
+  #endif
 #endif
 
-#ifndef HAVE_STRLCAT
- /*
-  * Macro that does the same thing as strlcat().
-  */
- #if defined(_MSC_VER) || defined(__MINGW32__)
-  /*
-   * strncat_s() is supported at least back to Visual
-   * Studio 2005.
-   */
-  #define strlcat(x, y, z) \
-	strncat_s((x), (z), (y), _TRUNCATE)
- #else
-  /*
-   * ANSI C says strncat() always null-terminates its first argument,
-   * so 1) we don't need to explicitly null-terminate the string
-   * ourselves and 2) we need to leave room for the null terminator.
-   */
-  #define strlcat(x, y, z) \
-	strncat((x), (y), (z) - strlen((x)) - 1)
- #endif
+#ifdef HAVE_STRLCPY
+  #define pcap_strlcpy	strlcpy
+#else
+  #if defined(_MSC_VER) || defined(__MINGW32__)
+    /*
+     * strncpy_s() is supported at least back to Visual
+     * Studio 2005; we require Visual Studio 2015 or later.
+     */
+    #define pcap_strlcpy(x, y, z) \
+	strncpy_s((x), (z), (y), _TRUNCATE)
+  #else
+    /*
+     * Define it ourselves.
+     */
+    extern size_t pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dstsize);
+  #endif
 #endif
 
 #ifdef _MSC_VER
@@ -100,38 +95,21 @@
 #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.
+ * We want asprintf(), for some cases where we use it to construct
+ * dynamically-allocated variable-length strings; it's present on
+ * some, but not all, platforms.
  */
-#ifdef HAVE_SNPRINTF
-#define pcap_snprintf snprintf
+#ifdef HAVE_ASPRINTF
+#define pcap_asprintf asprintf
 #else
-extern int pcap_snprintf(char *, size_t, PCAP_FORMAT_STRING(const char *), ...)
-    PCAP_PRINTFLIKE(3, 4);
+extern int pcap_asprintf(char **, PCAP_FORMAT_STRING(const char *), ...)
+    PCAP_PRINTFLIKE(2, 3);
 #endif
 
-#ifdef HAVE_VSNPRINTF
-#define pcap_vsnprintf vsnprintf
+#ifdef HAVE_VASPRINTF
+#define pcap_vasprintf vasprintf
 #else
-extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
+extern int pcap_vasprintf(char **, const char *, va_list ap);
 #endif
 
 #ifdef HAVE_STRTOK_R
@@ -146,7 +124,6 @@
     /*
      * Define it ourselves.
      */
-    #define NEED_STRTOK_R
     extern char *pcap_strtok_r(char *, const char *, char **);
   #endif
 #endif /* HAVE_STRTOK_R */
diff --git a/post_update.sh b/post_update.sh
new file mode 100755
index 0000000..3cc1b1d
--- /dev/null
+++ b/post_update.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# $1 Path to the new version.
+# $2 Path to the old version.
+
+cp -a -n $2/config.h $1/
+cp -a $2/.gitignore $1/
+cp -a -n $2/pcap-netfilter-linux-android.h $1/
+cp -a -n $2/pcap-netfilter-linux-android.c $1/
+cp -a -n $2/grammar.c $1/
+cp -a -n $2/grammar.h $1/
+cp -a -n $2/scanner.c $1/
+cp -a -n $2/scanner.h $1/
+
diff --git a/rpcap-protocol.c b/rpcap-protocol.c
index 692f7c5..0cdc0ba 100644
--- a/rpcap-protocol.c
+++ b/rpcap-protocol.c
@@ -61,6 +61,8 @@
  *
  * \param sock: the socket we are currently using.
  *
+ * \param ssl: if compiled with openssl, the optional ssl handler to use with the above socket.
+ *
  * \param ver: the protocol version we want to put in the reply.
  *
  * \param errcode: a integer which tells the other party the type of error
@@ -78,7 +80,7 @@
  * error message is returned in the 'errbuf' variable.
  */
 int
-rpcap_senderror(SOCKET sock, uint8 ver, unsigned short errcode, const char *error, char *errbuf)
+rpcap_senderror(SOCKET sock, SSL *ssl, uint8 ver, unsigned short errcode, const char *error, char *errbuf)
 {
 	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data to be sent is buffered */
 	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
@@ -99,7 +101,7 @@
 		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
 		return -1;
 
-	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+	if (sock_send(sock, ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
 	return 0;
diff --git a/rpcap-protocol.h b/rpcap-protocol.h
index 83ebdc5..a69cf80 100644
--- a/rpcap-protocol.h
+++ b/rpcap-protocol.h
@@ -63,80 +63,20 @@
  *
  * Version negotiation is done as part of the authentication process:
  *
- * The client sends an authentication request, with the version number
- * in the request being the maximum version it supports.
+ * The client sends an authentication request, with a version number
+ * of 0.  All servers must accept authentication requests with a version
+ * number of 0, even if they don't support version 0 for any other
+ * requests.
  *
- * If the server supports that version, it attempts to authenticate the
- * client, and replies as appropriate, with the version number in the
- * reply being that version.
+ * The server attempts to authenticate the client.  If that succeeds,
+ * older servers - which only support version 0 - will send an
+ * authentication reply with no payload.  Newer servers - which might
+ * support other versions - will send an authentication reply with
+ * a payload giving the minimum and maximum versions it supports.
  *
- * If the server doesn't support that version because it's too large,
- * it replies with a RPCAP_MSG_ERROR message, with the maximum version
- * they support as the version number in the reply, and with the error
- * code being PCAP_ERR_WRONGVER.
- *
- * If the server doesn't support that version because it's too small,
- * it replies with a RPCAP_MSG_ERROR message, with that version as
- * the version number in the reply, and with the error code being
- * PCAP_ERR_WRONGVER.
- *
- * If the client supports that version, it retries the authentication
- * with that version and, if that fails for any reason, including
- * PCAP_ERR_WRONGVER, fails.  Otherwise, it fails, telling its caller
- * that there's no version that both support.
- *
- * This requires that the set of versions supported by a client or
- * server be a range of integers, with no gaps.  Thus:
- *
- * the client's version set is [Cmin, Cmax], with Cmin <= Cmax;
- *
- * the server's version set is [Smin, Smax], with Smin <= Smax;
- *
- * the client sends Cmax as the version number in the initial
- * authentication request;
- *
- * if the server doesn't support the version sent by the client,
- * either Smax < Cmax or Smin > Cmax (because the client sent Cmax
- * to the server, and the server doesn't support it);
- *
- * if Smax < Cmax:
- *
- *    the server sends Smax as the version number in the RPCAP_MSG_ERROR/
- *    PCAP_ERR_WRONGVER message - the client will accept this because
- *    Cmax != 0, as these numbers are unsigned, and this means that
- *    this isn't an old client that rejects all messages with a non-zero
- *    version number, it's a new client that accepts RPCAP_MSG_ERROR
- *    messages no matter what the version is;
- *
- *    if Smax >= Cmin, both the client and the server can use it, and
- *    the client retries with Smax;
- *
- *    if Smax < Cmin, there is no version the client and server can
- *    both support.
- *
- * if Smin > Cmax:
- *
- *    the server sends Cmax as the version number in the RPCAP_MSG_ERROR/
- *    PCAP_ERR_WRONGVER message - the client will accept this because
- *    Cmax is a valid client version number.
- *
- *    the client will retry with Cmax, get the same version failure,
- *    and report that there is no version the client and server can
- *    both support (as the version sets are disjoint).
- *
- * Old negotiation-unaware clients just send version 0 and, if they
- * get back PCAP_ERR_WRONGVER, treat it as a fatal error.  This
- * means they'll fail to talk to any server that can't handle
- * version 0, which is the appropriate thing to do, as they can
- * only use version 0.
- *
- * Old negotiation-unaware servers fail if they get a version other
- * than 0, sending back PCAP_ERR_WRONGVER with version 0, which is
- * the only version, and thus both the minimum and maximum version,
- * they support.  The client will either fail if it doesn't support
- * version 0, or will retry with version 0 and succeed, so it will
- * fail with servers that can't handle version 0 or will negotiate
- * version 0 with servers that can handle version 0.
+ * The client attempts to find the largest version number that is
+ * in both its range of supported versions and the server's supported
+ * versions.  If it fails, it gives up; otherwise, it uses that version.
  */
 #define RPCAP_MIN_VERSION 0
 #define RPCAP_MAX_VERSION 0
@@ -148,7 +88,8 @@
  * comparison will always succeed.
  */
 #if RPCAP_MIN_VERSION == 0
-#define RPCAP_VERSION_IS_SUPPORTED(v)	((v) <= RPCAP_MAX_VERSION)
+#define RPCAP_VERSION_IS_SUPPORTED(v)	\
+	((v) <= RPCAP_MAX_VERSION)
 #else
 #define RPCAP_VERSION_IS_SUPPORTED(v)	\
 	((v) >= RPCAP_MIN_VERSION && (v) <= RPCAP_MAX_VERSION)
@@ -176,6 +117,12 @@
  * for better alignment.
  * These structures have been created in order to be correctly aligned to
  * a 32-bit boundary, but be careful in any case.
+ *
+ * The layout of these structures MUST not be changed.  If a packet
+ * format is different in different versions of the protocol, versions
+ * of the structure should be provided for all the different versions or
+ * version ranges (if more than one version of the protocol has the same
+ * layout) that we support.
  */
 
 /*
@@ -199,6 +146,19 @@
 	uint32 plen;	/* Length of the payload of this RPCAP message */
 };
 
+/*
+ * Format of data that may appear at the end of an authentication reply,
+ * giving the minimum and maximum versions of the protocol that the
+ * server supports.
+ *
+ * Older servers don't provide this; they support only version 0.
+ */
+struct rpcap_authreply
+{
+	uint8 minvers;	/* Minimum version supported */
+	uint8 maxvers;	/* Maximum version supported */
+};
+
 /* Format of the message for the interface description (findalldevs command) */
 struct rpcap_findalldevs_if
 {
@@ -299,7 +259,7 @@
 struct rpcap_openreply
 {
 	int32 linktype;	/* Link type */
-	int32 tzoff;	/* Timezone offset */
+	int32 tzoff;	/* Timezone offset - not used by newer clients */
 };
 
 /* Format of the message that starts a remote capture (startcap command) */
@@ -327,10 +287,14 @@
  */
 struct rpcap_pkthdr
 {
+	/*
+	 * This protocol needs to be updated with a new version before
+	 * 2038-01-19 03:14:07 UTC.
+	 */
 	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 len;		/* Real length of this packet (off wire) */
 	uint32 npkt;		/* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */
 };
 
@@ -342,7 +306,7 @@
 	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 */
+/* Structure that keeps a single BPF instruction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */
 struct rpcap_filterbpf_insn
 {
 	uint16 code;	/* opcode of the instruction */
@@ -378,20 +342,25 @@
 	uint32 value;	/* Parameter related to the sampling method */
 };
 
-/* Messages field coding */
+/*
+ * Messages field coding.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
 #define RPCAP_MSG_IS_REPLY		0x080	/* Flag indicating a reply */
 
-#define RPCAP_MSG_ERROR			1	/* Message that keeps an error notification */
-#define RPCAP_MSG_FINDALLIF_REQ		2	/* Request to list all the remote interfaces */
-#define RPCAP_MSG_OPEN_REQ		3	/* Request to open a remote device */
-#define RPCAP_MSG_STARTCAP_REQ		4	/* Request to start a capture on a remote device */
-#define RPCAP_MSG_UPDATEFILTER_REQ	5	/* Send a compiled filter into the remote device */
-#define RPCAP_MSG_CLOSE			6	/* Close the connection with the remote peer */
-#define RPCAP_MSG_PACKET		7	/* This is a 'data' message, which carries a network packet */
-#define RPCAP_MSG_AUTH_REQ		8	/* Message that keeps the authentication parameters */
-#define RPCAP_MSG_STATS_REQ		9	/* It requires to have network statistics */
-#define RPCAP_MSG_ENDCAP_REQ		10	/* Stops the current capture, keeping the device open */
-#define RPCAP_MSG_SETSAMPLING_REQ	11	/* Set sampling parameters */
+#define RPCAP_MSG_ERROR			0x01	/* Message that keeps an error notification */
+#define RPCAP_MSG_FINDALLIF_REQ		0x02	/* Request to list all the remote interfaces */
+#define RPCAP_MSG_OPEN_REQ		0x03	/* Request to open a remote device */
+#define RPCAP_MSG_STARTCAP_REQ		0x04	/* Request to start a capture on a remote device */
+#define RPCAP_MSG_UPDATEFILTER_REQ	0x05	/* Send a compiled filter into the remote device */
+#define RPCAP_MSG_CLOSE			0x06	/* Close the connection with the remote peer */
+#define RPCAP_MSG_PACKET		0x07	/* This is a 'data' message, which carries a network packet */
+#define RPCAP_MSG_AUTH_REQ		0x08	/* Message that keeps the authentication parameters */
+#define RPCAP_MSG_STATS_REQ		0x09	/* It requires to have network statistics */
+#define RPCAP_MSG_ENDCAP_REQ		0x0A	/* Stops the current capture, keeping the device open */
+#define RPCAP_MSG_SETSAMPLING_REQ	0x0B	/* Set sampling parameters */
 
 #define RPCAP_MSG_FINDALLIF_REPLY	(RPCAP_MSG_FINDALLIF_REQ | RPCAP_MSG_IS_REPLY)		/* Keeps the list of all the remote interfaces */
 #define RPCAP_MSG_OPEN_REPLY		(RPCAP_MSG_OPEN_REQ | RPCAP_MSG_IS_REPLY)		/* The remote device has been opened correctly */
@@ -410,24 +379,32 @@
 
 #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 */
+/*
+ * Network error codes.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
+#define PCAP_ERR_NETW			1	/* Network error */
+#define PCAP_ERR_INITTIMEOUT		2	/* The RPCAP initial timeout has expired */
+#define PCAP_ERR_AUTH			3	/* Generic authentication error */
+#define PCAP_ERR_FINDALLIF		4	/* Generic findalldevs error */
+#define PCAP_ERR_NOREMOTEIF		5	/* The findalldevs was ok, but the remote end had no interfaces to list */
+#define PCAP_ERR_OPEN			6	/* Generic pcap_open error */
+#define PCAP_ERR_UPDATEFILTER		7	/* Generic updatefilter error */
+#define PCAP_ERR_GETSTATS		8	/* Generic pcap_stats error */
+#define PCAP_ERR_READEX			9	/* Generic pcap_next_ex error */
+#define PCAP_ERR_HOSTNOAUTH		10	/* The host is not authorized to connect to this server */
+#define PCAP_ERR_REMOTEACCEPT		11	/* Generic pcap_remoteaccept error */
+#define PCAP_ERR_STARTCAPTURE		12	/* Generic pcap_startcapture error */
+#define PCAP_ERR_ENDCAPTURE		13	/* Generic pcap_endcapture error */
+#define PCAP_ERR_RUNTIMETIMEOUT		14	/* The RPCAP run-time timeout has expired */
+#define PCAP_ERR_SETSAMPLING		15	/* Error during the settings of sampling parameters */
+#define PCAP_ERR_WRONGMSG		16	/* The other end endpoint sent a message which has not been recognized */
+#define PCAP_ERR_WRONGVER		17	/* The other end endpoint has a version number that is not compatible with our */
+#define PCAP_ERR_AUTH_FAILED		18	/* The user couldn't be authenticated */
+#define PCAP_ERR_TLS_REQUIRED		19	/* The server requires TLS to connect */
+#define PCAP_ERR_AUTH_TYPE_NOTSUP	20	/* The authentication type isn't supported */
 
 /*
  * \brief Buffer used by socket functions to send-receive packets.
@@ -442,9 +419,10 @@
  *********************************************************/
 
 #include "sockutils.h"
+#include "sslutils.h"
 
 extern void rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length);
 extern const char *rpcap_msg_type_string(uint8 type);
-extern int rpcap_senderror(SOCKET sock, uint8 ver, uint16 errcode, const char *error, char *errbuf);
+extern int rpcap_senderror(SOCKET sock, SSL *ssl, uint8 ver, uint16 errcode, const char *error, char *errbuf);
 
 #endif
diff --git a/rpcapd/.gitignore b/rpcapd/.gitignore
index 50c27ab..aec4fdb 100644
--- a/rpcapd/.gitignore
+++ b/rpcapd/.gitignore
@@ -3,3 +3,4 @@
 *.o
 rpcapd
 rpcapd.manadmin
+rpcapd-config.manfile
diff --git a/rpcapd/CMakeLists.txt b/rpcapd/CMakeLists.txt
index b3b16e3..f2bd12d 100644
--- a/rpcapd/CMakeLists.txt
+++ b/rpcapd/CMakeLists.txt
@@ -50,8 +50,8 @@
   if(WIN32)
     set(RPCAPD_EXTRA_SOURCES
         win32-svc.c
+        ${pcap_SOURCE_DIR}/charconv.c
         ${pcap_SOURCE_DIR}/missing/getopt.c
-        ${pcap_SOURCE_DIR}/missing/win_snprintf.c
         rpcapd.rc)
     include_directories(${pcap_SOURCE_DIR}/rpcapd ${pcap_SOURCE_DIR}/missing)
   endif(WIN32)
@@ -59,10 +59,11 @@
   add_executable(rpcapd
     daemon.c
     fileconf.c
-    log-stderr.c
+    log.c
     rpcapd.c
     ${pcap_SOURCE_DIR}/rpcap-protocol.c
     ${pcap_SOURCE_DIR}/sockutils.c
+    ${pcap_SOURCE_DIR}/sslutils.c
     ${pcap_SOURCE_DIR}/fmtutils.c
     ${RPCAPD_EXTRA_SOURCES}
   )
@@ -71,6 +72,46 @@
     set_target_properties(rpcapd PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
   endif()
 
+  if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+    set_target_properties(rpcapd PROPERTIES
+        LINK_FLAGS "${SANITIZER_FLAGS}")
+  endif()
+
+  #
+  # By default, build rpcapd universal with the appropriate set of
+  # architectures for the OS on which we're doing the build.
+  #
+  if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+    #
+    # Get the major version of Darwin.
+    #
+    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+    if(SYSTEM_VERSION_MAJOR EQUAL 9)
+      #
+      # Leopard.  Build for 32-bit x86 and 32-bit PowerPC, with
+      # 32-bit x86 first.
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "i386;ppc")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+      #
+      # Snow Leopard.  Build for x86-64 and 32-bit x86, with
+      # x86-64 first.
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "x86_64;i386")
+    else()
+      #
+      # Post-Snow Leopard.  Build only for x86-64.
+      # XXX - update if and when Apple adds ARM-based Macs.
+      # (You're on your own for iOS etc.)
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "x86_64")
+    endif()
+
+    set_target_properties(rpcapd PROPERTIES
+      OSX_ARCHITECTURES "${OSX_PROGRAM_ARCHITECTURES}")
+  endif()
+
   if(WIN32)
     target_link_libraries(rpcapd ${LIBRARY_NAME}
       ${RPCAPD_LINK_LIBRARIES} ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
@@ -92,11 +133,17 @@
 
   set(MANADMIN_EXPAND rpcapd.manadmin.in)
 
-  if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
-    install(TARGETS rpcapd DESTINATION bin/amd64)
-  else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
-    install(TARGETS rpcapd DESTINATION bin)
-  endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set(MANFILE_EXPAND rpcapd-config.manfile.in)
+
+  if(NOT MSVC)
+    install(TARGETS rpcapd DESTINATION sbin)
+  else(NOT MSVC)
+    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+      install(TARGETS rpcapd DESTINATION bin/amd64)
+    else(CMAKE_SIZEOF_VOID_P EQUAL 8)
+      install(TARGETS rpcapd DESTINATION bin)
+    endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  endif(NOT MSVC)
 
   # On UN*X, and on Windows when not using MSVC, generate process man
   # pages and arrange that they be installed.
@@ -114,5 +161,13 @@
         set(MANADMIN ${MANADMIN} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
     endforeach(TEMPLATE_MANPAGE)
     install(FILES ${MANADMIN} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_ADMIN_COMMANDS})
+
+    set(MANFILE "")
+    foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
+        string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
   endif(NOT MSVC)
 endif(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
diff --git a/rpcapd/Makefile.in b/rpcapd/Makefile.in
index d3e02c1..3290679 100644
--- a/rpcapd/Makefile.in
+++ b/rpcapd/Makefile.in
@@ -38,6 +38,7 @@
 
 # VPATH
 srcdir = @srcdir@
+top_srcdir = @top_srcdir@
 VPATH = @srcdir@
 
 #
@@ -66,7 +67,7 @@
 RPCAPD_LIBS = @RPCAPD_LIBS@
 
 # Standard CFLAGS
-FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+FULL_CFLAGS = $(CCOPT) @V_PROG_CCOPT_FAT@ $(INCLS) $(DEFS) $(CFLAGS)
 
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -81,10 +82,10 @@
 
 SRC =	daemon.c \
 	fileconf.c \
-	log-stderr.c \
+	log.c \
 	rpcapd.c
 
-OBJ =	$(SRC:.c=.o) ../rpcap-protocol.o ../sockutils.o ../fmtutils.o
+OBJ =	$(SRC:.c=.o) ../rpcap-protocol.o ../sockutils.o ../fmtutils.o ../sslutils.o
 PUBHDR =
 
 HDR = $(PUBHDR) log.h
@@ -97,15 +98,19 @@
 MANADMIN = \
 	rpcapd.manadmin.in
 
+MANFILE = \
+	rpcapd-config.manfile.in
+
 rpcapd: $(OBJ) ../libpcap.a
-	$(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) ../libpcap.a $(LIBS) $(RPCAPD_LIBS) $(PTHREAD_LIBS)
+	$(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) @V_PROG_LDFLAGS_FAT@ \
+	    -o $@ $(OBJ) ../libpcap.a $(LIBS) $(RPCAPD_LIBS) $(PTHREAD_LIBS)
 clean:
 	rm -f $(CLEANFILES)
 
 distclean: clean
 	rm -f Makefile config.cache config.log config.status \
 	    config.h stamp-h stamp-h.in
-	rm -f $(MANADMIN:.in=)
+	rm -f $(MANADMIN:.in=) $(MANFILE:.in=)
 	rm -rf autom4te.cache
 
 install: rpcapd
@@ -114,17 +119,24 @@
 	$(INSTALL_PROGRAM) rpcapd $(DESTDIR)$(sbindir)/rpcapd
 	[ -d $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@ ] || \
 	    (mkdir -p $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@)
+	[ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+	    (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
 	for i in $(MANADMIN); do \
 		$(INSTALL_DATA) `echo $$i | sed 's/.manadmin.in/.manadmin/'` \
 		    $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+	for i in $(MANFILE); do \
+		$(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+		    $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
 
 uninstall:
 	rm -f $(DESTDIR)$(sbindir)/rpcapd
 	for i in $(MANADMIN); do \
 		rm -f $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+	for i in $(MANFILE); do \
+		rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
 
 tags: $(TAGFILES)
 	ctags -wtd $(TAGFILES)
 
 depend:
-	../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+	$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c
index 4bf42fd..620dec3 100644
--- a/rpcapd/daemon.c
+++ b/rpcapd/daemon.c
@@ -39,12 +39,14 @@
 #include <errno.h>		// for the errno variable
 #include <stdlib.h>		// for malloc(), free(), ...
 #include <string.h>		// for strlen(), ...
+#include <limits.h>		// for INT_MAX
 
 #ifdef _WIN32
   #include <process.h>		// for threads
 #else
   #include <unistd.h>
   #include <pthread.h>
+  #include <signal.h>
   #include <sys/time.h>
   #include <sys/types.h>	// for select() and such
   #include <pwd.h>		// for password management
@@ -63,40 +65,57 @@
 #include "daemon.h"
 #include "log.h"
 
-#define RPCAP_TIMEOUT_INIT 90		/* Initial timeout for RPCAP connections (default: 90 sec) */
-#define RPCAP_TIMEOUT_RUNTIME 180	/* Run-time timeout for RPCAP connections (default: 3 min) */
-#define RPCAP_SUSPEND_WRONGAUTH 1	/* If the authentication is wrong, stops 1 sec before accepting a new auth message */
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include "sslutils.h"
+#endif
+
+//
+// Timeout, in seconds, when we're waiting for a client to send us an
+// authentication request; if they don't send us a request within that
+// interval, we drop the connection, so we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_INIT 90
+
+//
+// Timeout, in seconds, when we're waiting for an authenticated client
+// to send us a request, if a capture isn't in progress; if they don't
+// send us a request within that interval, we drop the connection, so
+// we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_RUNTIME 180
+
+//
+// Time, in seconds, that we wait after a failed authentication attempt
+// before processing the next request; this prevents a client from
+// rapidly trying different accounts or passwords.
+//
+#define RPCAP_SUSPEND_WRONGAUTH 1
 
 // Parameters for the service loop.
 struct daemon_slpars
 {
-	SOCKET sockctrl_in;	//!< SOCKET ID of the input side of the control connection
-	SOCKET sockctrl_out;	//!< SOCKET ID of the output side of the control connection
-	uint8 protocol_version;	//!< negotiated protocol version
+	SOCKET sockctrl;	//!< SOCKET ID of the control connection
+	SSL *ssl;		//!< Optional SSL handler for the controlling sockets
 	int isactive;		//!< Not null if the daemon has to run in active mode
 	int nullAuthAllowed;	//!< '1' if we permit NULL authentication, '0' otherwise
 };
 
-/*
- * Data for a session managed by a thread.
- */
-struct session {
-	SOCKET sockctrl_out;
-	SOCKET sockdata;
-	uint8 protocol_version;
-	pcap_t *fp;
-	unsigned int TotCapt;
-};
-
 //
-// Structure to refer to a thread.
+// Data for a session managed by a thread.
 // It includes both a Boolean indicating whether we *have* a thread,
 // and a platform-dependent (UN*X vs. Windows) identifier for the
 // thread; on Windows, we could use an invalid handle to indicate
 // that we don't have a thread, but there *is* no portable "no thread"
 // value for a pthread_t on UN*X.
 //
-struct thread_handle {
+struct session {
+	SOCKET sockctrl;
+	SOCKET sockdata;
+	SSL *ctrl_ssl, *data_ssl; // optional SSL handlers for sockctrl and sockdata.
+	uint8 protocol_version;
+	pcap_t *fp;
+	unsigned int TotCapt;
 	int	have_thread;
 #ifdef _WIN32
 	HANDLE thread;
@@ -106,52 +125,116 @@
 };
 
 // Locally defined functions
-static int daemon_msg_err(SOCKET sockctrl_in, uint32 plen);
+static int daemon_msg_err(SOCKET sockctrl, SSL *, uint32 plen);
 static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
 static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
 
-static int daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen);
+static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen);
 
-static int daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen);
-static int daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param);
-static int daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struct thread_handle *threaddata);
+static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, size_t sourcelen);
+static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param, int uses_ssl);
+static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session);
 
-static int daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen);
-static int daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errbuf);
+static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen);
+static int daemon_unpackapplyfilter(SOCKET sockctrl, SSL *, struct session *session, uint32 *plenp, char *errbuf);
 
-static int daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt);
+static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt);
 
-static int daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap_sampling *samp_param);
+static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, struct rpcap_sampling *samp_param);
 
 static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
 #ifdef _WIN32
 static unsigned __stdcall daemon_thrdatamain(void *ptr);
 #else
 static void *daemon_thrdatamain(void *ptr);
+static void noop_handler(int sign);
 #endif
 
-static int rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp);
-static int rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
-static int rpcapd_discard(SOCKET sock, uint32 len);
+static int rpcapd_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *headerp);
+static int rpcapd_recv(SOCKET sock, SSL *, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
+static int rpcapd_discard(SOCKET sock, SSL *, uint32 len);
+static void session_close(struct session *);
+
+//
+// TLS record layer header; used when processing the first message from
+// the client, in case we aren't doing TLS but they are.
+//
+struct tls_record_header {
+	uint8 type;		// ContentType - will be 22, for Handshake
+	uint8 version_major;	// TLS protocol major version
+	uint8 version_injor;	// TLS protocol minor version
+	// This is *not* aligned on a 2-byte boundary; we just
+	// declare it as two bytes.  Don't assume any particular
+	// compiler's mechanism for saying "packed"!
+	uint8 length_hi;	// Upper 8 bits of payload length
+	uint8 length_lo;	// Low 8 bits of payload length
+};
+
+#define TLS_RECORD_HEADER_LEN	5	// Don't use sizeof in case it's padded
+
+#define TLS_RECORD_TYPE_ALERT		21
+#define TLS_RECORD_TYPE_HANDSHAKE	22
+
+//
+// TLS alert message.
+//
+struct tls_alert {
+	uint8 alert_level;
+	uint8 alert_description;
+};
+
+#define TLS_ALERT_LEN			2
+
+#define TLS_ALERT_LEVEL_FATAL		2
+#define TLS_ALERT_HANDSHAKE_FAILURE	40
+
+static int is_url(const char *source);
+
+/*
+ * Maximum sizes for fixed-bit-width values.
+ */
+#ifndef UINT16_MAX
+#define UINT16_MAX	65535U
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX	4294967295U
+#endif
 
 int
-daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nullAuthAllowed)
+daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+    int nullAuthAllowed, int uses_ssl)
 {
+	uint8 first_octet;
+	struct tls_record_header tls_header;
+	struct tls_alert tls_alert;
 	struct daemon_slpars pars;		// service loop parameters
 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
 	char errmsgbuf[PCAP_ERRBUF_SIZE + 1];	// buffer for errors to send to the client
+	int host_port_check_status;
+	SSL *ssl = NULL;
 	int nrecv;
 	struct rpcap_header header;		// RPCAP message general header
 	uint32 plen;				// payload length from header
 	int authenticated = 0;			// 1 if the client has successfully authenticated
 	char source[PCAP_BUF_SIZE+1];		// keeps the string that contains the interface to open
 	int got_source = 0;			// 1 if we've gotten the source from an open request
+#ifndef _WIN32
+	struct sigaction action;
+#endif
 	struct session *session = NULL;		// struct session main variable
 	const char *msg_type_string;		// string for message type
 	int client_told_us_to_close = 0;	// 1 if the client told us to close the capture
 
-	struct thread_handle threaddata;	// 'read from daemon and send to client' thread
-
 	// needed to save the values of the statistics
 	struct pcap_stat stats;
 	unsigned int svrcapt;
@@ -163,31 +246,255 @@
 	struct timeval tv;			// maximum time the select() can block waiting for data
 	int retval;				// select() return value
 
+	*errbuf = 0;	// Initialize errbuf
+
+	//
+	// Peek into the socket to determine whether the client sent us
+	// a TLS handshake message or a non-TLS rpcapd message.
+	//
+	// The first byte of an rpcapd request is the version number;
+	// the first byte of a TLS handshake message is 22.  The
+	// first request to an rpcapd server must be an authentication
+	// request or a close request, and must have a version number
+	// of 0, so it will be possible to distinguish between an
+	// initial plaintext request to a server and an initial TLS
+	// handshake message.
+	//
+	nrecv = sock_recv(sockctrl, NULL, (char *)&first_octet, 1,
+	    SOCK_EOF_ISNT_ERROR|SOCK_MSG_PEEK, errbuf, PCAP_ERRBUF_SIZE);
+	if (nrecv == -1)
+	{
+		// Fatal error.
+		rpcapd_log(LOGPRIO_ERROR, "Peek from client failed: %s", errbuf);
+		goto end;
+	}
+	if (nrecv == 0)
+	{
+		// Client closed the connection.
+		goto end;
+	}
+
+#ifdef HAVE_OPENSSL
+	//
+	// We have to upgrade to TLS as soon as possible, so that the
+	// whole protocol goes through the encrypted tunnel, including
+	// early error messages.
+	//
+	// Even in active mode, the other end has to initiate the TLS
+	// handshake as we still are the server as far as TLS is concerned,
+	// so we don't check isactive.
+	//
+	if (uses_ssl)
+	{
+		//
+		// We're expecting a TLS handshake message.  If this
+		// isn't one, assume it's a non-TLS rpcapd message.
+		//
+		// The first octet of a TLS handshake is
+		// TLS_RECORD_TYPE_HANDSHAKE.
+		//
+		if (first_octet != TLS_RECORD_TYPE_HANDSHAKE)
+		{
+			//
+			// We assume this is a non-TLS rpcapd message.
+			//
+			// Read the message header from the client.
+			//
+			nrecv = rpcapd_recv_msg_header(sockctrl, NULL, &header);
+			if (nrecv == -1)
+			{
+				// Fatal error.
+				goto end;
+			}
+			if (nrecv == -2)
+			{
+				// Client closed the connection.
+				goto end;
+			}
+			plen = header.plen;
+
+			// Discard the rest of the message.
+			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
+			{
+				// Network error.
+				goto end;
+			}
+
+			//
+			// Send an authentication error, indicating
+			// that we require TLS.
+			//
+			if (rpcap_senderror(sockctrl, NULL, header.ver,
+			    PCAP_ERR_TLS_REQUIRED,
+			    "TLS is required by this server", errbuf) == -1)
+			{
+				// That failed; log a message and give up.
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+				goto end;
+			}
+
+			// Shut the session down.
+			goto end;
+		}
+		ssl = ssl_promotion(1, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+		if (! ssl)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
+			    errbuf);
+			goto end;
+		}
+	}
+	else
+#endif
+	{
+		//
+		// We're expecting a non-TLS rpcapd message.  If this
+		// looks, instead, like a TLS handshake message, send
+		// a TLS handshake_failed alert.
+		//
+		// The first octet of a TLS handshake is
+		// TLS_RECORD_TYPE_HANDSHAKE.
+		//
+		if (first_octet == TLS_RECORD_TYPE_HANDSHAKE)
+		{
+			//
+			// TLS handshake.
+			// Read the record header.
+			//
+			nrecv = sock_recv(sockctrl, ssl, (char *) &tls_header,
+			    sizeof tls_header, SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR,
+			    errbuf, PCAP_ERRBUF_SIZE);
+			if (nrecv == -1)
+			{
+				// Network error.
+				rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+				goto end;
+			}
+			if (nrecv == 0)
+			{
+				// Immediate EOF
+				goto end;
+			}
+			plen = (tls_header.length_hi << 8) | tls_header.length_lo;
+
+			// Discard the rest of the message.
+			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
+			{
+				// Network error.
+				goto end;
+			}
+
+			//
+			// Send a TLS handshake failure alert.
+			// Use the same version the client sent us.
+			//
+			tls_header.type = TLS_RECORD_TYPE_ALERT;
+			tls_header.length_hi = 0;
+			tls_header.length_lo = TLS_ALERT_LEN;
+
+			if (sock_send(sockctrl, NULL, (char *) &tls_header,
+			    TLS_RECORD_HEADER_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
+			{
+				// That failed; log a message and give up.
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+				goto end;
+			}
+
+			tls_alert.alert_level = TLS_ALERT_LEVEL_FATAL;
+			tls_alert.alert_description = TLS_ALERT_HANDSHAKE_FAILURE;
+			if (sock_send(sockctrl, NULL, (char *) &tls_alert,
+			    TLS_ALERT_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
+			{
+				// That failed; log a message and give up.
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+				goto end;
+			}
+			//
+			// Give up anyway.
+			//
+			goto end;
+		}
+	}
+
 	// Set parameters structure
-	pars.sockctrl_in = sockctrl_in;
-	pars.sockctrl_out = sockctrl_out;
-	pars.protocol_version = 0;		// not yet known
+	pars.sockctrl = sockctrl;
+	pars.ssl = ssl;
 	pars.isactive = isactive;		// active mode
 	pars.nullAuthAllowed = nullAuthAllowed;
 
-	// We don't have a thread yet.
-	threaddata.have_thread = 0;
 	//
-	// We *shouldn't* have to initialize the thread indicator
-	// itself, because the compiler *should* realize that we
-	// only use this if have_thread isn't 0, but we *do* have
-	// to do it, because not all compilers *do* realize that.
+	// We have a connection.
 	//
-	// There is no "invalid thread handle" value for a UN*X
-	// pthread_t, so we just zero it out.
+	// If it's a passive mode connection, check whether the connecting
+	// host is among the ones allowed.
 	//
-#ifdef _WIN32
-	threaddata.thread = INVALID_HANDLE_VALUE;
-#else
-	memset(&threaddata.thread, 0, sizeof(threaddata.thread));
-#endif
+	// In either case, we were handed a copy of the host list; free it
+	// as soon as we're done with it.
+	//
+	if (pars.isactive)
+	{
+		// Nothing to do.
+		free(passiveClients);
+		passiveClients = NULL;
+	}
+	else
+	{
+		struct sockaddr_storage from;
+		socklen_t fromlen;
 
-	*errbuf = 0;	// Initialize errbuf
+		//
+		// Get the address of the other end of the connection.
+		//
+		fromlen = sizeof(struct sockaddr_storage);
+		if (getpeername(pars.sockctrl, (struct sockaddr *)&from,
+		    &fromlen) == -1)
+		{
+			sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
+			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+			goto end;
+		}
+
+		//
+		// Are they in the list of host/port combinations we allow?
+		//
+		host_port_check_status = sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE);
+		free(passiveClients);
+		passiveClients = NULL;
+		if (host_port_check_status < 0)
+		{
+			if (host_port_check_status == -2) {
+				//
+				// We got an error; log it.
+				//
+				rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+			}
+
+			//
+			// Sorry, we can't let you in.
+			//
+			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+			goto end;
+		}
+	}
+
+#ifndef _WIN32
+	//
+	// Catch SIGUSR1, but do nothing.  We use it to interrupt the
+	// capture thread to break it out of a loop in which it's
+	// blocked waiting for packets to arrive.
+	//
+	// We don't want interrupted system calls to restart, so that
+	// the read routine for the pcap_t gets EINTR rather than
+	// restarting if it's blocked in a system call.
+	//
+	memset(&action, 0, sizeof (action));
+	action.sa_handler = noop_handler;
+	action.sa_flags = 0;
+	sigemptyset(&action.sa_mask);
+	sigaction(SIGUSR1, &action, NULL);
+#endif
 
 	//
 	// The client must first authenticate; loop until they send us a
@@ -198,10 +505,11 @@
 	while (!authenticated)
 	{
 		//
-		// If we're in active mode, we have to check for the
-		// initial timeout.
-		//
-		// XXX - do this on *every* trip through the loop?
+		// If we're not in active mode, we use select(), with a
+		// timeout, to wait for an authentication request; if
+		// the timeout expires, we drop the connection, so that
+		// a client can't just connect to us and leave us
+		// waiting forever.
 		//
 		if (!pars.isactive)
 		{
@@ -210,13 +518,13 @@
 			tv.tv_sec = RPCAP_TIMEOUT_INIT;
 			tv.tv_usec = 0;
 
-			FD_SET(pars.sockctrl_in, &rfds);
+			FD_SET(pars.sockctrl, &rfds);
 
-			retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv);
+			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
 			if (retval == -1)
 			{
-				sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
-				if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+				sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 				goto end;
 			}
@@ -225,7 +533,7 @@
 			// So, this was a fake connection. Drop it down
 			if (retval == 0)
 			{
-				if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
+				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 				goto end;
 			}
@@ -234,7 +542,7 @@
 		//
 		// Read the message header from the client.
 		//
-		nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header);
+		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
 		if (nrecv == -1)
 		{
 			// Fatal error.
@@ -249,49 +557,17 @@
 		plen = header.plen;
 
 		//
-		// Did the client specify a version we can handle?
+		// While we're in the authentication pharse, all requests
+		// must use version 0.
 		//
-		if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+		if (header.ver != 0)
 		{
 			//
-			// Tell them it's not a valid protocol version.
+			// Send it back to them with their version.
 			//
-			uint8 reply_version;
-
-			//
-			// If RPCAP_MIN_VERSION is 0, no version is too
-			// old, as the oldest supported version is 0,
-			// and there are no negative versions.
-			//
-#if RPCAP_MIN_VERSION != 0
-			if (header.ver < RPCAP_MIN_VERSION)
-			{
-				//
-				// Their maximum version is too old;
-				// there *is* no version we can both
-				// handle, and they might reject
-				// an error with a version they don't
-				// understand, so reply with the
-				// version they sent.  That may
-				// make them retry with that version,
-				// but they'll give up on that
-				// failure.
-				//
-				reply_version = header.ver;
-			}
-			else
-#endif
-			{
-				//
-				// Their maximum version is too new,
-				// but they might be able to handle
-				// *our* maximum version, so reply
-				// with that version.
-				//
-				reply_version = RPCAP_MAX_VERSION;
-			}
-			if (rpcap_senderror(pars.sockctrl_out, reply_version,
-			    PCAP_ERR_WRONGVER, "RPCAP version number mismatch",
+			if (rpcap_senderror(pars.sockctrl, pars.ssl, header.ver,
+			    PCAP_ERR_WRONGVER,
+			    "RPCAP version in requests in the authentication phase must be 0",
 			    errbuf) == -1)
 			{
 				// That failed; log a message and give up.
@@ -299,22 +575,12 @@
 				goto end;
 			}
 
-			// Discard the rest of the message.
-			if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
-			{
-				// Network error.
-				goto end;
-			}
-
-			// Let them try again.
-			continue;
+			// Discard the rest of the message and drop the
+			// connection.
+			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
+			goto end;
 		}
 
-		//
-		// OK, we use the version the client specified.
-		//
-		pars.protocol_version = header.ver;
-
 		switch (header.type)
 		{
 			case RPCAP_MSG_AUTH_REQ:
@@ -344,7 +610,7 @@
 				// Discard the rest of the message, if
 				// there is anything more.
 				//
-				(void)rpcapd_discard(pars.sockctrl_in, plen);
+				(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
 				// We're done with this client.
 				goto end;
 
@@ -356,7 +622,7 @@
 				// an error message rather than a "let
 				// me log in" message, indicating that
 				// we're not allowed to connect to them?
-				(void)daemon_msg_err(pars.sockctrl_in, plen);
+				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
 				goto end;
 
 			case RPCAP_MSG_FINDALLIF_REQ:
@@ -373,21 +639,21 @@
 				msg_type_string = rpcap_msg_type_string(header.type);
 				if (msg_type_string != NULL)
 				{
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
 				}
 				else
 				{
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
 				}
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_WRONGMSG,
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver, PCAP_ERR_WRONGMSG,
 				    errmsgbuf, errbuf) == -1)
 				{
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Network error.
 					goto end;
@@ -409,21 +675,21 @@
 				msg_type_string = rpcap_msg_type_string(header.type);
 				if (msg_type_string != NULL)
 				{
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
 				}
 				else
 				{
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
 				}
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_WRONGMSG,
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver, PCAP_ERR_WRONGMSG,
 				    errmsgbuf, errbuf) == -1)
 				{
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Fatal error.
 					goto end;
@@ -434,16 +700,16 @@
 				//
 				// Unknown message type.
 				//
-				pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_WRONGMSG,
+				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver, PCAP_ERR_WRONGMSG,
 				    errmsgbuf, errbuf) == -1)
 				{
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Fatal error.
 					goto end;
@@ -481,7 +747,7 @@
 		//
 		// Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
 		//  sockdata is 0
-		if ((!pars.isactive) &&  ((session == NULL) || ((session != NULL) && (session->sockdata == 0))))
+		if ((!pars.isactive) && (session == NULL || session->sockdata == 0))
 		{
 			// Check for the initial timeout
 			FD_ZERO(&rfds);
@@ -489,14 +755,17 @@
 			tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
 			tv.tv_usec = 0;
 
-			FD_SET(pars.sockctrl_in, &rfds);
-
-			retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv);
+			FD_SET(pars.sockctrl, &rfds);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+			retval = 1;
+#else
+			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
+#endif
 			if (retval == -1)
 			{
-				sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_NETW,
+				sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    0, PCAP_ERR_NETW,
 				    errmsgbuf, errbuf) == -1)
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 				goto end;
@@ -506,9 +775,8 @@
 			// So, this was a fake connection. Drop it down
 			if (retval == 0)
 			{
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version,
-				    PCAP_ERR_INITTIMEOUT,
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    0, PCAP_ERR_INITTIMEOUT,
 				    "The RPCAP initial timeout has expired",
 				    errbuf) == -1)
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -519,7 +787,7 @@
 		//
 		// Read the message header from the client.
 		//
-		nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header);
+		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
 		if (nrecv == -1)
 		{
 			// Fatal error.
@@ -534,21 +802,20 @@
 		plen = header.plen;
 
 		//
-		// Did the client specify the version we negotiated?
+		// Did the client specify a protocol version that we
+		// support?
 		//
-		// For now, there's only one version.
-		//
-		if (header.ver != pars.protocol_version)
+		if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
 		{
 			//
-			// Tell them it's not the negotiated version.
+			// Tell them it's not a supported version.
 			// Send the error message with their version,
 			// so they don't reject it as having the wrong
 			// version.
 			//
-			if (rpcap_senderror(pars.sockctrl_out,
+			if (rpcap_senderror(pars.sockctrl, pars.ssl,
 			    header.ver, PCAP_ERR_WRONGVER,
-			    "RPCAP version in message isn't the negotiated version",
+			    "RPCAP version in message isn't supported by the server",
 			    errbuf) == -1)
 			{
 				// That failed; log a message and give up.
@@ -557,7 +824,7 @@
 			}
 
 			// Discard the rest of the message.
-			(void)rpcapd_discard(pars.sockctrl_in, plen);
+			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
 			// Give up on them.
 			goto end;
 		}
@@ -566,7 +833,7 @@
 		{
 			case RPCAP_MSG_ERROR:		// The other endpoint reported an error
 			{
-				(void)daemon_msg_err(pars.sockctrl_in, plen);
+				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
 				// Do nothing; just exit; the error code is already into the errbuf
 				// XXX - actually exit....
 				break;
@@ -574,7 +841,7 @@
 
 			case RPCAP_MSG_FINDALLIF_REQ:
 			{
-				if (daemon_msg_findallif_req(&pars, plen) == -1)
+				if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
 				{
 					// Fatal error; a message has
 					// been logged, so just give up.
@@ -594,7 +861,8 @@
 				// us multiple open requests, the last
 				// one wins.
 				//
-				retval = daemon_msg_open_req(&pars, plen, source, sizeof(source));
+				retval = daemon_msg_open_req(header.ver, &pars,
+				    plen, source, sizeof(source));
 				if (retval == -1)
 				{
 					// Fatal error; a message has
@@ -611,8 +879,8 @@
 				{
 					// They never told us what device
 					// to capture on!
-					if (rpcap_senderror(pars.sockctrl_out,
-					    pars.protocol_version,
+					if (rpcap_senderror(pars.sockctrl, pars.ssl,
+					    header.ver,
 					    PCAP_ERR_STARTCAPTURE,
 					    "No capture device was specified",
 					    errbuf) == -1)
@@ -622,14 +890,16 @@
 						rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 						goto end;
 					}
-					if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+					if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 					{
 						goto end;
 					}
 					break;
 				}
 
-				if (daemon_msg_startcap_req(&pars, plen, &threaddata, source, &session, &samp_param) == -1)
+				if (daemon_msg_startcap_req(header.ver, &pars,
+				    plen, source, &session, &samp_param,
+				    uses_ssl) == -1)
 				{
 					// Fatal error; a message has
 					// been logged, so just give up.
@@ -642,7 +912,8 @@
 			{
 				if (session)
 				{
-					if (daemon_msg_updatefilter_req(&pars, session, plen) == -1)
+					if (daemon_msg_updatefilter_req(header.ver,
+					    &pars, session, plen) == -1)
 					{
 						// Fatal error; a message has
 						// been logged, so just give up.
@@ -651,8 +922,8 @@
 				}
 				else
 				{
-					if (rpcap_senderror(pars.sockctrl_out,
-					    pars.protocol_version,
+					if (rpcap_senderror(pars.sockctrl, pars.ssl,
+					    header.ver,
 					    PCAP_ERR_UPDATEFILTER,
 					    "Device not opened. Cannot update filter",
 					    errbuf) == -1)
@@ -673,13 +944,14 @@
 				// This is used only in case of active mode.
 				//
 				client_told_us_to_close = 1;
-				SOCK_DEBUG_MESSAGE("The other end system asked to close the connection.");
+				rpcapd_log(LOGPRIO_DEBUG, "The other end system asked to close the connection.");
 				goto end;
 			}
 
 			case RPCAP_MSG_STATS_REQ:
 			{
-				if (daemon_msg_stats_req(&pars, session, plen, &stats, svrcapt) == -1)
+				if (daemon_msg_stats_req(header.ver, &pars,
+				    session, plen, &stats, svrcapt) == -1)
 				{
 					// Fatal error; a message has
 					// been logged, so just give up.
@@ -705,7 +977,8 @@
 						svrcapt = 0;
 					}
 
-					if (daemon_msg_endcap_req(&pars, session, &threaddata) == -1)
+					if (daemon_msg_endcap_req(header.ver,
+					    &pars, session) == -1)
 					{
 						free(session);
 						session = NULL;
@@ -718,8 +991,8 @@
 				}
 				else
 				{
-					rpcap_senderror(pars.sockctrl_out,
-					    pars.protocol_version,
+					rpcap_senderror(pars.sockctrl, pars.ssl,
+					    header.ver,
 					    PCAP_ERR_ENDCAPTURE,
 					    "Device not opened. Cannot close the capture",
 					    errbuf);
@@ -729,7 +1002,8 @@
 
 			case RPCAP_MSG_SETSAMPLING_REQ:
 			{
-				if (daemon_msg_setsampling_req(&pars, plen, &samp_param) == -1)
+				if (daemon_msg_setsampling_req(header.ver,
+				    &pars, plen, &samp_param) == -1)
 				{
 					// Fatal error; a message has
 					// been logged, so just give up.
@@ -745,8 +1019,8 @@
 				// get to reauthenticate.
 				//
 				rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version,
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver,
 				    PCAP_ERR_WRONGMSG,
 				    "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
 				    errbuf) == -1)
@@ -755,7 +1029,7 @@
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Fatal error.
 					goto end;
@@ -778,22 +1052,22 @@
 				if (msg_type_string != NULL)
 				{
 					rpcapd_log(LOGPRIO_INFO, "The client sent a %s server-to-client message", msg_type_string);
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
 				}
 				else
 				{
 					rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
-					pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
 				}
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_WRONGMSG,
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver, PCAP_ERR_WRONGMSG,
 				    errmsgbuf, errbuf) == -1)
 				{
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Fatal error.
 					goto end;
@@ -805,16 +1079,16 @@
 				// Unknown message type.
 				//
 				rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
-				pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
-				if (rpcap_senderror(pars.sockctrl_out,
-				    pars.protocol_version, PCAP_ERR_WRONGMSG,
+				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+				if (rpcap_senderror(pars.sockctrl, pars.ssl,
+				    header.ver, PCAP_ERR_WRONGMSG,
 				    errbuf, errmsgbuf) == -1)
 				{
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 					goto end;
 				}
 				// Discard the rest of the message.
-				if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
 				{
 					// Fatal error.
 					goto end;
@@ -825,58 +1099,34 @@
 	}
 
 end:
-	// The child thread is about to end
-
-	// perform pcap_t cleanup, in case it has not been done
+	// The service loop is finishing up.
+	// If we have a capture session running, close it.
 	if (session)
 	{
-		if (threaddata.have_thread)
-		{
-#ifdef _WIN32
-			//
-			// Tell the data connection thread main capture
-			// loop to break out of that loop.
-			//
-			pcap_breakloop(session->fp);
-
-			//
-			// If it's currently blocked waiting for packets
-			// to arrive, try to wake it up, so it can see
-			// the "break out of the loop" indication.
-			//
-			SetEvent(pcap_getevent(session->fp));
-
-			//
-			// Wait for the thread to exit, so we don't close
-			// sockets out from under it.
-			//
-			// XXX - have a timeout, so we don't wait forever?
-			//
-			WaitForSingleObject(threaddata.thread, INFINITE);
-
-			//
-			// Release the thread handle, as we're done with
-			// it.
-			//
-			CloseHandle(threaddata.thread);
-#else
-			pthread_cancel(threaddata.thread);
-#endif
-			threaddata.have_thread = 0;
-		}
-		if (session->sockdata)
-		{
-			sock_close(session->sockdata, NULL, 0);
-			session->sockdata = 0;
-		}
-		pcap_close(session->fp);
+		session_close(session);
 		free(session);
 		session = NULL;
 	}
 
+	if (passiveClients) {
+		free(passiveClients);
+	}
+	//
+	// Finish using the SSL handle for the control socket, if we
+	// have an SSL connection, and close the control socket.
+	//
+#ifdef HAVE_OPENSSL
+	if (ssl)
+	{
+		// Finish using the SSL handle for the socket.
+		// This must be done *before* the socket is closed.
+		ssl_finish(ssl);
+	}
+#endif
+	sock_close(sockctrl, NULL, 0);
+
 	// Print message and return
-	SOCK_DEBUG_MESSAGE("I'm exiting from the child loop");
-	SOCK_DEBUG_MESSAGE(errbuf);
+	rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
 
 	return client_told_us_to_close;
 }
@@ -885,7 +1135,7 @@
  * This handles the RPCAP_MSG_ERR message.
  */
 static int
-daemon_msg_err(SOCKET sockctrl_in, uint32 plen)
+daemon_msg_err(SOCKET sockctrl, SSL *ssl, uint32 plen)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];
 	char remote_errbuf[PCAP_ERRBUF_SIZE];
@@ -896,7 +1146,7 @@
 		 * Message is too long; just read as much of it as we
 		 * can into the buffer provided, and discard the rest.
 		 */
-		if (sock_recv(sockctrl_in, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+		if (sock_recv(sockctrl, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
@@ -904,7 +1154,7 @@
 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
 			return -1;
 		}
-		if (rpcapd_discard(sockctrl_in, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
+		if (rpcapd_discard(sockctrl, ssl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
 		{
 			// Network error.
 			return -1;
@@ -922,7 +1172,7 @@
 	}
 	else
 	{
-		if (sock_recv(sockctrl_in, remote_errbuf, plen,
+		if (sock_recv(sockctrl, ssl, remote_errbuf, plen,
 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
@@ -968,11 +1218,13 @@
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
-	struct rpcap_header header;		// RPCAP message general header
 	int status;
 	struct rpcap_auth auth;			// RPCAP authentication header
+	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
+	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
+	struct rpcap_authreply *authreply;	// authentication reply message
 
-	status = rpcapd_recv(pars->sockctrl_in, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
+	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
 	if (status == -1)
 	{
 		return -1;
@@ -989,8 +1241,16 @@
 			if (!pars->nullAuthAllowed)
 			{
 				// Send the client an error reply.
-				pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Authentication failed; NULL authentication not permitted.");
-				goto error;
+				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+				    "Authentication failed; NULL authentication not permitted.");
+				if (rpcap_senderror(pars->sockctrl, pars->ssl,
+				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
+				{
+					// That failed; log a message and give up.
+					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+					return -1;
+				}
+				goto error_noreply;
 			}
 			break;
 		}
@@ -1008,7 +1268,7 @@
 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
 				goto error;
 			}
-			status = rpcapd_recv(pars->sockctrl_in, username, usernamelen, &plen, errmsgbuf);
+			status = rpcapd_recv(pars->sockctrl, pars->ssl, username, usernamelen, &plen, errmsgbuf);
 			if (status == -1)
 			{
 				free(username);
@@ -1030,7 +1290,7 @@
 				free(username);
 				goto error;
 			}
-			status = rpcapd_recv(pars->sockctrl_in, passwd, passwdlen, &plen, errmsgbuf);
+			status = rpcapd_recv(pars->sockctrl, pars->ssl, passwd, passwdlen, &plen, errmsgbuf);
 			if (status == -1)
 			{
 				free(username);
@@ -1053,9 +1313,8 @@
 				//
 				free(username);
 				free(passwd);
-				if (rpcap_senderror(pars->sockctrl_out,
-				    pars->protocol_version,
-				    PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+				if (rpcap_senderror(pars->sockctrl, pars->ssl,
+				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
 				{
 					// That failed; log a message and give up.
 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1082,23 +1341,49 @@
 			}
 
 		default:
-			pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
-			goto error;
+			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+			    "Authentication type not recognized.");
+			if (rpcap_senderror(pars->sockctrl, pars->ssl,
+			    0, PCAP_ERR_AUTH_TYPE_NOTSUP, errmsgbuf, errbuf) == -1)
+			{
+				// That failed; log a message and give up.
+				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+				return -1;
+			}
+			goto error_noreply;
 	}
 
 	// The authentication succeeded; let the client know.
-	rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_AUTH_REPLY, 0, 0);
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
 
-	// Send the ok message back
-	if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+	rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
+	    RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
+
+	authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
+	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	//
+	// Indicate to our peer what versions we support.
+	//
+	memset(authreply, 0, sizeof(struct rpcap_authreply));
+	authreply->minvers = RPCAP_MIN_VERSION;
+	authreply->maxvers = RPCAP_MAX_VERSION;
+
+	// Send the reply.
+	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
-		// That failed; log a messsage and give up.
+		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
 	}
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
@@ -1106,8 +1391,8 @@
 	return 0;
 
 error:
-	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
-	    PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+	if (rpcap_senderror(pars->sockctrl, pars->ssl, 0, PCAP_ERR_AUTH,
+	    errmsgbuf, errbuf) == -1)
 	{
 		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1116,7 +1401,7 @@
 
 error_noreply:
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
@@ -1136,16 +1421,32 @@
 	 * policies, user right assignment)
 	 * However, it seems to me that if you run it as a service, this
 	 * right should be provided by default.
+	 *
+	 * XXX - hopefully, this returns errors such as ERROR_LOGON_FAILURE,
+	 * which merely indicates that the user name or password is
+	 * incorrect, not whether it's the user name or the password
+	 * that's incorrect, so a client that's trying to brute-force
+	 * accounts doesn't know whether it's the user name or the
+	 * password that's incorrect, so it doesn't know whether to
+	 * stop trying to log in with a given user name and move on
+	 * to another user name.
 	 */
+	DWORD error;
 	HANDLE Token;
+	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to log
+
 	if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
 	{
-		int error;
-
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
 		error = GetLastError();
-		FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
-			PCAP_ERRBUF_SIZE, NULL);
-
+		if (error != ERROR_LOGON_FAILURE)
+		{
+			// Some error other than an authentication error;
+			// log it.
+			pcap_fmt_errmsg_for_win32_err(errmsgbuf,
+			    PCAP_ERRBUF_SIZE, error, "LogonUser() failed");
+			rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+		}
 		return -1;
 	}
 
@@ -1153,12 +1454,10 @@
 	// I didn't test it.
 	if (ImpersonateLoggedOnUser(Token) == 0)
 	{
-		int error;
-
-		error = GetLastError();
-		FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
-			PCAP_ERRBUF_SIZE, NULL);
-
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+		pcap_fmt_errmsg_for_win32_err(errmsgbuf, PCAP_ERRBUF_SIZE,
+		    GetLastError(), "ImpersonateLoggedOnUser() failed");
+		rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
 		CloseHandle(Token);
 		return -1;
 	}
@@ -1170,7 +1469,7 @@
 	/*
 	 * See
 	 *
-	 *	http://www.unixpapa.com/incnote/passwd.html
+	 *	https://www.unixpapa.com/incnote/passwd.html
 	 *
 	 * We use the Solaris/Linux shadow password authentication if
 	 * we have getspnam(), otherwise we just do traditional
@@ -1186,16 +1485,18 @@
 	 * only password database or some other authentication mechanism,
 	 * behind its API.
 	 */
+	int error;
 	struct passwd *user;
 	char *user_password;
 #ifdef HAVE_GETSPNAM
 	struct spwd *usersp;
 #endif
+	char *crypt_password;
 
 	// This call is needed to get the uid
 	if ((user = getpwnam(username)) == NULL)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
 		return -1;
 	}
 
@@ -1203,7 +1504,7 @@
 	// This call is needed to get the password; otherwise 'x' is returned
 	if ((usersp = getspnam(username)) == NULL)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
 		return -1;
 	}
 	user_password = usersp->sp_pwdp;
@@ -1221,23 +1522,52 @@
 	user_password = user->pw_passwd;
 #endif
 
-	if (strcmp(user_password, (char *) crypt(password, user_password)) != 0)
+	//
+	// The Single UNIX Specification says that if crypt() fails it
+	// sets errno, but some implementatons that haven't been run
+	// through the SUS test suite might not do so.
+	//
+	errno = 0;
+	crypt_password = crypt(password, user_password);
+	if (crypt_password == NULL)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
+		error = errno;
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+		if (error == 0)
+		{
+			// It didn't set errno.
+			rpcapd_log(LOGPRIO_ERROR, "crypt() failed");
+		}
+		else
+		{
+			rpcapd_log(LOGPRIO_ERROR, "crypt() failed: %s",
+			    strerror(error));
+		}
+		return -1;
+	}
+	if (strcmp(user_password, crypt_password) != 0)
+	{
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
 		return -1;
 	}
 
 	if (setuid(user->pw_uid))
 	{
+		error = errno;
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "setuid");
+		    error, "setuid");
+		rpcapd_log(LOGPRIO_ERROR, "setuid() failed: %s",
+		    strerror(error));
 		return -1;
 	}
 
 /*	if (setgid(user->pw_gid))
 	{
+		error = errno;
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "setgid");
+		rpcapd_log(LOGPRIO_ERROR, "setgid() failed: %s",
+		    strerror(error));
 		return -1;
 	}
 */
@@ -1247,8 +1577,23 @@
 
 }
 
+/*
+ * Make sure that the reply length won't overflow 32 bits if we add the
+ * specified amount to it.  If it won't, add that amount to it.
+ *
+ * We check whether replylen + itemlen > UINT32_MAX, but subtract itemlen
+ * from both sides, to prevent overflow.
+ */
+#define CHECK_AND_INCREASE_REPLY_LEN(itemlen) \
+	if (replylen > UINT32_MAX - (itemlen)) { \
+		pcap_strlcpy(errmsgbuf, "Reply length doesn't fit in 32 bits", \
+		    sizeof (errmsgbuf)); \
+		goto error; \
+	} \
+	replylen += (uint32)(itemlen)
+
 static int
-daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
+daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
@@ -1258,10 +1603,11 @@
 	pcap_if_t *d;				// temp pointer needed to scan the interface chain
 	struct pcap_addr *address;		// pcap structure that keeps a network address of an interface
 	struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
+	uint32 replylen;			// length of reply payload
 	uint16 nif = 0;				// counts the number of interface listed
 
 	// Discard the rest of the message; there shouldn't be any payload.
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		// Network error.
 		return -1;
@@ -1273,7 +1619,7 @@
 
 	if (alldevs == NULL)
 	{
-		if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+		if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
 			PCAP_ERR_NOREMOTEIF,
 			"No interfaces found! Make sure libpcap/WinPcap is properly installed"
 			" and you have the right to access to the remote device.",
@@ -1285,18 +1631,37 @@
 		return 0;
 	}
 
-	// checks the number of interfaces and it computes the total length of the payload
+	// This checks the number of interfaces and computes the total
+	// length of the payload.
+	replylen = 0;
 	for (d = alldevs; d != NULL; d = d->next)
 	{
 		nif++;
 
-		if (d->description)
-			plen+= strlen(d->description);
-		if (d->name)
-			plen+= strlen(d->name);
+		if (d->description) {
+			size_t stringlen = strlen(d->description);
+			if (stringlen > UINT16_MAX) {
+				pcap_strlcpy(errmsgbuf,
+				    "Description length doesn't fit in 16 bits",
+				    sizeof (errmsgbuf));
+				goto error;
+			}
+			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
+		}
+		if (d->name) {
+			size_t stringlen = strlen(d->name);
+			if (stringlen > UINT16_MAX) {
+				pcap_strlcpy(errmsgbuf,
+				    "Name length doesn't fit in 16 bits",
+				    sizeof (errmsgbuf));
+				goto error;
+			}
+			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
+		}
 
-		plen+= sizeof(struct rpcap_findalldevs_if);
+		CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_findalldevs_if));
 
+		uint16_t naddrs = 0;
 		for (address = d->addresses; address != NULL; address = address->next)
 		{
 			/*
@@ -1308,7 +1673,14 @@
 #ifdef AF_INET6
 			case AF_INET6:
 #endif
-				plen+= (sizeof(struct rpcap_sockaddr) * 4);
+				CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_sockaddr) * 4);
+				if (naddrs == UINT16_MAX) {
+					pcap_strlcpy(errmsgbuf,
+					    "Number of interfaces doesn't fit in 16 bits",
+					    sizeof (errmsgbuf));
+					goto error;
+				}
+				naddrs++;
 				break;
 
 			default:
@@ -1317,14 +1689,14 @@
 		}
 	}
 
-	// RPCAP findalldevs command
+	// RPCAP findalldevs reply
 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf,
 	    PCAP_ERRBUF_SIZE) == -1)
 		goto error;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
-	    RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
+	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+	    RPCAP_MSG_FINDALLIF_REPLY, nif, replylen);
 
 	// send the interface list
 	for (d = alldevs; d != NULL; d = d->next)
@@ -1339,10 +1711,18 @@
 
 		memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if));
 
-		if (d->description) ldescr = (short) strlen(d->description);
-		else ldescr = 0;
-		if (d->name) lname = (short) strlen(d->name);
-		else lname = 0;
+		/*
+		 * We've already established that the string lengths
+		 * fit in 16 bits.
+		 */
+		if (d->description)
+			ldescr = (uint16) strlen(d->description);
+		else
+			ldescr = 0;
+		if (d->name)
+			lname = (uint16) strlen(d->name);
+		else
+			lname = 0;
 
 		findalldevs_if->desclen = htons(ldescr);
 		findalldevs_if->namelen = htons(lname);
@@ -1427,7 +1807,7 @@
 	pcap_freealldevs(alldevs);
 
 	// Send a final command that says "now send it!"
-	if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
@@ -1439,7 +1819,7 @@
 	if (alldevs)
 		pcap_freealldevs(alldevs);
 
-	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
 	    PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1)
 	{
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1453,7 +1833,8 @@
 	to discard excess data in the message, if present)
 */
 static int
-daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen)
+daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, size_t sourcelen)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
@@ -1465,11 +1846,11 @@
 
 	if (plen > sourcelen - 1)
 	{
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
 		goto error;
 	}
 
-	nread = sock_recv(pars->sockctrl_in, source, plen,
+	nread = sock_recv(pars->sockctrl, pars->ssl, source, plen,
 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
 	if (nread == -1)
 	{
@@ -1479,8 +1860,13 @@
 	source[nread] = '\0';
 	plen -= nread;
 
-	// XXX - make sure it's *not* a URL; we don't support opening
-	// remote devices here.
+	// Is this a URL rather than a device?
+	// If so, reject it.
+	if (is_url(source))
+	{
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string refers to a remote device");
+		goto error;
+	}
 
 	// Open the selected device
 	// This is a fake open, since we do that only to get the needed parameters, then we close the device again
@@ -1496,7 +1882,7 @@
 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
 		goto error;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
 	    RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
 
 	openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
@@ -1507,13 +1893,20 @@
 
 	memset(openreply, 0, sizeof(struct rpcap_openreply));
 	openreply->linktype = htonl(pcap_datalink(fp));
-	openreply->tzoff = 0; /* This is always 0 for live captures */
+	/*
+	 * This is always 0 for live captures; we no longer support it
+	 * as something we read from capture files and supply to
+	 * clients, but we have to send it over the wire, as open
+	 * replies are expected to have 8 bytes of payload by
+	 * existing clients.
+	 */
+	openreply->tzoff = 0;
 
 	// We're done with the pcap_t.
 	pcap_close(fp);
 
 	// Send the reply.
-	if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
@@ -1521,8 +1914,8 @@
 	return 0;
 
 error:
-	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
-	    PCAP_ERR_OPEN, errmsgbuf, errbuf) == -1)
+	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_OPEN,
+	    errmsgbuf, errbuf) == -1)
 	{
 		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1530,7 +1923,7 @@
 	}
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
@@ -1542,7 +1935,9 @@
 	to discard excess data in the message, if present)
 */
 static int
-daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param _U_)
+daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param _U_, int uses_ssl)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
@@ -1554,17 +1949,12 @@
 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
 
 	// socket-related variables
-	SOCKET sockdata = INVALID_SOCKET;	// socket descriptor of the data connection
 	struct addrinfo hints;			// temp, needed to open a socket connection
 	struct addrinfo *addrinfo;		// temp, needed to open a socket connection
 	struct sockaddr_storage saddr;		// temp, needed to retrieve the network data port chosen on the local machine
 	socklen_t saddrlen;			// temp, needed to retrieve the network data port chosen on the local machine
 	int ret;				// return value from functions
 
-#ifndef _WIN32
-	pthread_attr_t detachedAttribute;	// temp, needed to set the created thread as detached
-#endif
-
 	// RPCAP-related variables
 	struct rpcap_startcapreq startcapreq;		// start capture request message
 	struct rpcap_startcapreply *startcapreply;	// start capture reply message
@@ -1572,7 +1962,7 @@
 
 	addrinfo = NULL;
 
-	status = rpcapd_recv(pars->sockctrl_in, (char *) &startcapreq,
+	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &startcapreq,
 	    sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
 	if (status == -1)
 	{
@@ -1585,14 +1975,42 @@
 
 	startcapreq.flags = ntohs(startcapreq.flags);
 
+	// Check that the client does not ask for UDP is the server has been asked
+	// to enforce encryption, as SSL is not supported yet with UDP:
+	if (uses_ssl && (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM))
+	{
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "SSL not supported with UDP forward of remote packets");
+		goto error;
+	}
+
 	// Create a session structure
 	session = malloc(sizeof(struct session));
 	if (session == NULL)
 	{
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
 		goto error;
 	}
 
+	session->sockdata = INVALID_SOCKET;
+	session->ctrl_ssl = session->data_ssl = NULL;
+	// We don't have a thread yet.
+	session->have_thread = 0;
+	//
+	// We *shouldn't* have to initialize the thread indicator
+	// itself, because the compiler *should* realize that we
+	// only use this if have_thread isn't 0, but we *do* have
+	// to do it, because not all compilers *do* realize that.
+	//
+	// There is no "invalid thread handle" value for a UN*X
+	// pthread_t, so we just zero it out.
+	//
+#ifdef _WIN32
+	session->thread = INVALID_HANDLE_VALUE;
+#else
+	memset(&session->thread, 0, sizeof(session->thread));
+#endif
+
 	// Open the selected device
 	if ((session->fp = pcap_open_live(source,
 			ntohl(startcapreq.snaplen),
@@ -1624,9 +2042,9 @@
 	we want to connect to
 	*/
 	saddrlen = sizeof(struct sockaddr_storage);
-	if (getpeername(pars->sockctrl_in, (struct sockaddr *) &saddr, &saddrlen) == -1)
+	if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 	{
-		sock_geterror("getpeername(): ", errmsgbuf, PCAP_ERRBUF_SIZE);
+		sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
 		goto error;
 	}
 
@@ -1637,20 +2055,20 @@
 	// Now we have to create a new socket to send packets
 	if (serveropen_dp)		// Data connection is opened by the server toward the client
 	{
-		pcap_snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
+		snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
 
 		// Get the name of the other peer (needed to connect to that specific network address)
 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peerhost,
 				sizeof(peerhost), NULL, 0, NI_NUMERICHOST))
 		{
-			sock_geterror("getnameinfo(): ", errmsgbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getnameinfo()", errmsgbuf, PCAP_ERRBUF_SIZE);
 			goto error;
 		}
 
 		if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
 			goto error;
 
-		if ((sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+		if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
 			goto error;
 	}
 	else		// Data connection is opened by the client toward the server
@@ -1661,14 +2079,14 @@
 		if (sock_initaddress(NULL, "0", &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
 			goto error;
 
-		if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+		if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
 			goto error;
 
 		// get the complete sockaddr structure used in the data connection
 		saddrlen = sizeof(struct sockaddr_storage);
-		if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		if (getsockname(session->sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
-			sock_geterror("getsockname(): ", errmsgbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getsockname()", errmsgbuf, PCAP_ERRBUF_SIZE);
 			goto error;
 		}
 
@@ -1676,7 +2094,7 @@
 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
 				0, portdata, sizeof(portdata), NI_NUMERICSERV))
 		{
-			sock_geterror("getnameinfo(): ", errmsgbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("getnameinfo()", errmsgbuf, PCAP_ERRBUF_SIZE);
 			goto error;
 		}
 	}
@@ -1686,11 +2104,12 @@
 	addrinfo = NULL;
 
 	// Needed to send an error on the ctrl connection
-	session->sockctrl_out = pars->sockctrl_out;
-	session->protocol_version = pars->protocol_version;
+	session->sockctrl = pars->sockctrl;
+	session->ctrl_ssl = pars->ssl;
+	session->protocol_version = ver;
 
 	// Now I can set the filter
-	ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf);
+	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
 	if (ret == -1)
 	{
 		// Fatal error.  A message has been logged; just give up.
@@ -1707,7 +2126,7 @@
 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
 		goto error;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
 	    RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
 
 	startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
@@ -1725,7 +2144,7 @@
 		startcapreply->portdata = htons(port);
 	}
 
-	if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
 		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1739,52 +2158,61 @@
 		// Connection creation
 		saddrlen = sizeof(struct sockaddr_storage);
 
-		socktemp = accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
+		socktemp = accept(session->sockdata, (struct sockaddr *) &saddr, &saddrlen);
 
 		if (socktemp == INVALID_SOCKET)
 		{
-			sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
+			sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
 			rpcapd_log(LOGPRIO_ERROR, "Accept of data connection failed: %s",
 			    errbuf);
 			goto error;
 		}
 
 		// Now that I accepted the connection, the server socket is no longer needed
-		sock_close(sockdata, NULL, 0);
-		sockdata = socktemp;
+		sock_close(session->sockdata, NULL, 0);
+		session->sockdata = socktemp;
 	}
 
-	session->sockdata = sockdata;
+	SSL *ssl = NULL;
+	if (uses_ssl)
+	{
+#ifdef HAVE_OPENSSL
+		/* In both active or passive cases, wait for the client to initiate the
+		 * TLS handshake. Yes during that time the control socket will not be
+		 * served, but the same was true from the above call to accept(). */
+		ssl = ssl_promotion(1, session->sockdata, errbuf, PCAP_ERRBUF_SIZE);
+		if (! ssl)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "TLS handshake failed: %s", errbuf);
+			goto error;
+		}
+#endif
+	}
+	session->data_ssl = ssl;
 
 	// Now we have to create a new thread to receive packets
 #ifdef _WIN32
-	threaddata->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
+	session->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
 	    (void *) session, 0, NULL);
-	if (threaddata->thread == 0)
+	if (session->thread == 0)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
 		goto error;
 	}
 #else
-	/* GV we need this to create the thread as detached. */
-	/* GV otherwise, the thread handle is not destroyed  */
-	pthread_attr_init(&detachedAttribute);
-	pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
-	ret = pthread_create(&threaddata->thread, &detachedAttribute,
-	    daemon_thrdatamain, (void *) session);
+	ret = pthread_create(&session->thread, NULL, daemon_thrdatamain,
+	    (void *) session);
 	if (ret != 0)
 	{
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 		    ret, "Error creating the data thread");
-		pthread_attr_destroy(&detachedAttribute);
 		goto error;
 	}
-	pthread_attr_destroy(&detachedAttribute);
 #endif
-	threaddata->have_thread = 1;
+	session->have_thread = 1;
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 		goto fatal_error;
 
 	*sessionp = session;
@@ -1800,32 +2228,13 @@
 	if (addrinfo)
 		freeaddrinfo(addrinfo);
 
-	if (threaddata->have_thread)
-	{
-#ifdef _WIN32
-		if (session->fp)
-		{
-			pcap_breakloop(session->fp);
-			SetEvent(pcap_getevent(session->fp));
-		}
-		CloseHandle(threaddata->thread);
-#else
-		pthread_cancel(threaddata->thread);
-#endif
-		threaddata->have_thread = 0;
-	}
-
-	if (sockdata != INVALID_SOCKET)
-		sock_close(sockdata, NULL, 0);
-
 	if (session)
 	{
-		if (session->fp)
-			pcap_close(session->fp);
+		session_close(session);
 		free(session);
 	}
 
-	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
 	    PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1)
 	{
 		// That failed; log a message and give up.
@@ -1834,7 +2243,7 @@
 	}
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		// Network error.
 		return -1;
@@ -1849,51 +2258,9 @@
 	//
 	*sessionp = NULL;
 
-	if (threaddata->have_thread)
-	{
-#ifdef _WIN32
-		if (session && session->fp)
-		{
-			//
-			// Tell the data connection thread main capture
-			// loop to break out of that loop.
-			//
-			pcap_breakloop(session->fp);
-
-			//
-			// If it's currently blocked waiting for packets
-			// to arrive, try to wake it up, so it can see
-			// the "break out of the loop" indication.
-			//
-			SetEvent(pcap_getevent(session->fp));
-		}
-
-		//
-		// Wait for the thread to exit, so we don't close
-		// sockets out from under it.
-		//
-		// XXX - have a timeout, so we don't wait forever?
-		//
-		WaitForSingleObject(threaddata->thread, INFINITE);
-
-		//
-		// Release the thread handle, as we're done with
-		// it.
-		//
-		CloseHandle(threaddata->thread);
-#else
-		pthread_cancel(threaddata->thread);
-#endif
-		threaddata->have_thread = 0;
-	}
-
-	if (sockdata != INVALID_SOCKET)
-		sock_close(sockdata, NULL, 0);
-
 	if (session)
 	{
-		if (session->fp)
-			pcap_close(session->fp);
+		session_close(session);
 		free(session);
 	}
 
@@ -1901,57 +2268,17 @@
 }
 
 static int
-daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struct thread_handle *threaddata)
+daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	struct rpcap_header header;
 
-	if (threaddata->have_thread)
-	{
-#ifdef _WIN32
-		//
-		// Tell the data connection thread main capture loop to
-		// break out of that loop.
-		//
-		pcap_breakloop(session->fp);
+	session_close(session);
 
-		//
-		// If it's currently blocked waiting for packets to
-		// arrive, try to wake it up, so it can see the "break
-		// out of the loop" indication.
-		//
-		SetEvent(pcap_getevent(session->fp));
+	rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
 
-		//
-		// Wait for the thread to exit, so we don't close
-		// sockets out from under it.
-		//
-		// XXX - have a timeout, so we don't wait forever?
-		//
-		WaitForSingleObject(threaddata->thread, INFINITE);
-
-		//
-		// Release the thread handle, as we're done with
-		// it.
-		//
-		CloseHandle(threaddata->thread);
-#else
-		pthread_cancel(threaddata->thread);
-#endif
-		threaddata->have_thread = 0;
-	}
-	if (session->sockdata)
-	{
-		sock_close(session->sockdata, NULL, 0);
-		session->sockdata = 0;
-	}
-
-	pcap_close(session->fp);
-
-	rpcap_createhdr(&header, pars->protocol_version,
-	    RPCAP_MSG_ENDCAP_REPLY, 0, 0);
-
-	if (sock_send(pars->sockctrl_out, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
 		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1961,8 +2288,25 @@
 	return 0;
 }
 
+//
+// We impose a limit on the filter program size, so that, on Windows,
+// where there's only one server process with multiple threads, it's
+// harder to eat all the server address space by sending larger filter
+// programs.  (This isn't an issue on UN*X, where there are multiple
+// server processes, one per client connection.)
+//
+// We pick a value that limits each filter to 64K; that value is twice
+// the in-kernel limit for Linux and 16 times the in-kernel limit for
+// *BSD and macOS.
+//
+// It also prevents an overflow on 32-bit platforms when calculating
+// the total size of the filter program.  (It's not an issue on 64-bit
+// platforms with a 64-bit size_t, as the filter size is 32 bits.)
+//
+#define RPCAP_BPF_MAXINSNS	8192
+
 static int
-daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errmsgbuf)
+daemon_unpackapplyfilter(SOCKET sockctrl, SSL *ctrl_ssl, struct session *session, uint32 *plenp, char *errmsgbuf)
 {
 	int status;
 	struct rpcap_filter filter;
@@ -1971,7 +2315,7 @@
 	struct bpf_program bf_prog;
 	unsigned int i;
 
-	status = rpcapd_recv(sockctrl_in, (char *) &filter,
+	status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &filter,
 	    sizeof(struct rpcap_filter), plenp, errmsgbuf);
 	if (status == -1)
 	{
@@ -1986,10 +2330,17 @@
 
 	if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
 	{
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
 		return -2;
 	}
 
+	if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS)
+	{
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+		    "Filter program is larger than the maximum size of %u instructions",
+		    RPCAP_BPF_MAXINSNS);
+		return -2;
+	}
 	bf_insn = (struct bpf_insn *) malloc (sizeof(struct bpf_insn) * bf_prog.bf_len);
 	if (bf_insn == NULL)
 	{
@@ -2002,7 +2353,7 @@
 
 	for (i = 0; i < bf_prog.bf_len; i++)
 	{
-		status = rpcapd_recv(sockctrl_in, (char *) &insn,
+		status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &insn,
 		    sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
 		if (status == -1)
 		{
@@ -2021,15 +2372,18 @@
 		bf_insn++;
 	}
 
+	//
+	// XXX - pcap_setfilter() should do the validation for us.
+	//
 	if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
 	{
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
 		return -2;
 	}
 
 	if (pcap_setfilter(session->fp, &bf_prog))
 	{
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
 		return -2;
 	}
 
@@ -2037,14 +2391,15 @@
 }
 
 static int
-daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen)
+daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
 	int ret;				// status of daemon_unpackapplyfilter()
 	struct rpcap_header header;		// keeps the answer to the updatefilter command
 
-	ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf);
+	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
 	if (ret == -1)
 	{
 		// Fatal error.  A message has been logged; just give up.
@@ -2057,19 +2412,18 @@
 	}
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		// Network error.
 		return -1;
 	}
 
 	// A response is needed, otherwise the other host does not know that everything went well
-	rpcap_createhdr(&header, pars->protocol_version,
-	    RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
+	rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
 
-	if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
+	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
 	{
-		// That failed; log a messsage and give up.
+		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
 	}
@@ -2077,12 +2431,12 @@
 	return 0;
 
 error:
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
-	rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
-	    PCAP_ERR_UPDATEFILTER, errmsgbuf, NULL);
+	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_UPDATEFILTER,
+	    errmsgbuf, NULL);
 
 	return 0;
 }
@@ -2091,7 +2445,8 @@
 	\brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
 */
 static int
-daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap_sampling *samp_param)
+daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    struct rpcap_sampling *samp_param)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];
@@ -2099,7 +2454,7 @@
 	struct rpcap_sampling rpcap_samp;
 	int status;
 
-	status = rpcapd_recv(pars->sockctrl_in, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
+	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
 	if (status == -1)
 	{
 		return -1;
@@ -2114,17 +2469,16 @@
 	samp_param->value = ntohl(rpcap_samp.value);
 
 	// A response is needed, otherwise the other host does not know that everything went well
-	rpcap_createhdr(&header, pars->protocol_version,
-	    RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
+	rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
 
-	if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
-		// That failed; log a messsage and give up.
+		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
 	}
 
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
@@ -2132,8 +2486,8 @@
 	return 0;
 
 error:
-	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
-	    PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_SETSAMPLING,
+	    errmsgbuf, errbuf) == -1)
 	{
 		// That failed; log a message and give up.
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -2141,7 +2495,7 @@
 	}
 
 	// Check if all the data has been read; if not, discard the data in excess
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		return -1;
 	}
@@ -2150,7 +2504,9 @@
 }
 
 static int
-daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt)
+daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt)
 {
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
@@ -2159,7 +2515,7 @@
 	struct rpcap_stats *netstats;		// statistics sent on the network
 
 	// Checks that the header does not contain other data; if so, discard it
-	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
 	{
 		// Network error.
 		return -1;
@@ -2169,7 +2525,7 @@
 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
 		goto error;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
 	    RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
 
 	netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
@@ -2182,7 +2538,7 @@
 	{
 		if (pcap_stats(session->fp, stats) == -1)
 		{
-			pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
+			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
 			goto error;
 		}
 
@@ -2203,7 +2559,7 @@
 	}
 
 	// Send the packet
-	if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
 		return -1;
@@ -2212,8 +2568,8 @@
 	return 0;
 
 error:
-	rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
-	    PCAP_ERR_GETSTATS, errmsgbuf, NULL);
+	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_GETSTATS,
+	    errmsgbuf, NULL);
 	return 0;
 }
 
@@ -2234,6 +2590,9 @@
 	char *sendbuf;						// temporary buffer in which data to be sent is buffered
 	int sendbufidx;						// index which keeps the number of bytes currently buffered
 	int status;
+#ifndef _WIN32
+	sigset_t sigusr1;			// signal set with just SIGUSR1
+#endif
 
 	session = (struct session *) ptr;
 
@@ -2268,7 +2627,21 @@
 	//
 	// So we don't need to make sure that sendbufsize will overflow.
 	//
+	// However, we *do* need to make sure its value fits in an int,
+	// because sock_send() can't send more than INT_MAX bytes (it could
+	// do so on 64-bit UN*Xes, but can't do so on Windows, not even
+	// 64-bit Windows, as the send() buffer size argument is an int
+	// in Winsock).
+	//
 	sendbufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + pcap_snapshot(session->fp);
+	if (sendbufsize > INT_MAX)
+	{
+		rpcapd_log(LOGPRIO_ERROR,
+		    "Buffer size for this child thread would be larger than %d",
+		    INT_MAX);
+		sendbuf = NULL;	// we haven't allocated a buffer, so nothing to free
+		goto error;
+	}
 	sendbuf = (char *) malloc (sendbufsize);
 	if (sendbuf == NULL)
 	{
@@ -2278,30 +2651,36 @@
 	}
 
 #ifndef _WIN32
-	// Modify thread params so that it can be killed at any time
-	retval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-	if (retval != 0)
-	{
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    retval, "pthread_setcancelstate");
-		rpcapd_log(LOGPRIO_ERROR,
-		    "Can't set cancel state on data thread: %s", errbuf);
-		goto error;
-	}
-	retval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
-	if (retval != 0)
-	{
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    retval, "pthread_setcanceltype");
-		rpcapd_log(LOGPRIO_ERROR,
-		    "Can't set cancel type on data thread: %s", errbuf);
-		goto error;
-	}
+	//
+	// Set the signal set to include just SIGUSR1, and block that
+	// signal; we only want it unblocked when we're reading
+	// packets - we dn't want any other system calls, such as
+	// ones being used to send to the client or to log messages,
+	// to be interrupted.
+	//
+	sigemptyset(&sigusr1);
+	sigaddset(&sigusr1, SIGUSR1);
+	pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
 #endif
 
 	// Retrieve the packets
-	while ((retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data)) >= 0)	// cast to avoid a compiler warning
+	for (;;)
 	{
+#ifndef _WIN32
+		//
+		// Unblock SIGUSR1 while we might be waiting for packets.
+		//
+		pthread_sigmask(SIG_UNBLOCK, &sigusr1, NULL);
+#endif
+		retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data);	// cast to avoid a compiler warning
+#ifndef _WIN32
+		//
+		// Now block it again.
+		//
+		pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
+#endif
+		if (retval < 0)
+			break;		// error
 		if (retval == 0)	// Read timeout elapsed
 			continue;
 
@@ -2309,7 +2688,7 @@
 
 		// Bufferize the general header
 		if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
-		    &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
 			rpcapd_log(LOGPRIO_ERROR,
@@ -2326,7 +2705,7 @@
 
 		// Bufferize the pkt header
 		if (sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL,
-		    &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
 		    PCAP_ERRBUF_SIZE) == -1)
 		{
 			rpcapd_log(LOGPRIO_ERROR,
@@ -2338,12 +2717,16 @@
 		net_pkt_header->caplen = htonl(pkt_header->caplen);
 		net_pkt_header->len = htonl(pkt_header->len);
 		net_pkt_header->npkt = htonl(++(session->TotCapt));
-		net_pkt_header->timestamp_sec = htonl(pkt_header->ts.tv_sec);
-		net_pkt_header->timestamp_usec = htonl(pkt_header->ts.tv_usec);
+		//
+		// This protocol needs to be updated with a new version
+		// before 2038-01-19 03:14:07 UTC.
+		//
+		net_pkt_header->timestamp_sec = htonl((uint32)pkt_header->ts.tv_sec);
+		net_pkt_header->timestamp_usec = htonl((uint32)pkt_header->ts.tv_usec);
 
 		// Bufferize the pkt data
 		if (sock_bufferize((char *) pkt_data, pkt_header->caplen,
-		    sendbuf, &sendbufidx, sendbufsize, SOCKBUF_BUFFERIZE,
+		    sendbuf, &sendbufidx, (int)sendbufsize, SOCKBUF_BUFFERIZE,
 		    errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
 			rpcapd_log(LOGPRIO_ERROR,
@@ -2355,7 +2738,7 @@
 		// Send the packet
 		// If the client dropped the connection, don't report an
 		// error, just quit.
-		status = sock_send(session->sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
+		status = sock_send(session->sockdata, session->data_ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
 		if (status < 0)
 		{
 			if (status == -1)
@@ -2377,23 +2760,40 @@
 		}
 	}
 
-	if (retval == -1)
+	if (retval < 0 && retval != PCAP_ERROR_BREAK)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
-		rpcap_senderror(session->sockctrl_out, session->protocol_version,
+		//
+		// Failed with an error other than "we were told to break
+		// out of the loop".
+		//
+		// The latter just means that the client told us to stop
+		// capturing, so there's no error to report.
+		//
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
+		rpcap_senderror(session->sockctrl, session->ctrl_ssl, session->protocol_version,
 		    PCAP_ERR_READEX, errbuf, NULL);
-		goto error;
 	}
 
 error:
- 	closesocket(session->sockdata);
-	session->sockdata = 0;
-
+	//
+	// The main thread will clean up the session structure.
+	//
 	free(sendbuf);
 
 	return 0;
 }
 
+#ifndef _WIN32
+//
+// Do-nothing handler for SIGUSR1; the sole purpose of SIGUSR1 is to
+// interrupt the data thread if it's blocked in a system call waiting
+// for packets to arrive.
+//
+static void noop_handler(int sign _U_)
+{
+}
+#endif
+
 /*!
 	\brief It serializes a network address.
 
@@ -2459,6 +2859,7 @@
 */
 void sleep_secs(int secs)
 {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 #ifdef _WIN32
 	Sleep(secs*1000);
 #else
@@ -2470,18 +2871,19 @@
 	while (secs_remaining != 0)
 		secs_remaining = sleep(secs_remaining);
 #endif
+#endif
 }
 
 /*
  * Read the header of a message.
  */
 static int
-rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp)
+rpcapd_recv_msg_header(SOCKET sock, SSL *ssl, struct rpcap_header *headerp)
 {
 	int nread;
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
 
-	nread = sock_recv(sock, (char *) headerp, sizeof(struct rpcap_header),
+	nread = sock_recv(sock, ssl, (char *) headerp, sizeof(struct rpcap_header),
 	    SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
 	if (nread == -1)
 	{
@@ -2508,7 +2910,7 @@
  * error.
  */
 static int
-rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
+rpcapd_recv(SOCKET sock, SSL *ssl, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
 {
 	int nread;
 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
@@ -2516,10 +2918,10 @@
 	if (toread > *plen)
 	{
 		// Tell the client and continue.
-		pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
 		return -2;
 	}
-	nread = sock_recv(sock, buffer, toread,
+	nread = sock_recv(sock, ssl, buffer, toread,
 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
 	if (nread == -1)
 	{
@@ -2537,13 +2939,13 @@
  * error.
  */
 static int
-rpcapd_discard(SOCKET sock, uint32 len)
+rpcapd_discard(SOCKET sock, SSL *ssl, uint32 len)
 {
 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
 
 	if (len != 0)
 	{
-		if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
 			// Network error.
 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
@@ -2552,3 +2954,163 @@
 	}
 	return 0;
 }
+
+//
+// Shut down any packet-capture thread associated with the session,
+// close the SSL handle for the data socket if we have one, close
+// the data socket if we have one, and close the underlying packet
+// capture handle if we have one.
+//
+// We do not, of course, touch the controlling socket that's also
+// copied into the session, as the service loop might still use it.
+//
+static void session_close(struct session *session)
+{
+	if (session->have_thread)
+	{
+		//
+		// Tell the data connection thread main capture loop to
+		// break out of that loop.
+		//
+		// This may be sufficient to wake up a blocked thread,
+		// but it's not guaranteed to be sufficient.
+		//
+		pcap_breakloop(session->fp);
+
+#ifdef _WIN32
+		//
+		// Set the event on which a read would block, so that,
+		// if it's currently blocked waiting for packets to
+		// arrive, it'll wake up, so it can see the "break
+		// out of the loop" indication.  (pcap_breakloop()
+		// might do this, but older versions don't.  Setting
+		// it twice should, at worst, cause an extra wakeup,
+		// which shouldn't be a problem.)
+		//
+		// XXX - what about modules other than NPF?
+		//
+		SetEvent(pcap_getevent(session->fp));
+
+		//
+		// Wait for the thread to exit, so we don't close
+		// sockets out from under it.
+		//
+		// XXX - have a timeout, so we don't wait forever?
+		//
+		WaitForSingleObject(session->thread, INFINITE);
+
+		//
+		// Release the thread handle, as we're done with
+		// it.
+		//
+		CloseHandle(session->thread);
+		session->have_thread = 0;
+		session->thread = INVALID_HANDLE_VALUE;
+#else
+		//
+		// Send a SIGUSR1 signal to the thread, so that, if
+		// it's currently blocked waiting for packets to arrive,
+		// it'll wake up (we've turned off SA_RESTART for
+		// SIGUSR1, so that the system call in which it's blocked
+		// should return EINTR rather than restarting).
+		//
+		pthread_kill(session->thread, SIGUSR1);
+
+		//
+		// Wait for the thread to exit, so we don't close
+		// sockets out from under it.
+		//
+		// XXX - have a timeout, so we don't wait forever?
+		//
+		pthread_join(session->thread, NULL);
+		session->have_thread = 0;
+		memset(&session->thread, 0, sizeof(session->thread));
+#endif
+	}
+
+#ifdef HAVE_OPENSSL
+	if (session->data_ssl)
+	{
+		// Finish using the SSL handle for the socket.
+		// This must be done *before* the socket is closed.
+		ssl_finish(session->data_ssl);
+		session->data_ssl = NULL;
+	}
+#endif
+
+	if (session->sockdata != INVALID_SOCKET)
+	{
+		sock_close(session->sockdata, NULL, 0);
+		session->sockdata = INVALID_SOCKET;
+	}
+
+	if (session->fp)
+	{
+		pcap_close(session->fp);
+		session->fp = NULL;
+	}
+}
+
+//
+// Check whether a capture source string is a URL or not.
+// This includes URLs that refer to a local device; a scheme, followed
+// by ://, followed by *another* scheme and ://, is just silly, and
+// anybody who supplies that will get an error.
+//
+static int
+is_url(const char *source)
+{
+	char *colonp;
+
+	/*
+	 * RFC 3986 says:
+	 *
+	 *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+	 *
+	 *   hier-part   = "//" authority path-abempty
+	 *               / path-absolute
+	 *               / path-rootless
+	 *               / path-empty
+	 *
+	 *   authority   = [ userinfo "@" ] host [ ":" port ]
+	 *
+	 *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
+	 *
+	 * Step 1: look for the ":" at the end of the scheme.
+	 * A colon in the source is *NOT* sufficient to indicate that
+	 * this is a URL, as interface names on some platforms might
+	 * include colons (e.g., I think some Solaris interfaces
+	 * might).
+	 */
+	colonp = strchr(source, ':');
+	if (colonp == NULL)
+	{
+		/*
+		 * The source is the device to open.  It's not a URL.
+		 */
+		return (0);
+	}
+
+	/*
+	 * All schemes must have "//" after them, i.e. we only support
+	 * hier-part   = "//" authority path-abempty, not
+	 * hier-part   = path-absolute
+	 * hier-part   = path-rootless
+	 * hier-part   = path-empty
+	 *
+	 * We need that in order to distinguish between a local device
+	 * name that happens to contain a colon and a URI.
+	 */
+	if (strncmp(colonp + 1, "//", 2) != 0)
+	{
+		/*
+		 * The source is the device to open.  It's not a URL.
+		 */
+		return (0);
+	}
+
+	/*
+	 * It's a URL.
+	 */
+	return (1);
+}
diff --git a/rpcapd/daemon.h b/rpcapd/daemon.h
index bd240b8..dbbdb62 100644
--- a/rpcapd/daemon.h
+++ b/rpcapd/daemon.h
@@ -33,12 +33,19 @@
 #ifndef __DAEMON_H__
 #define __DAEMON_H__
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "sslutils.h"
+
 //
 // Returns 1 if the client closed the control connection explicitly, 0
-// otherwise; used in active mode only.
+// otherwise; the return value is used only by callers that call us
+// for active mode.
 //
-int daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive,
-    int nullAuthAllowed);
+int daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+    int nullAuthAllowed, int uses_ssl);
 
 void sleep_secs(int secs);
 
diff --git a/rpcapd/fileconf.c b/rpcapd/fileconf.c
index ab1e9dd..b79dda1 100644
--- a/rpcapd/fileconf.c
+++ b/rpcapd/fileconf.c
@@ -42,99 +42,450 @@
 #include <signal.h>
 #include <pcap.h>		// for PCAP_ERRBUF_SIZE
 
-#include "sockutils.h"		// for SOCK_DEBUG_MESSAGE
 #include "portability.h"
 #include "rpcapd.h"
 #include "config_params.h"	// configuration file parameters
 #include "fileconf.h"
 #include "rpcap-protocol.h"
+#include "log.h"
 
-static int strrem(char *string, char chr);
+//
+// Parameter names.
+//
+#define PARAM_ACTIVECLIENT	"ActiveClient"
+#define PARAM_PASSIVECLIENT	"PassiveClient"
+#define PARAM_NULLAUTHPERMIT	"NullAuthPermit"
+
+static char *skipws(char *ptr);
+
+/*
+ * Locale-independent version checks for alphabetical and alphanumerical
+ * characters that also can handle being handed a char value that might
+ * be negative.
+ */
+#define FILECONF_ISALPHA(c) \
+	(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#define FILECONF_ISALNUM(c) \
+	(FILECONF_ISALPHA(c) || ((c) >= '0' && (c) <= '9'))
 
 void fileconf_read(void)
 {
 	FILE *fp;
-	char msg[PCAP_ERRBUF_SIZE + 1];
-	int i;
+	unsigned int num_active_clients;
 
 	if ((fp = fopen(loadfile, "r")) != NULL)
 	{
 		char line[MAX_LINE + 1];
-		char *ptr;
+		unsigned int lineno;
 
 		hostlist[0] = 0;
-		i = 0;
+		num_active_clients = 0;
+		lineno = 0;
 
 		while (fgets(line, MAX_LINE, fp) != NULL)
 		{
-			if (line[0] == '\n') continue;	// Blank line
-			if (line[0] == '\r') continue;	// Blank line
-			if (line[0] == '#') continue;	// Comment
+			size_t linelen;
+			char *ptr;
+			char *param;
+			size_t result;
+			size_t toklen;
 
-			ptr = strstr(line, "ActiveClient");
-			if (ptr)
+			lineno++;
+
+			linelen = strlen(line);
+			if (line[linelen - 1] != '\n')
 			{
-				char *address, *port;
-				char *lasts;
+				int c;
 
-				ptr = strchr(ptr, '=') + 1;
-				address = pcap_strtok_r(ptr, RPCAP_HOSTLIST_SEP, &lasts);
+				//
+				// Either the line doesn't fit in
+				// the buffer, or we got an EOF
+				// before the EOL.  Assume it's the
+				// former.
+				//
+				rpcapd_log(LOGPRIO_ERROR,
+				    "%s, line %u is longer than %u characters",
+				    loadfile, lineno, MAX_LINE);
 
-				if ((address != NULL) && (i < MAX_ACTIVE_LIST))
+				//
+				// Eat characters until we get an NL.
+				//
+				while ((c = getc(fp)) != '\n')
 				{
-					port = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
-					strlcpy(activelist[i].address, address, MAX_LINE);
-
-					if (strcmp(port, "DEFAULT") == 0) // the user choose a custom port
-						strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
-					else
-						strlcpy(activelist[i].port, port, MAX_LINE);
-
-					activelist[i].address[MAX_LINE] = 0;
-					activelist[i].port[MAX_LINE] = 0;
+					if (c == EOF)
+						goto done;
 				}
+
+				//
+				// Try the next line.
+				//
+				continue;
+			}
+			ptr = line;
+
+			//
+			// Skip leading white space, if any.
+			//
+			ptr = skipws(ptr);
+			if (ptr == NULL)
+			{
+				// Blank line.
+				continue;
+			}
+
+			//
+			// Is the next character a "#"?  If so, this
+			// line is a comment; skip to the next line.
+			//
+			if (*ptr == '#')
+				continue;
+
+			//
+			// Is the next character alphabetic?  If not,
+			// this isn't a valid parameter name.
+			//
+			if (FILECONF_ISALPHA(*ptr))
+			{
+				rpcapd_log(LOGPRIO_ERROR,
+				    "%s, line %u doesn't have a valid parameter name",
+				    loadfile, lineno);
+				continue;
+			}
+
+			//
+			// Grab the first token, which is made of
+			// alphanumerics, underscores, and hyphens.
+			// That's the name of the parameter being set.
+			//
+			param = ptr;
+			while (FILECONF_ISALNUM(*ptr) || *ptr == '-' || *ptr == '_')
+				ptr++;
+
+			//
+			// Skip over white space, if any.
+			//
+			ptr = skipws(ptr);
+			if (ptr == NULL || *ptr != '=')
+			{
+				//
+				// We hit the end of the line before
+				// finding a non-white space character,
+				// or we found one but it's not an "=".
+				// That means there's no "=", so this
+				// line is invalid.  Complain and skip
+				// this line.
+				//
+				rpcapd_log(LOGPRIO_ERROR,
+				    "%s, line %u has a parameter but no =",
+				    loadfile, lineno);
+				continue;
+			}
+
+			//
+			// We found the '='; set it to '\0', and skip
+			// past it.
+			//
+			*ptr++ = '\0';
+
+			//
+			// Skip past any white space after the "=".
+			//
+			ptr = skipws(ptr);
+			if (ptr == NULL)
+			{
+				//
+				// The value is empty.
+				//
+				rpcapd_log(LOGPRIO_ERROR,
+				    "%s, line %u has a parameter but no value",
+				    loadfile, lineno);
+				continue;
+			}
+
+			//
+			// OK, what parameter is this?
+			//
+			if (strcmp(param, PARAM_ACTIVECLIENT) == 0) {
+				//
+				// Add this to the list of active clients.
+				//
+				char *address, *port;
+
+				//
+				// We can't have more than MAX_ACTIVE_LIST
+				// active clients.
+				//
+				if (num_active_clients >= MAX_ACTIVE_LIST)
+				{
+					//
+					// Too many entries for the active
+					// client list.  Complain and
+					// ignore it.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has an %s parameter, but we already have %u active clients",
+					    loadfile, lineno, PARAM_ACTIVECLIENT,
+					    MAX_ACTIVE_LIST);
+					continue;
+				}
+
+				//
+				// Get the address.
+				// It's terminated by a host list separator
+				// *or* a #; there *shouldn't* be a #, as
+				// that starts a comment, and that would
+				// mean that we have no port.
+				//
+				address = ptr;
+				toklen = strcspn(ptr, RPCAP_HOSTLIST_SEP "#");
+				ptr += toklen;	// skip to the terminator
+				if (toklen == 0)
+				{
+					if (*ptr == ' ' || *ptr == '\t' ||
+					    *ptr == '\r' || *ptr == '\n' ||
+					    *ptr == '#' || *ptr == '\0')
+					{
+						//
+						// The first character it saw
+						// was a whitespace character
+						// or a comment character,
+						// or we ran out of characters.
+						// This means that there's
+						// no value.
+						//
+						rpcapd_log(LOGPRIO_ERROR,
+						    "%s, line %u has a parameter but no value",
+						    loadfile, lineno);
+					}
+					else
+					{
+						//
+						// This means that the first
+						// character it saw was a
+						// separator.  This means that
+						// there's no address in the
+						// value, just a port.
+						//
+						rpcapd_log(LOGPRIO_ERROR,
+						    "%s, line %u has an %s parameter with a value containing no address",
+						    loadfile, lineno, PARAM_ACTIVECLIENT);
+					}
+					continue;
+				}
+
+				//
+				// Null-terminate the address, and skip past
+				// it.
+				//
+				*ptr++ = '\0';
+
+				//
+				// Skip any white space following the
+				// separating character.
+				//
+				ptr = skipws(ptr);
+				if (ptr == NULL)
+				{
+					//
+					// The value is empty, so there's
+					// no port in the value.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has an %s parameter with a value containing no port",
+					    loadfile, lineno, PARAM_ACTIVECLIENT);
+					continue;
+				}
+
+				//
+				// Get the port.
+				// We look for a white space character
+				// or a # as a terminator; the # introduces
+				// a comment that runs to the end of the
+				// line.
+				//
+				port = ptr;
+				toklen = strcspn(ptr, " \t#\r\n");
+				ptr += toklen;
+				if (toklen == 0)
+				{
+					//
+					// The value is empty, so there's
+					// no port in the value.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has an %s parameter with a value containing no port",
+					    loadfile, lineno, PARAM_ACTIVECLIENT);
+					continue;
+				}
+
+				//
+				// Null-terminate the port, and skip past
+				// it.
+				//
+				*ptr++ = '\0';
+				result = pcap_strlcpy(activelist[num_active_clients].address, address, sizeof(activelist[num_active_clients].address));
+				if (result >= sizeof(activelist[num_active_clients].address))
+				{
+					//
+					// It didn't fit.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has an %s parameter with an address with more than %u characters",
+					    loadfile, lineno, PARAM_ACTIVECLIENT,
+					    (unsigned int)(sizeof(activelist[num_active_clients].address) - 1));
+					continue;
+				}
+				if (strcmp(port, "DEFAULT") == 0) // the user choose a custom port
+					result = pcap_strlcpy(activelist[num_active_clients].port, RPCAP_DEFAULT_NETPORT_ACTIVE, sizeof(activelist[num_active_clients].port));
 				else
-					SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
+					result = pcap_strlcpy(activelist[num_active_clients].port, port, sizeof(activelist[num_active_clients].port));
+				if (result >= sizeof(activelist[num_active_clients].address))
+				{
+					//
+					// It didn't fit.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has an %s parameter with an port with more than %u characters",
+					    loadfile, lineno, PARAM_ACTIVECLIENT,
+					    (unsigned int)(sizeof(activelist[num_active_clients].port) - 1));
+					continue;
+				}
 
-				i++;
-				continue;
+				num_active_clients++;
 			}
-
-			ptr = strstr(line, "PassiveClient");
-			if (ptr)
+			else if (strcmp(param, PARAM_PASSIVECLIENT) == 0)
 			{
-				ptr = strchr(ptr, '=') + 1;
-				strlcat(hostlist, ptr, MAX_HOST_LIST);
-				strlcat(hostlist, ",", MAX_HOST_LIST);
-				continue;
+				char *eos;
+				char *host;
+
+				//
+				// Get the host.
+				// We look for a white space character
+				// or a # as a terminator; the # introduces
+				// a comment that runs to the end of the
+				// line.
+				//
+				host = ptr;
+				toklen = strcspn(ptr, " \t#\r\n");
+				if (toklen == 0)
+				{
+					//
+					// The first character it saw
+					// was a whitespace character
+					// or a comment character.
+					// This means that there's
+					// no value.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has a parameter but no value",
+					    loadfile, lineno);
+					continue;
+				}
+				ptr += toklen;
+				*ptr++ = '\0';
+
+				//
+				// Append this to the host list.
+				// Save the curren end-of-string for the
+				// host list, in case the new host doesn't
+				// fit, so that we can discard the partially-
+				// copied host name.
+				//
+				eos = hostlist + strlen(hostlist);
+				if (eos != hostlist)
+				{
+					//
+					// The list is not empty, so prepend
+					// a comma before adding this host.
+					//
+					result = pcap_strlcat(hostlist, ",", sizeof(hostlist));
+					if (result >= sizeof(hostlist))
+					{
+						//
+						// It didn't fit.  Discard
+						// the comma (which wasn't
+						// added, but...), complain,
+						// and ignore this line.
+						//
+						*eos = '\0';
+						rpcapd_log(LOGPRIO_ERROR,
+						    "%s, line %u has a %s parameter with a host name that doesn't fit",
+						    loadfile, lineno, PARAM_PASSIVECLIENT);
+						continue;
+					}
+				}
+				result = pcap_strlcat(hostlist, host, sizeof(hostlist));
+				if (result >= sizeof(hostlist))
+				{
+					//
+					// It didn't fit.  Discard the comma,
+					// complain, and ignore this line.
+					//
+					*eos = '\0';
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has a %s parameter with a host name that doesn't fit",
+					    loadfile, lineno, PARAM_PASSIVECLIENT);
+					continue;
+				}
 			}
-
-			ptr = strstr(line, "NullAuthPermit");
-			if (ptr)
+			else if (strcmp(param, PARAM_NULLAUTHPERMIT) == 0)
 			{
-				ptr = strstr(ptr, "YES");
-				if (ptr)
+				char *setting;
+
+				//
+				// Get the setting.
+				// We look for a white space character
+				// or a # as a terminator; the # introduces
+				// a comment that runs to the end of the
+				// line.
+				//
+				setting = ptr;
+				toklen = strcspn(ptr, " \t#\r\n");
+				ptr += toklen;
+				if (toklen == 0)
+				{
+					//
+					// The first character it saw
+					// was a whitespace character
+					// or a comment character.
+					// This means that there's
+					// no value.
+					//
+					rpcapd_log(LOGPRIO_ERROR,
+					    "%s, line %u has a parameter but no value",
+					    loadfile, lineno);
+					continue;
+				}
+				*ptr++ = '\0';
+
+				//
+				// XXX - should we complain if it's
+				// neither "yes" nor "no"?
+				//
+				if (strcmp(setting, "YES") == 0)
 					nullAuthAllowed = 1;
 				else
 					nullAuthAllowed = 0;
+			}
+			else
+			{
+				rpcapd_log(LOGPRIO_ERROR,
+				    "%s, line %u has an unknown parameter %s",
+				    loadfile, lineno, param);
 				continue;
 			}
 		}
 
+done:
 		// clear the remaining fields of the active list
-		while (i < MAX_ACTIVE_LIST)
+		for (int i = num_active_clients; i < MAX_ACTIVE_LIST; i++)
 		{
 			activelist[i].address[0] = 0;
 			activelist[i].port[0] = 0;
-			i++;
+			num_active_clients++;
 		}
 
-		// Remove all '\n' and '\r' from the strings
-		strrem(hostlist, '\r');
-		strrem(hostlist, '\n');
-
-		pcap_snprintf(msg, PCAP_ERRBUF_SIZE, "New passive host list: %s\n\n", hostlist);
-		SOCK_DEBUG_MESSAGE(msg);
+		rpcapd_log(LOGPRIO_DEBUG, "New passive host list: %s", hostlist);
 		fclose(fp);
 	}
 }
@@ -156,13 +507,12 @@
 		fprintf(fp, "# Hosts which are allowed to connect to this server (passive mode)\n");
 		fprintf(fp, "# Format: PassiveClient = <name or address>\n\n");
 
-		strncpy(temphostlist, hostlist, MAX_HOST_LIST);
-		temphostlist[MAX_HOST_LIST] = 0;
+		pcap_strlcpy(temphostlist, hostlist, sizeof (temphostlist));
 
 		token = pcap_strtok_r(temphostlist, RPCAP_HOSTLIST_SEP, &lasts);
 		while(token != NULL)
 		{
-			fprintf(fp, "PassiveClient = %s\n", token);
+			fprintf(fp, "%s = %s\n", PARAM_PASSIVECLIENT, token);
 			token = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
 		}
 
@@ -175,18 +525,17 @@
 
 		while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
 		{
-			fprintf(fp, "ActiveClient = %s, %s\n", activelist[i].address, activelist[i].port);
+			fprintf(fp, "%s = %s, %s\n", PARAM_ACTIVECLIENT,
+			    activelist[i].address, activelist[i].port);
 			i++;
 		}
 
 		// Save if we want to permit NULL authentication
 		fprintf(fp, "\n\n");
-		fprintf(fp, "# Permit NULL authentication: YES or NOT\n\n");
+		fprintf(fp, "# Permit NULL authentication: YES or NO\n\n");
 
-		if (nullAuthAllowed)
-			fprintf(fp, "NullAuthPermit = YES\n");
-		else
-			fprintf(fp, "NullAuthPermit = NO\n");
+		fprintf(fp, "%s = %s\n", PARAM_NULLAUTHPERMIT,
+		    nullAuthAllowed ? "YES" : "NO");
 
 		fclose(fp);
 		return 0;
@@ -198,19 +547,19 @@
 
 }
 
-static int strrem(char *string, char chr)
+//
+// Skip over white space.
+// If we hit a CR or LF, return NULL, otherwise return a pointer to
+// the first non-white space character.  Replace white space characters
+// other than CR or LF with '\0', so that, if we're skipping white space
+// after a token, the token is null-terminated.
+//
+static char *skipws(char *ptr)
 {
-	char *pos;
-	int num = 0;
-	int len, i;
-
-	while ((pos = strchr(string, chr)) != NULL)
-	{
-		num++;
-		len = strlen(pos);
-		for (i = 0; i < len; i++)
-			pos[i] = pos[i+1];
+	while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') {
+		if (*ptr == '\r' || *ptr == '\n')
+			return NULL;
+		*ptr++ = '\0';
 	}
-
-	return num;
+	return ptr;
 }
diff --git a/rpcapd/log-stderr.c b/rpcapd/log-stderr.c
deleted file mode 100644
index 5af6f2e..0000000
--- a/rpcapd/log-stderr.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include "log.h"
-
-void
-rpcapd_log_init(void)
-{
-}
-
-void
-rpcapd_log(log_priority priority, const char *message, ...)
-{
-	const char *tag;
-	va_list ap;
-
-	switch (priority) {
-
-	case LOGPRIO_INFO:
-		tag = "";
-		break;
-
-	case LOGPRIO_WARNING:
-		tag = "warning: ";
-		break;
-
-	case LOGPRIO_ERROR:
-		tag = "error: ";
-		break;
-
-	default:
-		abort();
-		/* NOTREACHED */
-	}
-
-	fprintf(stderr, "rpcapd: %s", tag);
-	va_start(ap, message);
-	vfprintf(stderr, message, ap);
-	va_end(ap);
-	putc('\n', stderr);
-}
diff --git a/rpcapd/log.c b/rpcapd/log.c
new file mode 100644
index 0000000..f26c145
--- /dev/null
+++ b/rpcapd/log.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <syslog.h>
+#endif
+
+#include "portability.h"
+
+#include "log.h"
+
+static int log_to_systemlog;
+static int log_debug_messages;
+
+static void rpcapd_vlog_stderr(log_priority,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap)
+{
+	const char *tag;
+
+	/*
+	 * Squelch warnings from compilers that *don't* assume that
+	 * priority always has a valid enum value and therefore don't
+	 * assume that we'll always go through one of the case arms.
+	 *
+	 * If we have a default case, compilers that *do* assume that
+	 * will then complain about the default case code being
+	 * unreachable.
+	 *
+	 * Damned if you do, damned if you don't.
+	 */
+	tag = "";
+
+	switch (priority) {
+
+	case LOGPRIO_DEBUG:
+		tag = "DEBUG: ";
+		break;
+
+	case LOGPRIO_INFO:
+		tag = "";
+		break;
+
+	case LOGPRIO_WARNING:
+		tag = "warning: ";
+		break;
+
+	case LOGPRIO_ERROR:
+		tag = "error: ";
+		break;
+	}
+
+	fprintf(stderr, "rpcapd: %s", tag);
+	vfprintf(stderr, message, ap);
+	putc('\n', stderr);
+}
+
+static void rpcapd_vlog_systemlog(log_priority,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+#ifdef _WIN32
+#define MESSAGE_SUBKEY \
+    "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd"
+
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+    va_list ap)
+{
+#if 0
+	static int initialized = 0;
+	HKEY hey_handle;
+	static HANDLE log_handle;
+	WORD eventlog_type;
+	DWORD event_id;
+	char msgbuf[1024];
+	char *strings[1];
+
+	if (!initialized) {
+		/*
+		 * Register our message stuff in the Registry.
+		 *
+		 * First, create the registry key for us.  If the key
+		 * already exists, this succeeds and returns a handle
+		 * for it.
+		 */
+		if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY,
+		    &key_handle) != ERROR_SUCCESS) {
+			/*
+			 * Failed - give up and just log this message,
+			 * and all subsequent messages, to the
+			 * standard error.
+			 */
+			log_to_systemlog = 0;
+			initialized = 1;
+			rpcapd_vlog_stderr(priority, message, ap);
+			return;
+		}
+		log_handle = RegisterEventSource(NULL, "rpcapd");
+		initialized = 1;
+	}
+
+	switch (priority) {
+
+	case LOGPRIO_DEBUG:
+		//
+		// XXX - what *should* we do about debug messages?
+		//
+		eventlog_type = EVENTLOG_INFORMATION_TYPE;
+		event_id = RPCAPD_INFO_ID;
+		break;
+
+	case LOGPRIO_INFO:
+		eventlog_type = EVENTLOG_INFORMATION_TYPE;
+		event_id = RPCAPD_INFO_ID;
+		break;
+
+	case LOGPRIO_WARNING:
+		eventlog_type = EVENTLOG_WARNING_TYPE;
+		event_id = RPCAPD_WARNING_ID;
+		break;
+
+	case LOGPRIO_ERROR:
+		eventlog_type = EVENTLOG_ERROR_TYPE;
+		event_id = RPCAPD_ERROR_ID;
+		break;
+
+	default:
+		/* Don't do this. */
+		return;
+	}
+
+	vsprintf(msgbuf, message, ap);
+
+	strings[0] = msgbuf;
+	/*
+	 * If this fails, how are we going to report it?
+	 */
+	(void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0,
+	    strings, NULL);
+#else
+	rpcapd_vlog_stderr(priority, message, ap);
+#endif
+}
+#else
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+    va_list ap)
+{
+	static int initialized = 0;
+	int syslog_priority;
+
+	if (!initialized) {
+		//
+		// Open the log.
+		//
+		openlog("rpcapd", LOG_PID, LOG_DAEMON);
+		initialized = 1;
+	}
+
+	switch (priority) {
+
+	case LOGPRIO_DEBUG:
+		syslog_priority = LOG_DEBUG;
+		break;
+
+	case LOGPRIO_INFO:
+		syslog_priority = LOG_INFO;
+		break;
+
+	case LOGPRIO_WARNING:
+		syslog_priority = LOG_WARNING;
+		break;
+
+	case LOGPRIO_ERROR:
+		syslog_priority = LOG_ERR;
+		break;
+
+	default:
+		/* Don't do this. */
+		return;
+	}
+
+#ifdef HAVE_VSYSLOG
+	vsyslog(syslog_priority, message, ap);
+#else
+	/*
+	 * Thanks, IBM, for not providing vsyslog() in AIX!
+	 *
+	 * They also warn that the syslog functions shouldn't
+	 * be used in multithreaded programs, but the only thing
+	 * obvious that seems to make the syslog_r functions
+	 * better is that they have an additional argument
+	 * that points to the information that's static to
+	 * the syslog code in non-thread-safe versions.  Most
+	 * of that data is set by openlog(); since we already
+	 * do an openlog before doing logging, and don't
+	 * change that data afterwards, I suspect that, in
+	 * practice, the regular syslog routines are OK for
+	 * us (especially given that we'd end up having one
+	 * static struct syslog_data anyway, which means we'd
+	 * just be like the non-thread-safe version).
+	 */
+	char logbuf[1024+1];
+
+	vsnprintf(logbuf, sizeof logbuf, message, ap);
+	syslog(syslog_priority, "%s", logbuf);
+#endif
+}
+#endif
+
+void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg)
+{
+	log_debug_messages = log_debug_messages_arg;
+	log_to_systemlog = log_to_systemlog_arg;
+}
+
+void rpcapd_log(log_priority priority, const char *message, ...)
+{
+	va_list ap;
+
+	if (priority != LOGPRIO_DEBUG || log_debug_messages) {
+		va_start(ap, message);
+		if (log_to_systemlog)
+		{
+			rpcapd_vlog_systemlog(priority, message, ap);
+		}
+		else
+		{
+			rpcapd_vlog_stderr(priority, message, ap);
+		}
+		va_end(ap);
+	}
+}
diff --git a/rpcapd/log.h b/rpcapd/log.h
index b3806e1..28a6cee 100644
--- a/rpcapd/log.h
+++ b/rpcapd/log.h
@@ -1,8 +1,30 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #include "pcap/funcattrs.h"
 
-extern void rpcapd_log_init(void);
+extern void rpcapd_log_set(int, int);
 
 typedef enum {
+	LOGPRIO_DEBUG,
 	LOGPRIO_INFO,
 	LOGPRIO_WARNING,
 	LOGPRIO_ERROR
diff --git a/rpcapd/org.tcpdump.rpcapd.plist b/rpcapd/org.tcpdump.rpcapd.plist
index db3223a..b0e2439 100644
--- a/rpcapd/org.tcpdump.rpcapd.plist
+++ b/rpcapd/org.tcpdump.rpcapd.plist
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
 	<key>Disabled</key>
diff --git a/rpcapd/rpcapd-config.manfile.in b/rpcapd/rpcapd-config.manfile.in
new file mode 100644
index 0000000..267b48e
--- /dev/null
+++ b/rpcapd/rpcapd-config.manfile.in
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH RPCAPD-CONFIG @MAN_FILE_FORMATS@ "6 January 2019"
+.SH NAME
+rpcapd-config \- rpcapd configuration file format
+.SH DESCRIPTION
+An
+.B rpcapd
+configuration file allows parameters to be set for
+.BR rpcapd (@MAN_ADMIN_COMMANDS@).
+.LP
+A # introduces a comment that runs to the end of the line.  Blank lines,
+and lines with only a comment, are ignored.  Leading and trailing white
+space on a line are also ignored.
+.LP
+Lines that set a parameter are of the form
+.IP
+\fIparameter\fB=\fIvalue\fR
+.LP
+Whitespace preceding or following the = is ignored.
+.LP
+The
+.IR parameter s
+are:
+.TP
+.B ActiveClient
+.I value
+is a host name or IP address, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default active mode port for rpcapd, port 2003.
+Each
+.B ActiveClient
+line adds the host and port to the list of clients to which the server
+should connect in active mode.
+.TP
+.B PassiveClient
+.I value
+is a host name or IP address, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default passive mode port for rpcapd, port 2002.
+Each
+.B PassiveClient
+line adds the host and port to the list of clients addresses and ports
+that are allowed to connect to the server in passive mode.
+.TP
+.B NullAuthPermit
+.I value
+is either
+.B YES
+or
+.BR NO .
+.B YES
+means that null authentication is permitted;
+.B No
+means that it is not permitted.
+.SH SEE ALSO
+.BR rpcapd (@MAN_ADMIN_COMMANDS@)
diff --git a/rpcapd/rpcapd.c b/rpcapd/rpcapd.c
index e8b3b1d..b91a401 100644
--- a/rpcapd/rpcapd.c
+++ b/rpcapd/rpcapd.c
@@ -39,6 +39,7 @@
 #include <errno.h>		// for the errno variable
 #include <string.h>		// for strtok, etc
 #include <stdlib.h>		// for malloc(), free(), ...
+#include <stdio.h>		// for fprintf(), stderr, FILE etc
 #include <pcap.h>		// for PCAP_ERRBUF_SIZE
 #include <signal.h>		// for signal()
 
@@ -53,6 +54,10 @@
 #include "daemon.h"		// the true main() method of this daemon
 #include "log.h"
 
+#ifdef HAVE_OPENSSL
+#include "sslutils.h"
+#endif
+
 #ifdef _WIN32
   #include <process.h>		// for thread stuff
   #include "win32-svc.h"	// for Win32 service stuff
@@ -86,6 +91,7 @@
 #endif
 static volatile sig_atomic_t shutdown_server;	//!< '1' if the server is to shut down
 static volatile sig_atomic_t reread_config;	//!< '1' if the server is to re-read its configuration
+static int uses_ssl; //!< '1' to use TLS over the data socket
 
 extern char *optarg;	// for getopt()
 
@@ -112,7 +118,7 @@
 /*!
 	\brief Prints the usage screen if it is launched in console mode.
 */
-static void printusage(void)
+static void printusage(FILE * f)
 {
 	const char *usagetext =
 	"USAGE:"
@@ -121,7 +127,7 @@
 #ifndef _WIN32
 	"[-i] "
 #endif
-	"[-s <config_file>] [-f <config_file>]\n\n"
+        "[-D] [-s <config_file>] [-f <config_file>]\n\n"
 	"  -b <address>    the address to bind to (either numeric or literal).\n"
 	"                  Default: binds to all local IPv4 and IPv6 addresses\n\n"
 	"  -p <port>       the port to bind to.\n"
@@ -144,14 +150,24 @@
 #ifndef _WIN32
 	"  -i              run in inetd mode (UNIX only)\n\n"
 #endif
+	"  -D              log debugging messages\n\n"
+#ifdef HAVE_OPENSSL
+	"  -S              encrypt all communication with SSL (implements rpcaps://)\n"
+	"  -C              enable compression\n"
+	"  -K <pem_file>   uses the SSL private key in this file (default: key.pem)\n"
+	"  -X <pem_file>   uses the certificate from this file (default: cert.pem)\n"
+#endif
 	"  -s <config_file> save the current configuration to file\n\n"
 	"  -f <config_file> load the current configuration from file; all switches\n"
 	"                  specified from the command line are ignored\n\n"
 	"  -h              print this help screen\n\n";
 
-	(void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
-	"Compiled with %s\n\n", pcap_lib_version());
-	printf("%s", usagetext);
+	(void)fprintf(f, "RPCAPD, a remote packet capture daemon.\n"
+	"Compiled with %s\n", pcap_lib_version());
+#if defined(HAVE_OPENSSL) && defined(SSLEAY_VERSION)
+	(void)fprintf(f, "Compiled with %s\n", SSLeay_version(SSLEAY_VERSION));
+#endif
+	(void)fprintf(f, "\n%s", usagetext);
 }
 
 
@@ -160,15 +176,20 @@
 int main(int argc, char *argv[])
 {
 	char savefile[MAX_LINE + 1];		// name of the file on which we have to save the configuration
+	int log_to_systemlog = 0;		// Non-zero if we should log to the "system log" rather than the standard error
 	int isdaemon = 0;			// Non-zero if the user wants to run this program as a daemon
 #ifndef _WIN32
 	int isrunbyinetd = 0;			// Non-zero if this is being run by inetd or something inetd-like
 #endif
+	int log_debug_messages = 0;		// Non-zero if the user wants debug messages logged
 	int retval;				// keeps the returning value from several functions
 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
 #ifndef _WIN32
 	struct sigaction action;
 #endif
+#ifdef HAVE_OPENSSL
+	int enable_compression = 0;
+#endif
 
 	savefile[0] = 0;
 	loadfile[0] = 0;
@@ -177,14 +198,8 @@
 	// Initialize errbuf
 	memset(errbuf, 0, sizeof(errbuf));
 
-	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
-	{
-		SOCK_DEBUG_MESSAGE(errbuf);
-		exit(-1);
-	}
-
-	strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
-	strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
+	pcap_strlcpy(address, RPCAP_DEFAULT_NETADDR, sizeof (address));
+	pcap_strlcpy(port, RPCAP_DEFAULT_NETPORT, sizeof (port));
 
 	// Prepare to open a new server socket
 	memset(&mainhints, 0, sizeof(struct addrinfo));
@@ -194,28 +209,44 @@
 	mainhints.ai_socktype = SOCK_STREAM;
 
 	// Getting the proper command line options
-	while ((retval = getopt(argc, argv, "b:dhip:4l:na:s:f:v")) != -1)
+#	ifdef HAVE_OPENSSL
+#		define SSL_CLOPTS  "SK:X:C"
+#	else
+#		define SSL_CLOPTS ""
+#	endif
+
+#	define CLOPTS "b:dDhip:4l:na:s:f:v" SSL_CLOPTS
+
+	while ((retval = getopt(argc, argv, CLOPTS)) != -1)
 	{
 		switch (retval)
 		{
+			case 'D':
+				log_debug_messages = 1;
+				rpcapd_log_set(log_to_systemlog, log_debug_messages);
+				break;
 			case 'b':
-				strncpy(address, optarg, MAX_LINE);
+				pcap_strlcpy(address, optarg, sizeof (address));
 				break;
 			case 'p':
-				strncpy(port, optarg, MAX_LINE);
+				pcap_strlcpy(port, optarg, sizeof (port));
 				break;
 			case '4':
 				mainhints.ai_family = PF_INET;		// IPv4 server only
 				break;
 			case 'd':
 				isdaemon = 1;
+				log_to_systemlog = 1;
+				rpcapd_log_set(log_to_systemlog, log_debug_messages);
 				break;
 			case 'i':
 #ifdef _WIN32
-				printusage();
+				printusage(stderr);
 				exit(1);
 #else
 				isrunbyinetd = 1;
+				log_to_systemlog = 1;
+				rpcapd_log_set(log_to_systemlog, log_debug_messages);
 #endif
 				break;
 			case 'n':
@@ -226,7 +257,7 @@
 				break;
 			case 'l':
 			{
-				strncpy(hostlist, optarg, sizeof(hostlist));
+				pcap_strlcpy(hostlist, optarg, sizeof(hostlist));
 				break;
 			}
 			case 'a':
@@ -241,12 +272,12 @@
 				{
 					tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
 
-					strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
+					pcap_strlcpy(activelist[i].address, tmpaddress, sizeof (activelist[i].address));
 
 					if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
-						strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+						pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, sizeof (activelist[i].port));
 					else
-						strlcpy(activelist[i].port, tmpport, MAX_LINE);
+						pcap_strlcpy(activelist[i].port, tmpport, sizeof (activelist[i].port));
 
 					tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
 
@@ -254,44 +285,74 @@
 				}
 
 				if (i > MAX_ACTIVE_LIST)
-					SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
+					rpcapd_log(LOGPRIO_ERROR, "Only MAX_ACTIVE_LIST active connections are currently supported.");
 
 				// I don't initialize the remaining part of the structure, since
 				// it is already zeroed (it is a global var)
 				break;
 			}
 			case 'f':
-				strlcpy(loadfile, optarg, MAX_LINE);
+				pcap_strlcpy(loadfile, optarg, sizeof (loadfile));
 				break;
 			case 's':
-				strlcpy(savefile, optarg, MAX_LINE);
+				pcap_strlcpy(savefile, optarg, sizeof (savefile));
 				break;
+#ifdef HAVE_OPENSSL
+			case 'S':
+				uses_ssl = 1;
+				break;
+			case 'C':
+				enable_compression = 1;
+				break;
+			case 'K':
+				ssl_set_keyfile(optarg);
+				break;
+			case 'X':
+				ssl_set_certfile(optarg);
+				break;
+#endif
 			case 'h':
-				printusage();
+				printusage(stdout);
 				exit(0);
-				break;
+				/*NOTREACHED*/
 			default:
 				exit(1);
-				break;
+				/*NOTREACHED*/
 		}
 	}
 
 #ifndef _WIN32
 	if (isdaemon && isrunbyinetd)
 	{
-		fprintf(stderr, "rpcapd: -d and -i can't be used together\n");
+		rpcapd_log(LOGPRIO_ERROR, "rpcapd: -d and -i can't be used together");
 		exit(1);
 	}
 #endif
 
+	//
+	// We want UTF-8 error messages.
+	//
+	if (pcap_init(PCAP_CHAR_ENC_UTF_8, errbuf) == -1)
+	{
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+		exit(-1);
+	}
+	pcap_fmt_set_encoding(PCAP_CHAR_ENC_UTF_8);
+
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+	{
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+		exit(-1);
+	}
+
 	if (savefile[0] && fileconf_save(savefile))
-		SOCK_DEBUG_MESSAGE("Error when saving the configuration to file");
+		rpcapd_log(LOGPRIO_DEBUG, "Error when saving the configuration to file");
 
 	// If the file does not exist, it keeps the settings provided by the command line
 	if (loadfile[0])
 		fileconf_read();
 
-#ifdef WIN32
+#ifdef _WIN32
 	//
 	// Create a handle to signal the main loop to tell it to do
 	// something.
@@ -299,9 +360,9 @@
 	state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 	if (state_change_event == NULL)
 	{
-		sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-		rpcapd_log(LOGPRIO_ERROR, "Can't create state change event: %s",
-		    errbuf);
+		sock_geterror("Can't create state change event", errbuf,
+		    PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 		exit(2);
 	}
 
@@ -310,9 +371,9 @@
 	//
 	if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
 	{
-		sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-		rpcapd_log(LOGPRIO_ERROR, "Can't set control handler: %s",
-		    errbuf);
+		sock_geterror("Can't set control handler", errbuf,
+		    PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 		exit(2);
 	}
 #else
@@ -331,6 +392,17 @@
 	signal(SIGPIPE, SIG_IGN);
 #endif
 
+# ifdef HAVE_OPENSSL
+	if (uses_ssl) {
+		if (ssl_init_once(1, enable_compression, errbuf, PCAP_ERRBUF_SIZE) < 0)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "Can't initialize SSL: %s",
+			    errbuf);
+			exit(2);
+		}
+	}
+# endif
+
 #ifndef _WIN32
 	if (isrunbyinetd)
 	{
@@ -339,36 +411,30 @@
 		// by inetd or something that can run network daemons
 		// as if it were inetd (xinetd, launchd, systemd, etc.).
 		//
-		// Our standard input is the input side of a connection,
-		// and our standard output is the output side of a
-		// connection.
+		// We assume that the program that launched us just
+		// duplicated a single socket for the connection
+		// to our standard input, output, and error, so we
+		// can just use the standard input as our control
+		// socket.
 		//
-		int sockctrl_in, sockctrl_out;
+		int sockctrl;
 		int devnull_fd;
 
 		//
-		// Duplicate the standard input and output, making them
-		// the input and output side of the control connection.
+		// Duplicate the standard input as the control socket.
 		//
-		sockctrl_in = dup(0);
-		if (sockctrl_in == -1)
+		sockctrl = dup(0);
+		if (sockctrl == -1)
 		{
-			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-			rpcapd_log(LOGPRIO_ERROR, "Can't dup standard input: %s",
-			    errbuf);
-			exit(2);
-		}
-		sockctrl_out = dup(1);
-		if (sockctrl_out == -1)
-		{
-			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-			rpcapd_log(LOGPRIO_ERROR, "Can't dup standard output: %s",
-			    errbuf);
+			sock_geterror("Can't dup standard input", errbuf,
+			    PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 			exit(2);
 		}
 
 		//
-		// Try to set the standard input and output to /dev/null.
+		// Try to set the standard input, output, and error
+		// to /dev/null.
 		//
 		devnull_fd = open("/dev/null", O_RDWR);
 		if (devnull_fd != -1)
@@ -378,6 +444,7 @@
 			//
 			(void)dup2(devnull_fd, 0);
 			(void)dup2(devnull_fd, 1);
+			(void)dup2(devnull_fd, 2);
 			close(devnull_fd);
 		}
 
@@ -386,8 +453,14 @@
 		// This is passive mode, so we don't care whether we were
 		// told by the client to close.
 		//
-		(void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0,
-		    nullAuthAllowed);
+		char *hostlist_copy = strdup(hostlist);
+		if (hostlist_copy == NULL)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+			exit(0);
+		}
+		(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+		    nullAuthAllowed, uses_ssl);
 
 		//
 		// Nothing more to do.
@@ -442,8 +515,8 @@
 		//
 		// If this call succeeds, it is blocking on Win32
 		//
-		if (svc_start() != 1)
-			SOCK_DEBUG_MESSAGE("Unable to start the service");
+		if (!svc_start())
+			rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service");
 
 		// When the previous call returns, the entire application has to be stopped.
 		exit(0);
@@ -504,7 +577,7 @@
 		    (void *)&activelist[i], 0, NULL);
 		if (threadId == 0)
 		{
-			SOCK_DEBUG_MESSAGE("Error creating the active child threads");
+			rpcapd_log(LOGPRIO_DEBUG, "Error creating the active child threads");
 			continue;
 		}
 		CloseHandle(threadId);
@@ -539,7 +612,7 @@
 		//
 		if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
 		{
-			SOCK_DEBUG_MESSAGE(errbuf);
+			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
 			return;
 		}
 
@@ -618,7 +691,7 @@
 	//
 	// We're done; exit.
 	//
-	SOCK_DEBUG_MESSAGE(PROGRAM_NAME " is closing.\n");
+	rpcapd_log(LOGPRIO_DEBUG, PROGRAM_NAME " is closing.\n");
 
 #ifndef _WIN32
 	//
@@ -662,8 +735,9 @@
 
 	if (!SetEvent(state_change_event))
 	{
-		sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-		rpcapd_log(LOGPRIO_ERROR, "SetEvent on shutdown event failed: %s", errbuf);
+		sock_geterror("SetEvent on shutdown event failed", errbuf,
+		    PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 	}
 }
 
@@ -762,7 +836,7 @@
 	// For reference, Stevens, pg 128
 
 	while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
-		SOCK_DEBUG_MESSAGE("Child terminated");
+		rpcapd_log(LOGPRIO_DEBUG, "Child terminated");
 
 	return;
 }
@@ -829,14 +903,16 @@
 		event = WSACreateEvent();
 		if (event == WSA_INVALID_EVENT)
 		{
-			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-			rpcapd_log(LOGPRIO_ERROR, "Can't create socket event: %s", errbuf);
+			sock_geterror("Can't create socket event", errbuf,
+			    PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 			exit(2);
 		}
 		if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
 		{
-			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-			rpcapd_log(LOGPRIO_ERROR, "Can't setup socket event: %s", errbuf);
+			sock_geterror("Can't setup socket event", errbuf,
+			    PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 			exit(2);
 		}
 		events[i] = event;
@@ -853,8 +929,9 @@
 		    WSA_INFINITE, FALSE);
 		if (ret == WSA_WAIT_FAILED)
 		{
-			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-			rpcapd_log(LOGPRIO_ERROR, "WSAWaitForMultipleEvents failed: %s", errbuf);
+			sock_geterror("WSAWaitForMultipleEvents failed", errbuf,
+			    PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 			exit(2);
 		}
 
@@ -892,8 +969,9 @@
 			if (WSAEnumNetworkEvents(sock_info->sock,
 			    events[i], &network_events) == SOCKET_ERROR)
 			{
-				sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
-				rpcapd_log(LOGPRIO_ERROR, "WSAEnumNetworkEvents failed: %s", errbuf);
+				sock_geterror("WSAEnumNetworkEvents failed",
+				    errbuf, PCAP_ERRBUF_SIZE);
+				rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 				exit(2);
 			}
 			if (network_events.lNetworkEvents & FD_ACCEPT)
@@ -901,16 +979,16 @@
 				//
 				// Did an error occur?
 				//
-			 	if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
-			 	{
+				if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
+				{
 					//
 					// Yes - report it and keep going.
 					//
-					sock_fmterror(NULL,
+					sock_fmterror("Socket error",
 					    network_events.iErrorCode[FD_ACCEPT_BIT],
 					    errbuf,
 					    PCAP_ERRBUF_SIZE);
-					rpcapd_log(LOGPRIO_ERROR, "Socket error: %s", errbuf);
+					rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 					continue;
 				}
 
@@ -1033,6 +1111,20 @@
 	sock_cleanup();
 }
 
+#ifdef _WIN32
+//
+// A structure to hold the parameters to the daemon service loop
+// thread on Windows.
+//
+// (On UN*X, there is no need for this explicit copy since the
+// fork "inherits" the parent stack.)
+//
+struct params_copy {
+	SOCKET sockctrl;
+	char *hostlist;
+};
+#endif
+
 //
 // Accept a connection and start a worker thread, on Windows, or a
 // worker process, on UN*X, to handle the connection.
@@ -1048,7 +1140,7 @@
 #ifdef _WIN32
 	HANDLE threadId;			// handle for the subthread
 	u_long off = 0;
-	SOCKET *sockctrl_temp;
+	struct params_copy *params_copy = NULL;
 #else
 	pid_t pid;
 #endif
@@ -1069,7 +1161,7 @@
 			break;
 		}
 
-		// The accept() call can return this error when a signal is catched
+		// The accept() call can return this error when a signal is caught
 		// In this case, we have simply to ignore this error code
 		// Stevens, pg 124
 #ifdef _WIN32
@@ -1081,23 +1173,12 @@
 
 		// Don't check for errors here, since the error can be due to the fact that the thread
 		// has been killed
-		sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
+		sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
 		rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
 		    errbuf);
 		return;
 	}
 
-	//
-	// We have a connection.
-	// Check whether the connecting host is among the ones allowed.
-	//
-	if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
-	{
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
-		sock_close(sockctrl, NULL, 0);
-		return;
-	}
-
 #ifdef _WIN32
 	//
 	// Put the socket back into blocking mode; doing WSAEventSelect()
@@ -1108,56 +1189,75 @@
 	// First, we have to un-WSAEventSelect() this socket, and then
 	// we can turn non-blocking mode off.
 	//
+	// If this fails, we aren't guaranteed that, for example, any
+	// of the error message will be sent - if it can't be put in
+	// the socket queue, the send will just fail.
+	//
+	// So we just log the message and close the connection.
+	//
 	if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
 	{
-		sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+		sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 		sock_close(sockctrl, NULL, 0);
 		return;
 	}
 	if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
 	{
-		sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+		sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
 		sock_close(sockctrl, NULL, 0);
 		return;
 	}
 
 	//
-	// Allocate a location to hold the value of sockctrl.
+	// Make a copy of the host list to pass to the new thread, so that
+	// if we update it in the main thread, it won't catch us in the
+	// middle of updating it.
+	//
+	// daemon_serviceloop() will free it once it's done with it.
+	//
+	char *hostlist_copy = strdup(hostlist);
+	if (hostlist_copy == NULL)
+	{
+		rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+		sock_close(sockctrl, NULL, 0);
+		return;
+	}
+
+	//
+	// Allocate a location to hold the values of sockctrl.
 	// It will be freed in the newly-created thread once it's
 	// finished with it.
-	// I guess we *could* just cast sockctrl to a void *, but that's
-	// a bit ugly.
 	//
-	sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET));
-	if (sockctrl_temp == NULL)
+	params_copy = malloc(sizeof(*params_copy));
+	if (params_copy == NULL)
 	{
-		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "malloc() failed");
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		rpcapd_log(LOGPRIO_ERROR, "Out of memory allocating the parameter copy structure");
+		free(hostlist_copy);
 		sock_close(sockctrl, NULL, 0);
 		return;
 	}
-	*sockctrl_temp = sockctrl;
+	params_copy->sockctrl = sockctrl;
+	params_copy->hostlist = hostlist_copy;
 
 	threadId = (HANDLE)_beginthreadex(NULL, 0,
-	    main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL);
+	    main_passive_serviceloop_thread, (void *) params_copy, 0, NULL);
 	if (threadId == 0)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread");
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		rpcapd_log(LOGPRIO_ERROR, "Error creating the child thread");
+		free(params_copy);
+		free(hostlist_copy);
 		sock_close(sockctrl, NULL, 0);
-		free(sockctrl_temp);
 		return;
 	}
 	CloseHandle(threadId);
-#else
+#else /* _WIN32 */
 	pid = fork();
 	if (pid == -1)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child process");
-		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		rpcapd_log(LOGPRIO_ERROR, "Error creating the child process: %s",
+		    strerror(errno));
 		sock_close(sockctrl, NULL, 0);
 		return;
 	}
@@ -1190,10 +1290,14 @@
 		// This is passive mode, so we don't care whether we were
 		// told by the client to close.
 		//
-		(void)daemon_serviceloop(sockctrl, sockctrl, 0,
-		    nullAuthAllowed);
-
-		close(sockctrl);
+		char *hostlist_copy = strdup(hostlist);
+		if (hostlist_copy == NULL)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+			exit(0);
+		}
+		(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+		    nullAuthAllowed, uses_ssl);
 
 		exit(0);
 	}
@@ -1201,7 +1305,7 @@
 	// I am the parent
 	// Close the socket for this session (must be open only in the child)
 	closesocket(sockctrl);
-#endif
+#endif /* _WIN32 */
 }
 
 /*!
@@ -1235,10 +1339,9 @@
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_family = activepars->ai_family;
 
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
-			activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
-			(hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
-	SOCK_DEBUG_MESSAGE(errbuf);
+	rpcapd_log(LOGPRIO_DEBUG, "Connecting to host %s, port %s, using protocol %s",
+	    activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
+	    (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
 
 	// Initialize errbuf
 	memset(errbuf, 0, sizeof(errbuf));
@@ -1246,7 +1349,7 @@
 	// Do the work
 	if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
 	{
-		SOCK_DEBUG_MESSAGE(errbuf);
+		rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
 		return 0;
 	}
 
@@ -1256,25 +1359,36 @@
 
 		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
 		{
-			SOCK_DEBUG_MESSAGE(errbuf);
+			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
 
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
 					activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
 					(hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
 
-			SOCK_DEBUG_MESSAGE(errbuf);
+			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
 
 			sleep_secs(RPCAP_ACTIVE_WAIT);
 
 			continue;
 		}
 
-		activeclose = daemon_serviceloop(sockctrl, sockctrl, 1,
-		    nullAuthAllowed);
+		char *hostlist_copy = strdup(hostlist);
+		if (hostlist_copy == NULL)
+		{
+			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+			activeclose = 0;
+			sock_close(sockctrl, NULL, 0);
+		}
+		else
+		{
+			//
+			// daemon_serviceloop() will free the copy.
+			//
+			activeclose = daemon_serviceloop(sockctrl, 1,
+			    hostlist_copy, nullAuthAllowed, uses_ssl);
+		}
 
-		sock_close(sockctrl, NULL, 0);
-
-		// If the connection is closed by the user explicitely, don't try to connect to it again
+		// If the connection is closed by the user explicitly, don't try to connect to it again
 		// just exit the program
 		if (activeclose == 1)
 			break;
@@ -1290,9 +1404,7 @@
 //
 unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
 {
-	SOCKET sockctrl;
-
-	sockctrl = *((SOCKET *)ptr);
+	struct params_copy params = *(struct params_copy *)ptr;
 	free(ptr);
 
 	//
@@ -1300,9 +1412,8 @@
 	// This is passive mode, so we don't care whether we were
 	// told by the client to close.
 	//
-	(void)daemon_serviceloop(sockctrl, sockctrl, 0, nullAuthAllowed);
-
-	sock_close(sockctrl, NULL, 0);
+	(void)daemon_serviceloop(params.sockctrl, 0, params.hostlist,
+	    nullAuthAllowed, uses_ssl);
 
 	return 0;
 }
diff --git a/rpcapd/rpcapd.inetd.conf b/rpcapd/rpcapd.inetd.conf
index e4fad5e..86823f0 100644
--- a/rpcapd/rpcapd.inetd.conf
+++ b/rpcapd/rpcapd.inetd.conf
@@ -1,2 +1 @@
 2002 stream tcp nowait root /usr/local/sbin/rpcapd rpcapd -i
-
diff --git a/rpcapd/rpcapd.manadmin.in b/rpcapd/rpcapd.manadmin.in
index 92f676c..ea6046e 100644
--- a/rpcapd/rpcapd.manadmin.in
+++ b/rpcapd/rpcapd.manadmin.in
@@ -30,7 +30,7 @@
 .\"  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 .\"  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH RPCAPD @MAN_ADMIN_COMMANDS@ "April 20, 2018"
+.TH RPCAPD @MAN_ADMIN_COMMANDS@ "13 January 2019"
 .SH NAME
 rpcapd \- capture daemon to be controlled by a remote libpcap application
 .SH SYNOPSIS
@@ -61,16 +61,33 @@
 .B \-d
 ] [
 .B \-i
-] [
-.B \-s
-.I config_file
 ]
 .br
 .ti +8
 [
+.B \-D
+] [
+.B \-s
+.I config_file
+]
+[
 .B \-f
 .I config_file
 ]
+[
+.B \-S
+]
+.br
+.ti +8
+[
+.B \-K
+.I ssl_keyfile
+] [
+.B \-X
+.I ssl_certfile
+] [
+.B \-C
+]
 .br
 .ad
 .SH DESCRIPTION
@@ -82,7 +99,9 @@
 .LP
 In passive mode, the client (e.g., a network sniffer) connects to
 .BR rpcapd .
-It then sends hem the appropriate commands to start the capture.
+The client then sends the appropriate commands to
+.B rpcapd
+to start the capture.
 .LP
 In active mode,
 .B rpcapd
@@ -101,26 +120,34 @@
 the same way in both active and passive mode.
 .SH Configuration file
 .LP
-The user can create a configuration file in the same folder of the
+The user can create a configuration file in the same directory as the
 executable, and put the configuration commands in there. In order for
-rpcapd to execute the commands, you have to restart it on Win32, i.e.
-the initialization file is parsed only at the beginning). The UNIX
-version of rpcapd will reread the configuration file when receiving a
-HUP signel. In that case, all the existing connections remain in place,
+.B rpcapd
+to execute the commands, it needs to be restarted on Win32, i.e.
+the configuration file is parsed only at the beginning. The UNIX
+version of
+.B rpcapd
+will reread the configuration file upon receiving a
+HUP signal. In that case, all the existing connections remain in place,
 while the new connections will be created according to the new parameters.
 .LP
 In case a user does not want to create the configuration file manually,
-they can launch rpcapd with the requested parameters plus "-s filename".
+they can launch
+.B rpcapd
+with the desired flags plus
+.BR "-s filename" .
 Rpcapd will parse all the parameters and save them into the specified
 configuration file.
 .SH Installing rpcapd on Win32
 .LP
 The remote daemon is installed automatically when installing WinPcap.
-The installation process places the rpcapd file into the WinPcap folder.
+The installation process places the
+.B rpcapd
+executable file into the WinPcap folder.
 This file can be executed either from the command line, or as a service.
 For instance, the installation process updates the list of available
 services list and it creates a new item (Remote Packet Capture Protocol
-v.0 (experimental) ).  To avoid security problems, the service is
+v.0 (experimental)).  To avoid security problems, the service is
 inactive and it has to be started manually (control panel -
 administrative tools - services - start).
 .LP
@@ -132,7 +159,9 @@
 flag.
 .SH Starting rpcapd on Win32
 .LP
-The rpcapd executable can be launched directly, i.e.  it can run in the
+The
+.B rpcapd
+executable can be launched directly, i.e.  it can run in the
 foreground as well (not as a daemon/service).  The procedure is quite
 simple: you have to invoke the executable from the command line with all
 the requested parameters except for the
@@ -173,9 +202,10 @@
 .BI -l " host_list"
 Only allow hosts specified in the
 .I host_list
-file to connect to this server.
-Hosts are listed one per line.
-We suggest that you use use host names rather than literal IP addresses
+argument to connect to this server.
+.I host_list
+is a list of host names or IP addresses, separated by commas.
+We suggest that you use host names rather than literal IP addresses
 in order to avoid problems with different address families.
 .TP
 .B \-n
@@ -199,25 +229,57 @@
 it accepts passive connections as well.
 .TP
 .B \-d
-Run in daemon mode (UNIX only) or as a service (Win32 only)
-Warning (Win32): this switch is provided automatically when
+Run in daemon mode (UNIX only) or as a service (Win32 only).
+Warning (Win32): this flag is specified automatically when
 the service is started from the control panel.
 .TP
 .B \-i
 Run in inetd mode (UNIX only).
 .TP
+.B \-D
+Log debugging messages.
+.TP
 .BI \-s " config_file"
 Save the current configuration to
-.IR config_file .
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@).
 .TP
 .BI \-f " config_file"
 Load the current configuration from
-.IR config_file ;
-all switches specified from the command line are ignored.
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@)
+and ignore all flags specified on the command line.
 .TP
 .B \-h
 Print this help screen.
+.LP
+If
+.B rpcapd
+was compiled with SSL support, the following options are also
+available:
+.TP
+.B \-S
+Require that SSL be used on connections.
+.TP
+.B \-C
+With SSL enabled, XXX - I'm not sure how *fetching* the list of
+compression mechanisms does anything to compression.
+.TP
+.B \-S
+.I ssl_keyfile
+With SSL enabled, use
+.I ssl_keyfile
+as the SSL key file.
+.TP
+.B \-X
+.I ssl_certfile
+With SSL enabled, use
+.I ssl_certfile
+as the SSL certificate file.
 .br
 .ad
 .SH "SEE ALSO"
-pcap(3PCAP)
+.BR pcap (3PCAP),
+.BR rpcapd-config (@MAN_FILE_FORMATS@)
diff --git a/rpcapd/win32-svc.c b/rpcapd/win32-svc.c
index 8cc7dc9..49b6804 100644
--- a/rpcapd/win32-svc.c
+++ b/rpcapd/win32-svc.c
@@ -33,52 +33,43 @@
 
 #include "rpcapd.h"
 #include <pcap.h>		// for PCAP_ERRBUF_SIZE
-#include "sockutils.h"		// for SOCK_DEBUG_MESSAGE
+#include "fmtutils.h"
 #include "portability.h"
 #include "fileconf.h"
+#include "log.h"
+
+#include "win32-svc.h"	// for Win32 service stuff
 
 static SERVICE_STATUS_HANDLE service_status_handle;
 static SERVICE_STATUS service_status;
 
-void svc_geterr(char *str);
 static void WINAPI svc_main(DWORD argc, char **argv);
+static void WINAPI svc_control_handler(DWORD Opcode);
 static void update_svc_status(DWORD state, DWORD progress_indicator);
 
-int svc_start(void)
+BOOL svc_start(void)
 {
-	int rc;
+	BOOL rc;
 	SERVICE_TABLE_ENTRY ste[] =
 	{
 		{ PROGRAM_NAME, svc_main },
 		{ NULL, NULL }
 	};
+	char string[PCAP_ERRBUF_SIZE];
 
 	// This call is blocking. A new thread is created which will launch
 	// the svc_main() function
-	if ( (rc = StartServiceCtrlDispatcher(ste)) == 0)
-		svc_geterr("StartServiceCtrlDispatcher()");
+	if ((rc = StartServiceCtrlDispatcher(ste)) == 0) {
+		pcap_fmt_errmsg_for_win32_err(string, sizeof (string),
+		    GetLastError(), "StartServiceCtrlDispatcher() failed");
+		rpcapd_log(LOGPRIO_ERROR, "%s", string);
+	}
 
 	return rc; // FALSE if this is not started as a service
 }
 
-void svc_geterr(char *str)
-{
-	char message[PCAP_ERRBUF_SIZE];
-	char string[PCAP_ERRBUF_SIZE];
-	int val;
-
-	val = GetLastError();
-	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
-				  FORMAT_MESSAGE_MAX_WIDTH_MASK,
-				  NULL, val, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-				  (LPSTR) string, PCAP_ERRBUF_SIZE, NULL);
-
-	pcap_snprintf(message, PCAP_ERRBUF_SIZE, "%s failed with error %d: %s", str, val, string);
-
-	SOCK_DEBUG_MESSAGE(message);
-}
-
-void WINAPI svc_control_handler(DWORD Opcode)
+static void WINAPI
+svc_control_handler(DWORD Opcode)
 {
 	switch(Opcode)
 	{
@@ -143,7 +134,8 @@
 	return;
 }
 
-void WINAPI svc_main(DWORD argc, char **argv)
+static void WINAPI
+svc_main(DWORD argc, char **argv)
 {
 	service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
 
diff --git a/rpcapd/win32-svc.h b/rpcapd/win32-svc.h
index 3f511d2..60b25ec 100644
--- a/rpcapd/win32-svc.h
+++ b/rpcapd/win32-svc.h
@@ -30,4 +30,4 @@
  *
  */
 
-int svc_start(void);
+BOOL svc_start(void);
diff --git a/savefile.c b/savefile.c
index ec44ef4..d04b917 100644
--- a/savefile.c
+++ b/savefile.c
@@ -43,6 +43,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h> /* for INT_MAX */
 
 #include "pcap-int.h"
 
@@ -52,22 +53,23 @@
 
 #include "sf-pcap.h"
 #include "sf-pcapng.h"
+#include "pcap-common.h"
+#include "charconv.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
+ * This isn't exported on Windows, because it would only work if both
+ * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise,
+ * a FILE structure in WinPcap/Npcap and a FILE structure in the code using it
  * could be different if they're using different versions of the C runtime.
  *
- * Instead, pcap/pcap.h defines them as macros that wrap the hopen versions,
- * with the wrappers calling _fileno() and _get_osfhandle() themselves,
- * so that they convert the appropriate CRT version's FILE structure to
+ * Instead, pcap/pcap.h defines it as a macro that wraps the hopen version,
+ * with the wrapper calling _fileno() and _get_osfhandle() themselves,
+ * so that it 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
 
 /*
@@ -104,7 +106,7 @@
 	 * as it would have to handle reading partial packets and
 	 * keeping the state of the read.)
 	 */
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Savefiles cannot be put into non-blocking mode");
 	return (-1);
 }
@@ -112,40 +114,40 @@
 static int
 sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from savefiles");
 	return (-1);
 }
 
 #ifdef _WIN32
 static struct pcap_stat *
-sf_stats_ex(pcap_t *p, int *size)
+sf_stats_ex(pcap_t *p, int *size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from savefiles");
 	return (NULL);
 }
 
 static int
-sf_setbuff(pcap_t *p, int dim)
+sf_setbuff(pcap_t *p, int dim _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The kernel buffer size cannot be set while reading from a file");
 	return (-1);
 }
 
 static int
-sf_setmode(pcap_t *p, int mode)
+sf_setmode(pcap_t *p, int mode _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "impossible to set mode while reading from a file");
 	return (-1);
 }
 
 static int
-sf_setmintocopy(pcap_t *p, int size)
+sf_setmintocopy(pcap_t *p, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The mintocopy parameter cannot be set while reading from a file");
 	return (-1);
 }
@@ -153,7 +155,7 @@
 static HANDLE
 sf_getevent(pcap_t *pcap)
 {
-	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "The read event cannot be retrieved while reading from a file");
 	return (INVALID_HANDLE_VALUE);
 }
@@ -162,7 +164,7 @@
 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,
+	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "An OID get request cannot be performed on a file");
 	return (PCAP_ERROR);
 }
@@ -171,54 +173,54 @@
 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,
+	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)
+sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
 {
-	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
 	    PCAP_ERRBUF_SIZE);
 	return (0);
 }
 
 static int
-sf_setuserbuffer(pcap_t *p, int size)
+sf_setuserbuffer(pcap_t *p, int size _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	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)
+sf_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	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)
+sf_live_dump_ended(pcap_t *p, int sync _U_)
 {
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	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)
+sf_get_airpcap_handle(pcap_t *pcap _U_)
 {
 	return (NULL);
 }
 #endif
 
 static int
-sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+sf_inject(pcap_t *p, const void *buf _U_, int size _U_)
 {
-	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
 	    PCAP_ERRBUF_SIZE);
 	return (-1);
 }
@@ -230,7 +232,7 @@
 static int
 sf_setdirection(pcap_t *p, pcap_direction_t d _U_)
 {
-	pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+	snprintf(p->errbuf, sizeof(p->errbuf),
 	    "Setting direction is not supported on savefiles");
 	return (-1);
 }
@@ -245,6 +247,94 @@
 	pcap_freecode(&p->fcode);
 }
 
+#ifdef _WIN32
+/*
+ * Wrapper for fopen() and _wfopen().
+ *
+ * If we're in UTF-8 mode, map the pathname from UTF-8 to UTF-16LE and
+ * call _wfopen().
+ *
+ * If we're not, just use fopen(); that'll treat it as being in the
+ * local code page.
+ */
+FILE *
+charset_fopen(const char *path, const char *mode)
+{
+	wchar_t *utf16_path;
+#define MAX_MODE_LEN	16
+	wchar_t utf16_mode[MAX_MODE_LEN+1];
+	int i;
+	char c;
+	FILE *fp;
+	int save_errno;
+
+	if (pcap_utf_8_mode) {
+		/*
+		 * Map from UTF-8 to UTF-16LE.
+		 * Fail if there are invalid characters in the input
+		 * string, rather than converting them to REPLACEMENT
+		 * CHARACTER; the latter is appropriate for strings
+		 * to be displayed to the user, but for file names
+		 * you just want the attempt to open the file to fail.
+		 */
+		utf16_path = cp_to_utf_16le(CP_UTF8, path,
+		    MB_ERR_INVALID_CHARS);
+		if (utf16_path == NULL) {
+			/*
+			 * Error.  Assume errno has been set.
+			 *
+			 * XXX - what about Windows errors?
+			 */
+			return (NULL);
+		}
+
+		/*
+		 * Now convert the mode to UTF-16LE as well.
+		 * We assume the mode is ASCII, and that
+		 * it's short, so that's easy.
+		 */
+		for (i = 0; (c = *mode) != '\0'; i++, mode++) {
+			if (c > 0x7F) {
+				/* Not an ASCII character; fail with EINVAL. */
+				free(utf16_path);
+				errno = EINVAL;
+				return (NULL);
+			}
+			if (i >= MAX_MODE_LEN) {
+				/* The mode string is longer than we allow. */
+				free(utf16_path);
+				errno = EINVAL;
+				return (NULL);
+			}
+			utf16_mode[i] = c;
+		}
+		utf16_mode[i] = '\0';
+
+		/*
+		 * OK, we have UTF-16LE strings; hand them to
+		 * _wfopen().
+		 */
+		fp = _wfopen(utf16_path, utf16_mode);
+
+		/*
+		 * Make sure freeing the UTF-16LE string doesn't
+		 * overwrite the error code we got from _wfopen().
+		 */
+		save_errno = errno;
+		free(utf16_path);
+		errno = save_errno;
+
+		return (fp);
+	} else {
+		/*
+		 * This takes strings in the local code page as an
+		 * argument.
+		 */
+		return (fopen(path, mode));
+	}
+}
+#endif
+
 pcap_t *
 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
 					char *errbuf)
@@ -253,13 +343,18 @@
 	pcap_t *p;
 
 	if (fname == NULL) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		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 (stdin == NULL) {
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "The standard input is not open");
+			return (NULL);
+		}
 #if defined(_WIN32) || defined(MSDOS)
 		/*
 		 * We're reading from the standard input, so put it in binary
@@ -270,12 +365,16 @@
 	}
 	else {
 		/*
+		 * Use charset_fopen(); on Windows, it tests whether we're
+		 * in "local code page" or "UTF-8" mode, and treats the
+		 * pathname appropriately, and on other platforms, it just
+		 * wraps fopen().
+		 *
 		 * "b" is supported as of C90, so *all* UN*Xes should
-		 * support it, even though it does nothing.  It's
-		 * required on Windows, as the file is a binary file
-		 * and must be read in binary mode.
+		 * support it, even though it does nothing.  For MS-DOS,
+		 * we again need it.
 		 */
-		fp = fopen(fname, "rb");
+		fp = charset_fopen(fname, "rb");
 		if (fp == NULL) {
 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "%s", fname);
@@ -317,6 +416,7 @@
 	{
 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "_fdopen");
+		_close(fd);
 		return NULL;
 	}
 
@@ -331,7 +431,34 @@
 }
 #endif
 
-static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
+/*
+ * Given a link-layer header type and snapshot length, return a
+ * snapshot length to use when reading the file; it's guaranteed
+ * to be > 0 and <= INT_MAX.
+ *
+ * XXX - the only reason why we limit it to <= INT_MAX is so that
+ * it fits in p->snapshot, and the only reason that p->snapshot is
+ * signed is that pcap_snapshot() returns an int, not an unsigned int.
+ */
+bpf_u_int32
+pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen)
+{
+	if (snaplen == 0 || snaplen > INT_MAX) {
+		/*
+		 * Bogus snapshot length; use the maximum for this
+		 * link-layer type as a fallback.
+		 *
+		 * XXX - we don't clamp snapshot lengths that are
+		 * <= INT_MAX but > max_snaplen_for_dlt(linktype),
+		 * so a capture file could cause us to allocate
+		 * a Really Big Buffer.
+		 */
+		snaplen = max_snaplen_for_dlt(linktype);
+	}
+	return snaplen;
+}
+
+static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = {
 	pcap_check_header,
 	pcap_ng_check_header
 };
@@ -346,28 +473,40 @@
     char *errbuf)
 {
 	register pcap_t *p;
-	bpf_u_int32 magic;
+	uint8_t magic[4];
 	size_t amt_read;
 	u_int i;
 	int err;
 
 	/*
+	 * Fail if we were passed a NULL fp.
+	 *
+	 * That shouldn't happen if we're opening with a path name, but
+	 * it could happen if buggy code is opening with a FILE * and
+	 * didn't bother to make sure the FILE * isn't null.
+	 */
+	if (fp == NULL) {
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Null FILE * pointer provided to savefile open routine");
+		return (NULL);
+	}
+
+	/*
 	 * Read the first 4 bytes of the file; the network analyzer dump
 	 * file formats we support (pcap and pcapng), and several other
 	 * formats we might support in the future (such as snoop, DOS and
 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
 	 * numbers that are unique in their first 4 bytes.
 	 */
-	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
+	amt_read = fread(&magic, 1, sizeof(magic), fp);
 	if (amt_read != sizeof(magic)) {
 		if (ferror(fp)) {
 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "error reading dump file");
 		} else {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
-			    (unsigned long)sizeof(magic),
-			    (unsigned long)amt_read);
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "truncated dump file; tried to read %zu file header bytes, only got %zu",
+			    sizeof(magic), amt_read);
 		}
 		return (NULL);
 	}
@@ -392,7 +531,7 @@
 	/*
 	 * Well, who knows what this mess is....
 	 */
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
+	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
 	return (NULL);
 
 found:
@@ -442,6 +581,11 @@
 	p->oneshot_callback = pcap_oneshot;
 
 	/*
+	 * Default breakloop operation.
+	 */
+	p->breakloop_op = pcap_breakloop_common;
+
+	/*
 	 * Savefiles never require special BPF code generation.
 	 */
 	p->bpf_codegen_flags = 0;
@@ -451,15 +595,19 @@
 	return (p);
 }
 
-#ifdef _WIN32
-static
-#endif
+/*
+ * This isn't needed on Windows; we #define pcap_fopen_offline() as
+ * a wrapper around pcap_hopen_offline(), and we don't call it from
+ * inside this file, so it's unused.
+ */
+#ifndef _WIN32
 pcap_t *
 pcap_fopen_offline(FILE *fp, char *errbuf)
 {
 	return (pcap_fopen_offline_with_tstamp_precision(fp,
 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
 }
+#endif
 
 /*
  * Read packets from a capture file, and call the callback for each
@@ -502,7 +650,7 @@
 		}
 
 		if ((fcode = p->fcode.bf_insns) == NULL ||
-		    bpf_filter(fcode, data, h.len, h.caplen)) {
+		    pcap_filter(fcode, data, h.len, h.caplen)) {
 			(*callback)(user, &h, data);
 			if (++n >= cnt && cnt > 0)
 				break;
diff --git a/scanner.c b/scanner.c
index 2cf65c9..4b1572f 100644
--- a/scanner.c
+++ b/scanner.c
@@ -35,11 +35,233 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
 
+#ifdef yy_create_buffer
+#define pcap__create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer pcap__create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define pcap__delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer pcap__delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define pcap__scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer pcap__scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define pcap__scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string pcap__scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define pcap__scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes pcap__scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define pcap__init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer pcap__init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define pcap__flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer pcap__flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define pcap__load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state pcap__load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define pcap__switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer pcap__switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define pcap_push_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state pcap_push_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define pcap_pop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state pcap_pop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define pcap_ensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack pcap_ensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define pcap_lex_ALREADY_DEFINED
+#else
+#define yylex pcap_lex
+#endif
+
+#ifdef yyrestart
+#define pcap_restart_ALREADY_DEFINED
+#else
+#define yyrestart pcap_restart
+#endif
+
+#ifdef yylex_init
+#define pcap_lex_init_ALREADY_DEFINED
+#else
+#define yylex_init pcap_lex_init
+#endif
+
+#ifdef yylex_init_extra
+#define pcap_lex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra pcap_lex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define pcap_lex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy pcap_lex_destroy
+#endif
+
+#ifdef yyget_debug
+#define pcap_get_debug_ALREADY_DEFINED
+#else
+#define yyget_debug pcap_get_debug
+#endif
+
+#ifdef yyset_debug
+#define pcap_set_debug_ALREADY_DEFINED
+#else
+#define yyset_debug pcap_set_debug
+#endif
+
+#ifdef yyget_extra
+#define pcap_get_extra_ALREADY_DEFINED
+#else
+#define yyget_extra pcap_get_extra
+#endif
+
+#ifdef yyset_extra
+#define pcap_set_extra_ALREADY_DEFINED
+#else
+#define yyset_extra pcap_set_extra
+#endif
+
+#ifdef yyget_in
+#define pcap_get_in_ALREADY_DEFINED
+#else
+#define yyget_in pcap_get_in
+#endif
+
+#ifdef yyset_in
+#define pcap_set_in_ALREADY_DEFINED
+#else
+#define yyset_in pcap_set_in
+#endif
+
+#ifdef yyget_out
+#define pcap_get_out_ALREADY_DEFINED
+#else
+#define yyget_out pcap_get_out
+#endif
+
+#ifdef yyset_out
+#define pcap_set_out_ALREADY_DEFINED
+#else
+#define yyset_out pcap_set_out
+#endif
+
+#ifdef yyget_leng
+#define pcap_get_leng_ALREADY_DEFINED
+#else
+#define yyget_leng pcap_get_leng
+#endif
+
+#ifdef yyget_text
+#define pcap_get_text_ALREADY_DEFINED
+#else
+#define yyget_text pcap_get_text
+#endif
+
+#ifdef yyget_lineno
+#define pcap_get_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno pcap_get_lineno
+#endif
+
+#ifdef yyset_lineno
+#define pcap_set_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno pcap_set_lineno
+#endif
+
+#ifdef yyget_column
+#define pcap_get_column_ALREADY_DEFINED
+#else
+#define yyget_column pcap_get_column
+#endif
+
+#ifdef yyset_column
+#define pcap_set_column_ALREADY_DEFINED
+#else
+#define yyset_column pcap_set_column
+#endif
+
+#ifdef yywrap
+#define pcap_wrap_ALREADY_DEFINED
+#else
+#define yywrap pcap_wrap
+#endif
+
+#ifdef yyget_lval
+#define pcap_get_lval_ALREADY_DEFINED
+#else
+#define yyget_lval pcap_get_lval
+#endif
+
+#ifdef yyset_lval
+#define pcap_set_lval_ALREADY_DEFINED
+#else
+#define yyset_lval pcap_set_lval
+#endif
+
+#ifdef yyalloc
+#define pcap_alloc_ALREADY_DEFINED
+#else
+#define yyalloc pcap_alloc
+#endif
+
+#ifdef yyrealloc
+#define pcap_realloc_ALREADY_DEFINED
+#else
+#define yyrealloc pcap_realloc
+#endif
+
+#ifdef yyfree
+#define pcap_free_ALREADY_DEFINED
+#else
+#define yyfree pcap_free
+#endif
+
 /* First, we deal with  platform-specific or compiler-specific issues. */
 
 /* begin standard C headers. */
@@ -110,10 +332,16 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
 #endif /* ! C99 */
 
 #endif /* ! FLEXINT_H */
 
+/* begin standard C++ headers. */
+
 /* TODO: this is always defined, so inline it */
 #define yyconst const
 
@@ -126,12 +354,10 @@
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ *   integer in range [0..255] for use as an array index.
  */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
 
 /* An opaque pointer. */
 #ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -155,20 +381,16 @@
  * definition of BEGIN.
  */
 #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 ((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(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
 #define YY_END_OF_BUFFER_CHAR 0
 
 /* Size of default input buffer. */
@@ -201,7 +423,7 @@
 #define EOB_ACT_CONTINUE_SCAN 0
 #define EOB_ACT_END_OF_FILE 1
 #define EOB_ACT_LAST_MATCH 2
-
+    
     #define YY_LESS_LINENO(n)
     #define YY_LINENO_REWIND_TO(ptr)
     
@@ -218,7 +440,6 @@
 		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
 		} \
 	while ( 0 )
-
 #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
 
 #ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -278,7 +499,7 @@
 	 * possible backing-up.
 	 *
 	 * When we actually see the EOF, we change the status to "new"
-	 * (via pcap_restart()), so that the user can continue scanning by
+	 * (via yyrestart()), so that the user can continue scanning by
 	 * just pointing yyin at a new input file.
 	 */
 #define YY_BUFFER_EOF_PENDING 2
@@ -295,73 +516,67 @@
 #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 yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
 
-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 );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
 
-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 );
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
 
-#define YY_FLUSH_BUFFER pcap__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , 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,int len ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , 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 );
-
-#define yy_new_buffer pcap__create_buffer
-
+#define yy_new_buffer yy_create_buffer
 #define yy_set_interactive(is_interactive) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){ \
-        pcap_ensure_buffer_stack (yyscanner); \
+        yyensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
 	}
-
 #define yy_set_bol(at_bol) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){\
-        pcap_ensure_buffer_stack (yyscanner); \
+        yyensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
 	}
-
 #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
 /* Begin user sect3 */
 
 #define pcap_wrap(yyscanner) (/*CONSTCOND*/1)
 #define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
 
 typedef int yy_state_type;
 
 #define yytext_ptr yytext_r
 
-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 yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+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 yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
@@ -372,9 +587,8 @@
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 184
-#define YY_END_OF_BUFFER 185
+#define YY_NUM_RULES 183
+#define YY_END_OF_BUFFER 184
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -382,201 +596,201 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[1729] =
+static const flex_int16_t yy_accept[1724] =
     {   0,
-        0,    0,  185,  182,  113,  113,  113,  114,  182,  114,
-      114,  114,  183,  123,  123,  114,  114,  114,  114,  180,
-      180,  182,  180,  180,  180,  180,  180,  180,  180,  180,
+        0,    0,  184,  182,  113,  113,  114,  182,  114,  114,
+      123,  123,  114,  114,  114,  114,  180,  180,  182,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  114,  182,  117,  121,   67,    0,  180,  123,
-        0,  180,  180,  180,    0,  125,  119,  116,  118,  115,
-      120,  180,  181,  181,  180,  180,  180,   20,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  114,
+      117,  121,   67,    0,  180,  123,    0,  180,  180,  180,
+        0,  125,  119,  116,  118,  115,  120,  180,  181,  180,
+      180,  180,   20,  180,  180,  180,  180,  180,  180,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,    7,  180,   34,   35,
 
-      180,    7,  180,   34,   35,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,   92,
-      180,   68,  180,  180,  180,  180,  180,  180,   60,  180,
-      180,  180,  180,   86,  180,  180,  180,  180,  180,  180,
-       61,  180,    4,  180,  180,  180,  180,  180,  180,  180,
-       68,  121,  180,  124,  124,  180,  123,  180,    0,  125,
-      123,  125,  125,  125,  180,  180,  180,   67,    5,  180,
-       81,  180,  180,  180,  180,  180,  180,  180,   55,  107,
-        1,    0,  180,   21,  180,  180,  180,  180,  180,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-
-      180,  180,   36,  180,  180,   18,   43,    0,  180,   29,
-      180,   25,   70,  180,  180,   79,   37,  180,  100,  180,
-      180,  180,  180,  101,  180,   46,   69,   82,  106,  180,
-       14,  180,    3,  180,  180,  180,  180,  180,   94,  180,
-      180,   26,  180,  105,  180,  108,   38,    2,  180,   42,
-      180,    9,  180,   10,   89,  180,   88,  180,  180,    0,
-      180,  180,  124,  180,  180,  180,  180,  123,    0,  180,
-        0,  126,  125,  125,    0,  125,    0,  125,    0,  125,
-        0,   23,  180,  180,  180,  180,   64,   16,   41,  180,
-       39,  180,  180,  180,   30,  180,   98,  180,  180,  180,
-
-      111,  180,  180,  104,  110,   45,  109,  112,   11,  180,
-       12,   13,  180,  180,  180,   32,   78,  180,   62,    3,
-       99,   47,  180,  180,  180,   74,  180,  180,  180,  180,
-       48,  180,  180,   40,  180,    6,  180,   93,  180,    8,
-       95,  180,  180,    0,  180,   53,   73,   15,  180,  124,
-      124,  180,  124,  124,  124,  180,  123,  180,    0,  125,
-      180,    0,    0,  125,    0,  125,  126,  125,    0,    0,
-        0,    0,  125,  125,  125,  125,  125,    0,  180,   56,
-       57,   58,   59,  180,   22,  180,  180,  180,  180,   31,
-      180,  180,  180,  102,  103,    0,   19,  180,  180,  180,
-
-       87,  180,   33,  180,   80,   28,   27,  180,  180,   83,
-      180,  180,  180,   50,   17,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,    0,
-      180,  180,  124,  180,  180,  180,  180,  124,  124,  180,
-      123,  180,    0,    0,  125,  125,  125,    0,    0,  126,
-      125,  125,  126,  125,    0,    0,  125,  125,  125,  125,
-      125,    0,    0,    0,    0,  125,  125,    0,  125,    0,
-      125,    0,   97,  180,  180,  180,   24,  180,  180,   77,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,    0,
-      180,  180,  180,  180,  180,   70,  180,  180,  180,  180,
-
-      180,  180,  180,   75,   76,  180,   96,  180,  180,  180,
+      180,  180,  180,  180,   92,  180,   68,  180,  180,  180,
+      180,  180,  180,   60,  180,  180,  180,  180,   86,  180,
+      180,  180,  180,  180,  180,   61,  180,    4,  180,  180,
+      180,  180,  180,  180,  180,   68,  121,  180,  124,  124,
+      180,  123,  180,    0,  125,  123,  125,  125,  125,  180,
+      180,  180,   67,    5,  180,   81,  180,  180,  180,  180,
+      180,  180,  180,   55,  107,    1,    0,  180,   21,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  124,  124,  180,  124,  124,  124,  124,  180,  123,
-      180,    0,  125,  125,    0,  125,    0,    0,  125,    0,
-      125,  126,  125,    0,    0,    0,  125,  125,    0,  125,
-      126,  125,    0,    0,    0,    0,    0,    0,    0,  125,
-      125,  125,  125,  125,    0,  180,  180,  180,  180,   52,
-       63,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,   71,  180,  180,   44,   84,   85,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,   36,  180,  180,
 
-      180,  180,   54,  176,  179,  178,  172,  180,  174,  173,
-      177,  180,    0,  180,  180,  124,  180,  180,  180,  124,
-      180,  123,  180,    0,    0,  125,  125,  125,  125,  125,
-      125,    0,    0,  126,  125,  125,  125,    0,    0,  125,
-      125,  125,  125,  125,    0,    0,    0,    0,    0,    0,
+       18,   43,    0,  180,   29,  180,   25,   70,  180,  180,
+       79,   37,  180,  100,  180,  180,  180,  180,  101,  180,
+       46,   69,   82,  106,  180,   14,  180,    3,  180,  180,
+      180,  180,  180,   94,  180,  180,   26,  180,  105,  180,
+      108,   38,    2,  180,   42,  180,    9,  180,   10,   89,
+      180,   88,  180,  180,    0,  180,  180,  124,  180,  180,
+      180,  180,  123,    0,  180,    0,  126,  125,  125,    0,
+      125,    0,  125,    0,  125,    0,   23,  180,  180,  180,
+      180,   64,   16,   41,  180,   39,  180,  180,  180,   30,
+      180,   98,  180,  180,  180,  111,  180,  180,  104,  110,
+
+       45,  109,  112,   11,  180,   12,   13,  180,  180,  180,
+       32,   78,  180,   62,    3,   99,   47,  180,  180,  180,
+       74,  180,  180,  180,  180,   48,  180,  180,   40,  180,
+        6,  180,   93,  180,    8,   95,  180,  180,    0,  180,
+       53,   73,   15,  180,  124,  124,  180,  124,  124,  124,
+      180,  123,  180,    0,  125,  180,    0,    0,  125,    0,
+      125,  126,  125,    0,    0,    0,    0,  125,  125,  125,
+      125,  125,    0,  180,   56,   57,   58,   59,  180,   22,
+      180,  180,  180,  180,   31,  180,  180,  180,  102,  103,
+        0,   19,  180,  180,  180,   87,  180,   33,  180,   80,
+
+       28,   27,  180,  180,   83,  180,  180,  180,   50,   17,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,    0,  180,  180,  124,  180,  180,
+      180,  180,  124,  124,  180,  123,  180,    0,    0,  125,
+      125,  125,    0,    0,  126,  125,  125,  126,  125,    0,
         0,  125,  125,  125,  125,  125,    0,    0,    0,    0,
-        0,  125,  125,    0,  125,    0,  125,    0,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  128,  127,  180,  180,   72,  180,  180,
+      125,  125,    0,  125,    0,  125,    0,   97,  180,  180,
+      180,   24,  180,  180,   77,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,    0,  180,  180,  180,  180,  180,
+       70,  180,  180,  180,  180,  180,  180,  180,   75,   76,
 
-      180,  175,  171,  180,  180,  124,  124,  124,  124,  180,
-      123,  180,    0,  125,  125,    0,  125,  125,    0,  125,
-        0,    0,  125,    0,  125,  126,  125,    0,    0,    0,
-      125,  125,    0,  125,  126,  125,    0,    0,    0,    0,
-        0,  125,  125,    0,  125,  126,  125,    0,  125,  125,
-        0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
-      125,  125,    0,   65,  180,   55,  133,  140,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  145,  144,  180,   66,
-       49,  180,  180,    0,  180,  180,  180,  180,  180,  123,
-
-      180,    0,    0,  125,  125,  125,  125,  125,  125,  125,
-      125,  125,    0,    0,  126,  125,  125,  125,    0,    0,
-      125,  125,  125,  125,  125,    0,    0,    0,    0,    0,
-        0,    0,  125,  125,  125,  125,  125,    0,  125,  125,
-        0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
-      125,  125,    0,    0,    0,    0,    0,    0,  125,  125,
-        0,  125,    0,  125,    0,   90,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  146,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,   51,  122,  122,
-      124,  124,  180,  123,  180,    0,  125,  125,    0,  125,
-
-      125,    0,  125,  125,    0,  125,    0,  122,  125,    0,
-      125,  126,  125,    0,    0,    0,  125,  125,    0,  125,
-      126,  125,    0,    0,    0,    0,    0,  125,  125,    0,
-      125,  126,  125,    0,    0,    0,    0,    0,    0,  125,
-      125,    0,  125,  126,  125,    0,  125,  125,  125,    0,
-        0,    0,    0,    0,    0,    0,  125,  125,  125,  125,
-      125,    0,  180,  180,  180,  180,  180,  180,  180,  180,
-      138,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,   91,  122,  122,  124,  180,  122,  122,    0,
-        0,  125,  125,  125,  125,  125,  125,  125,  125,  125,
-
-      125,  125,  125,    0,  122,  126,  125,  125,  125,    0,
-        0,  125,  125,  125,  125,  125,    0,    0,    0,    0,
-        0,    0,    0,  125,  125,  125,  125,  125,    0,  125,
-      125,    0,    0,    0,    0,    0,    0,    0,  125,  125,
-      125,  125,  125,    0,  125,  125,  125,    0,    0,    0,
+      180,   96,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  124,  124,  180,  124,
+      124,  124,  124,  180,  123,  180,    0,  125,  125,    0,
+      125,    0,    0,  125,    0,  125,  126,  125,    0,    0,
+        0,  125,  125,    0,  125,  126,  125,    0,    0,    0,
         0,    0,    0,    0,  125,  125,  125,  125,  125,    0,
-        0,    0,    0,    0,    0,  125,  125,    0,  125,    0,
-      125,    0,  180,  180,  180,  142,  180,  180,  180,  180,
-      180,  180,  180,  130,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  124,  180,  123,    0,  125,  125,
-
-        0,  125,  125,    0,  125,  125,    0,  125,  125,    0,
-      125,    0,    0,    0,  125,    0,    0,  125,  126,  125,
-        0,    0,    0,  125,  125,    0,  125,  126,  125,    0,
-        0,    0,    0,    0,  125,  125,    0,  125,  126,  125,
-        0,    0,    0,    0,    0,    0,  125,  125,    0,  125,
-      126,  125,    0,    0,    0,    0,    0,    0,  125,  125,
-        0,  125,  126,  125,    0,  125,  125,  125,    0,    0,
-        0,    0,    0,    0,    0,  125,  125,  125,  125,  125,
-        0,  180,  180,  180,  180,  132,  180,  180,  180,  136,
+      180,  180,  180,  180,   52,   63,  180,  180,  180,  180,
       180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,   71,  180,  180,
+       44,   84,   85,  180,  180,  180,  180,   54,  176,  179,
 
-      180,  180,  180,  122,    0,    0,  125,  125,  125,  125,
-      125,  125,  125,  125,  125,  125,  125,  125,  125,  125,
-      125,    0,    0,    0,  126,    0,    0,  125,    0,    0,
-      125,  125,  125,    0,    0,    0,    0,    0,    0,    0,
-      125,  125,  125,    0,  125,  125,    0,    0,    0,    0,
-        0,    0,    0,  125,  125,  125,    0,  125,  125,  125,
+      178,  172,  180,  174,  173,  177,  180,    0,  180,  180,
+      124,  180,  180,  180,  124,  180,  123,  180,    0,    0,
+      125,  125,  125,  125,  125,  125,    0,    0,  126,  125,
+      125,  125,    0,    0,  125,  125,  125,  125,  125,    0,
+        0,    0,    0,    0,    0,    0,  125,  125,  125,  125,
+      125,    0,    0,    0,    0,    0,  125,  125,    0,  125,
+        0,  125,    0,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  128,  127,
+      180,  180,   72,  180,  180,  180,  175,  171,  180,  180,
+
+      124,  124,  124,  124,  180,  123,  180,    0,  125,  125,
+        0,  125,  125,    0,  125,    0,    0,  125,    0,  125,
+      126,  125,    0,    0,    0,  125,  125,    0,  125,  126,
+      125,    0,    0,    0,    0,    0,  125,  125,    0,  125,
+      126,  125,    0,  125,  125,    0,    0,    0,    0,    0,
+        0,    0,  125,  125,  125,  125,  125,    0,   65,  180,
+       55,  133,  140,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  145,  144,  180,   66,   49,  180,  180,    0,  180,
+      180,  180,  180,  180,  123,  180,    0,    0,  125,  125,
+
+      125,  125,  125,  125,  125,  125,  125,    0,    0,  126,
+      125,  125,  125,    0,    0,  125,  125,  125,  125,  125,
         0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
-        0,  125,  125,  125,    0,    0,    0,    0,    0,    0,
-        0,  125,  125,  125,    0,    0,    0,    0,    0,    0,
-      125,  125,    0,  125,    0,  125,    0,  129,  141,  143,
+      125,  125,    0,  125,  125,    0,    0,    0,    0,    0,
+        0,    0,  125,  125,  125,  125,  125,    0,    0,    0,
+        0,    0,    0,  125,  125,    0,  125,    0,  125,    0,
+       90,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  146,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,   51,  122,  122,  124,  124,  180,  123,  180,
+        0,  125,  125,    0,  125,  125,    0,  125,  125,    0,
 
-      137,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  155,  180,  180,  180,    0,    0,  125,
-        0,  125,    0,  125,  125,    0,  125,  125,    0,  125,
-      125,    0,  125,  125,    0,  125,    0,    0,    0,    0,
-      125,  125,    0,  125,    0,    0,  125,  125,  125,    0,
-        0,    0,    0,  125,  125,  125,    0,    0,    0,    0,
-        0,  125,  125,  125,    0,    0,    0,    0,    0,  125,
-      125,  125,    0,    0,    0,    0,    0,  125,  125,  125,
+      125,    0,  122,  125,    0,  125,  126,  125,    0,    0,
+        0,  125,  125,    0,  125,  126,  125,    0,    0,    0,
+        0,    0,  125,  125,    0,  125,  126,  125,    0,    0,
+        0,    0,    0,    0,  125,  125,    0,  125,  126,  125,
+        0,  125,  125,  125,    0,    0,    0,    0,    0,    0,
+        0,  125,  125,  125,  125,  125,    0,  180,  180,  180,
+      180,  180,  180,  180,  180,  138,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,   91,  122,  122,
+      124,  180,  122,  122,    0,    0,  125,  125,  125,  125,
+      125,  125,  125,  125,  125,  125,  125,  125,    0,  122,
+
+      126,  125,  125,  125,    0,    0,  125,  125,  125,  125,
+      125,    0,    0,    0,    0,    0,    0,    0,  125,  125,
+      125,  125,  125,    0,  125,  125,    0,    0,    0,    0,
+        0,    0,    0,  125,  125,  125,  125,  125,    0,  125,
+      125,  125,    0,    0,    0,    0,    0,    0,    0,  125,
+      125,  125,  125,  125,    0,    0,    0,    0,    0,    0,
+      125,  125,    0,  125,    0,  125,    0,  180,  180,  180,
+      142,  180,  180,  180,  180,  180,  180,  180,  130,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  124,
+      180,  123,    0,  125,  125,    0,  125,  125,    0,  125,
+
+      125,    0,  125,  125,    0,  125,    0,    0,    0,  125,
+        0,    0,  125,  126,  125,    0,    0,    0,  125,  125,
+        0,  125,  126,  125,    0,    0,    0,    0,    0,  125,
+      125,    0,  125,  126,  125,    0,    0,    0,    0,    0,
+        0,  125,  125,    0,  125,  126,  125,    0,    0,    0,
+        0,    0,    0,  125,  125,    0,  125,  126,  125,    0,
       125,  125,  125,    0,    0,    0,    0,    0,    0,    0,
-      125,  125,  125,    0,  180,  180,  180,  180,  180,  180,
+      125,  125,  125,  125,  125,    0,  180,  180,  180,  180,
+      132,  180,  180,  180,  136,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  122,    0,
 
-      147,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,    0,    0,    0,  125,  125,  125,  125,  125,  125,
-        0,    0,    0,    0,  125,  125,    0,    0,    0,    0,
-      125,  125,  125,    0,    0,    0,    0,    0,  125,  125,
-      125,  125,    0,    0,    0,    0,    0,  125,  125,  125,
-      125,    0,    0,    0,    0,    0,  125,  125,  125,  125,
-        0,    0,    0,    0,    0,  125,    0,    0,    0,    0,
-        0,  125,  125,  125,  180,  180,  180,  139,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  125,  125,  125,  125,  125,  125,  125,  125,    0,
-
-        0,    0,    0,  125,  125,    0,    0,  125,    0,    0,
-        0,  125,    0,    0,    0,  125,    0,    0,    0,  125,
-        0,    0,    0,  125,  125,  125,  125,    0,    0,    0,
-        0,    0,  125,  134,  180,  131,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  156,  180,  125,
-        0,    0,  125,  125,    0,  125,  125,  125,    0,  125,
-      125,  125,    0,  125,  125,  125,    0,  125,  125,  125,
-        0,    0,    0,    0,  125,  135,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  152,  180,  125,  125,
+        0,  125,  125,  125,  125,  125,  125,  125,  125,  125,
+      125,  125,  125,  125,  125,  125,    0,    0,    0,  126,
+        0,    0,  125,    0,    0,  125,  125,  125,    0,    0,
+        0,    0,    0,    0,    0,  125,  125,  125,    0,  125,
+      125,    0,    0,    0,    0,    0,    0,    0,  125,  125,
+      125,    0,  125,  125,  125,    0,    0,    0,    0,    0,
+        0,    0,  125,  125,  125,    0,  125,  125,  125,    0,
         0,    0,    0,    0,    0,    0,  125,  125,  125,    0,
+        0,    0,    0,    0,    0,  125,  125,    0,  125,    0,
+      125,    0,  129,  141,  143,  137,  180,  180,  180,  180,
 
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  151,    0,  125,  125,  125,  125,  125,    0,  167,
-      180,  180,  180,  180,  180,  180,  180,  154,  180,  180,
-      125,  125,  166,  180,  180,  180,  180,  180,  180,  153,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  165,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  180,  180,  180,  164,  180,  180,  180,
-      180,  180,  170,  180,  180,  180,  180,  180,  180,  180,
-      180,  180,  180,  157,  180,  180,  180,  180,  180,  150,
+      180,  180,  180,  180,  180,  180,  180,  180,  155,  180,
+      180,  180,    0,    0,  125,    0,  125,    0,  125,  125,
+        0,  125,  125,    0,  125,  125,    0,  125,  125,    0,
+      125,    0,    0,    0,    0,  125,  125,    0,  125,    0,
+        0,  125,  125,  125,    0,    0,    0,    0,  125,  125,
+      125,    0,    0,    0,    0,    0,  125,  125,  125,    0,
+        0,    0,    0,    0,  125,  125,  125,    0,    0,    0,
+        0,    0,  125,  125,  125,  125,  125,  125,    0,    0,
+        0,    0,    0,    0,    0,  125,  125,  125,    0,  180,
+      180,  180,  180,  180,  180,  147,  180,  180,  180,  180,
 
-      180,  180,  168,  180,  180,  180,  180,  180,  180,  148,
-      180,  169,  180,  163,  180,  180,  180,  180,  158,  180,
-      160,  180,  180,  162,  159,  149,  161,    0
+      180,  180,  180,  180,  180,  180,    0,    0,    0,  125,
+      125,  125,  125,  125,  125,    0,    0,    0,    0,  125,
+      125,    0,    0,    0,    0,  125,  125,  125,    0,    0,
+        0,    0,    0,  125,  125,  125,  125,    0,    0,    0,
+        0,    0,  125,  125,  125,  125,    0,    0,    0,    0,
+        0,  125,  125,  125,  125,    0,    0,    0,    0,    0,
+      125,    0,    0,    0,    0,    0,  125,  125,  125,  180,
+      180,  180,  139,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  125,  125,  125,  125,
+      125,  125,  125,  125,    0,    0,    0,    0,  125,  125,
+
+        0,    0,  125,    0,    0,    0,  125,    0,    0,    0,
+      125,    0,    0,    0,  125,    0,    0,    0,  125,  125,
+      125,  125,    0,    0,    0,    0,    0,  125,  134,  180,
+      131,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  156,  180,  125,    0,    0,  125,  125,    0,
+      125,  125,  125,    0,  125,  125,  125,    0,  125,  125,
+      125,    0,  125,  125,  125,    0,    0,    0,    0,  125,
+      135,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  152,  180,  125,  125,    0,    0,    0,    0,    0,
+        0,  125,  125,  125,    0,  180,  180,  180,  180,  180,
+
+      180,  180,  180,  180,  180,  180,  151,    0,  125,  125,
+      125,  125,  125,    0,  167,  180,  180,  180,  180,  180,
+      180,  180,  154,  180,  180,  125,  125,  166,  180,  180,
+      180,  180,  180,  180,  153,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  165,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  164,  180,  180,  180,  180,  180,  170,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  157,  180,
+      180,  180,  180,  180,  150,  180,  180,  168,  180,  180,
+
+      180,  180,  180,  180,  148,  180,  169,  180,  163,  180,
+      180,  180,  180,  158,  180,  160,  180,  180,  162,  159,
+      149,  161,    0
     } ;
 
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
@@ -587,11 +801,11 @@
        21,   22,    1,    1,   23,   23,   23,   23,   23,   23,
        24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
        24,   24,   24,   24,   24,   24,   24,   25,   24,   24,
-       26,   27,   26,    7,   28,    1,   29,   30,   31,   32,
+        7,   26,    7,    7,   27,    1,   28,   29,   30,   31,
 
-       33,   34,   35,   36,   37,   24,   38,   39,   40,   41,
-       42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
-       52,   24,    1,   53,    1,    1,    1,    1,    1,    1,
+       32,   33,   34,   35,   36,   24,   37,   38,   39,   40,
+       41,   42,   43,   44,   45,   46,   47,   48,   49,   50,
+       51,   24,    1,   52,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -608,2250 +822,2198 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst YY_CHAR yy_meta[54] =
+static const YY_CHAR yy_meta[53] =
     {   0,
-        1,    2,    2,    1,    2,    1,    1,    3,    2,    4,
-        5,    6,    6,    6,    6,    6,    6,    6,    7,    3,
-        3,    3,    8,    4,    9,    3,    1,    4,    8,    8,
-        8,    8,    8,    8,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        9,    4,    3
+        1,    2,    2,    1,    2,    1,    1,    1,    2,    3,
+        4,    5,    5,    5,    5,    5,    5,    5,    6,    1,
+        1,    1,    7,    3,    8,    1,    3,    7,    7,    7,
+        7,    7,    7,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    8,
+        3,    1
     } ;
 
-static yyconst flex_uint16_t yy_base[2189] =
+static const flex_int16_t yy_base[2184] =
     {   0,
-        0,    0, 5455,   53, 7856, 7856,   57, 5433,   64,   81,
-     5445, 7856, 7856,   99,   30,  151,   46, 5430,   52,  168,
-      210,  168,  160,   44,  125,   60,   31,   58,  132,  170,
-      214,  217,  229,   59,  170,  222,  237,  243,  250, 5418,
-      255, 5410, 5380,  300, 7856,    0, 7856,  316,  339,  363,
-     5413,  387,    0,  394,    0,  428, 7856, 7856, 7856, 7856,
-     7856,  296,  316,    0, 5386, 5383, 5397,    0, 5395, 5383,
-     5396, 5378, 5366, 5360, 5361, 5362, 5360, 5344, 5352, 5337,
-     5350, 5331,  116, 5341, 5312, 5297, 5295, 5299, 5305, 5294,
-     5299, 5279, 5278,   56,   68, 5263, 5261,   80, 5265, 5259,
+        0,    0, 6066, 7626, 7626, 7626, 6044,    0, 7626, 6056,
+       43,   70, 6044,   43, 6040,   75,  110,  151,    0,   70,
+       85,  102,   67,   61,   77,  105,  113,  155,  158,  170,
+       70,  176,  165,  110,  189,  148, 6025,  184, 6016, 6001,
+     7626,    0, 7626,  225,  247,  270, 6030,  293,    0,  300,
+        0,  322, 7626, 7626, 7626, 7626, 7626,  344,    0, 6003,
+     6000, 6013,    0, 6008, 5996, 6007, 6001, 5986, 5960, 5946,
+     5947, 5946, 5939, 5948, 5923, 5926, 5906,  284, 5907, 5907,
+     5875, 5868, 5857, 5849, 5816, 5811, 5801, 5794,   89,   81,
+     5765, 5752,  109, 5704, 5698, 5705,  123,  211,    0,    0,
 
-     5267,   68,  166,    0,    0,   15,  122, 5255, 5264,  189,
-     5238, 5236, 5219, 5222, 5212, 5219, 5209, 5208, 5214,    0,
-     5212,    0, 5195, 5181, 5175, 5176, 5175, 5174,  128, 5185,
-     5168, 5167, 5160,  159, 5147,  201, 5144,   38, 5137, 5149,
-        0, 5133,    0, 5112, 5111, 5094, 5090, 5078, 5048, 5062,
-     7856, 7856,  453,  477,  236,  518,  542,  566, 5071,  573,
-     5078,  597,  248, 5054, 5029, 5034, 5025,    0,    0, 5030,
-        0, 5038, 5033, 5022, 5006, 5007, 5004, 5005, 5012,    0,
-        0, 5006, 4996,    0, 5008, 4988, 4976, 4990, 4989, 4992,
-     4988, 4972, 4971, 4953, 4969, 4952, 4956, 4951, 4952, 4965,
+       99,  168, 5686, 5695,  204, 5676, 5656, 5659, 5635, 5624,
+     5610, 5600, 5591, 5597,    0, 5584,    0, 5567, 5573, 5567,
+     5568, 5567, 5567,  200, 5549, 5532, 5543, 5536,  131, 5532,
+      327, 5519,  194, 5518, 5530,    0, 5513,    0, 5510, 5509,
+     5514, 5488, 5479, 5467, 5482, 7626, 7626,  363,  386,  180,
+      426,  449,  472, 5475,  479, 5482,  502,  241, 5472, 5446,
+     5430, 5421,    0,    0, 5426,    0, 5435, 5430, 5419, 5413,
+     5414, 5374, 5375, 5382,    0,    0, 5377, 5366,    0, 5378,
+     5373, 5346, 5360, 5359, 5362, 5358, 5342, 5325, 5321, 5337,
+     5319, 5304, 5299, 5300, 5294, 5277, 5257,    0, 5262, 5254,
 
-     4950, 4934,    0, 4939, 4933,    0,    0, 4937, 4927,    0,
-     4938,    0, 4935, 4907, 4912,    0,    0, 4901,    0, 4909,
-     4917,  244, 4899,    0, 4887, 4882,    0, 4877,    0, 4880,
-        0, 4861, 4864, 4857, 4845, 4850, 4843, 4839,    0, 4837,
-     4849,    0, 4838,    0, 4837,    0,    0,    0, 4819,    0,
-      153,  156, 4830,    0,    0, 4821,    0, 4818, 4818,  637,
-     4847,  660,  684, 4830,  691,  500,  281,  715, 4821,  739,
-     4820, 4819,  747,  290, 4818, 4816,  507,  788,  811, 4815,
-        0,    0, 4775,  350, 4778, 4783,    0,    0,    0, 4781,
-        0, 4777, 4762, 4746,    0, 4746,    0, 4740, 4739, 4740,
+        0,    0, 5258, 5216,    0, 5226,    0, 5222, 5191, 5196,
+        0,    0, 5166,    0, 5175, 5182,  201, 5163,    0, 5146,
+     5161,    0, 5156,    0, 5138,    0, 5120, 5123, 5116, 5101,
+     5085, 5076, 5053,    0, 5051, 5062,    0, 5051,    0, 5018,
+        0,    0,    0, 5013,    0,  223,  240, 5023,    0,    0,
+     5014,    0, 5011, 5001,  541, 5010,  563,  586, 5006,  593,
+      352,  260,  616, 4996,  639, 4995, 4994,  647,  271, 4982,
+     4961,  408,  687,  709, 4960,    0,    0, 4936,  374, 4937,
+     4930,    0,    0,    0, 4927,    0, 4924, 4925, 4908,    0,
+     4908,    0, 4900, 4900, 4901,    0, 4886, 4853,    0,    0,
 
-        0, 4722, 4721,    0,    0,    0,    0,    0,  614, 4728,
-        0,    0, 4736, 4715, 4700,    0,    0, 4698,    0,    0,
-        0,    0, 4713, 4704, 4710,    0, 4703, 4706, 4707, 4679,
-     4675, 4667, 4639,    0, 4632,    0, 4607,    0,  275,    0,
-        0, 4599, 4592,  817, 4585,    0,    0,    0,  856,  880,
-      293,  921, 4610, 4608,  405,  944,  968,  992, 4598,  999,
-      621, 4581, 4579, 1022,  770, 1046, 1069, 4562,    0, 4553,
-      427,  428, 1093, 4552, 1117,  333, 4551, 4550, 4519,    0,
-        0,    0,    0, 4491,    0, 4504, 4502, 4469, 4460,    0,
-     4477, 4472, 4463,    0,    0, 1136,  293, 4453, 4420, 4437,
+        0,    0,    0,  519, 4858,    0,    0, 4865, 4847, 4830,
+        0,    0, 4825,    0,    0,    0,    0, 4825, 4789, 4790,
+        0, 4783, 4765, 4780, 4751, 4727, 4737, 4726,    0, 4708,
+        0, 4707,    0,  250,    0,    0, 4699, 4693,  715, 4688,
+        0,    0,    0,  753,  776,  272,  816, 4714, 4712,  360,
+      838,  861,  884, 4702,  891,  415, 4683, 4681,  913,  526,
+      936,  958, 4661,    0, 4660,  423,  511,  981, 4658, 1004,
+      294, 4657, 4664, 4602,    0,    0,    0,    0, 4596,    0,
+     4609, 4586, 4548, 4528,    0, 4543, 4537, 4517,    0,    0,
+     1023,  516, 4506, 4494, 4497,    0, 4487,    0, 4491, 4483,
 
-        0, 4427,    0, 4429, 4422,    0,    0, 4420, 4394,  292,
-     4393, 4411,  387, 4408,    0, 4390, 4382, 4394, 4368, 4362,
-     4372, 4350, 4357, 4338, 4317, 4318, 4310, 4278, 4292, 1173,
-     4310, 1196, 1220, 4305, 1227,  777,  285, 1251,  334, 1291,
-     1314, 1338, 4294, 4293, 1346,  336, 4291, 4256, 4255, 4254,
-     1387,  363, 4252, 4251,  515,  631, 1428, 4250, 1452,  364,
-     4240, 4247, 4218,  840,    0,  371, 4214,  903, 1493, 1516,
-     4212,    0,    0, 4184, 4200, 4149,    0, 4158, 4140,    0,
-     4145, 4158, 4143, 4126, 4125,  380, 4109,  427, 4108, 1121,
-     4106, 4095, 4082, 4067, 4076,    0, 4066, 4077, 4025, 4028,
+        0,    0, 4492, 4457,  515, 4455, 4456,   73, 4451,    0,
+     4439, 4431, 4407, 4381, 4373, 4360, 4340, 4356, 4349, 4320,
+     4320, 4311, 4299, 4314, 1059, 4328, 1081, 1104, 4313, 1111,
+      669,  313, 1134,  324, 1173, 1195, 1218, 4295, 4286, 1226,
+      357, 4257, 4198, 4197, 4194, 1266,  358, 4193, 4160,  663,
+      683, 1306, 4159, 1329,  420, 4155, 4161, 4135,  737,    0,
+      394, 4134,  798, 1369, 1391, 4131,    0,    0, 4104, 4088,
+     4065,    0, 4055, 4039,    0, 4043, 4056, 4009, 4022, 4020,
+      703, 4005,  728, 3990, 1008, 3987, 3974, 3993, 3981, 3960,
+        0, 3948, 3958, 3949, 3954, 3942, 3911, 3908,    0,    0,
 
-     4026, 4015, 4014,    0,    0, 4018,    0, 3981, 3973, 3986,
-     3984, 3976, 3949, 3960, 3929, 3923, 3918, 3909, 3888, 3885,
-     1541, 1565,  423, 1606, 3892, 3888,  633, 1630, 1654, 1661,
-     1685, 3877, 1692, 1716, 1739, 3876, 3857, 3856, 1762,  910,
-     1786, 1809, 3852,    0, 1274,    0,  461, 3837, 1281, 1833,
-     1856, 3833,    0,  785,  824, 3820,  485,  853,  856, 1880,
-     3810, 1904,  424, 3809, 3798,  529, 3762, 3765, 3739,    0,
-        0, 3742, 3729, 3715, 3691, 3703, 3683, 3666, 3672, 3664,
-     3643, 3632, 3633, 3619, 3601,   56,  504,  646, 3609, 3575,
-     3584, 3582,    0, 3573, 3567,    0,    0,    0, 3580, 3552,
+     3911,    0, 3906, 3898, 3900, 3879, 3869, 3860, 3860, 3850,
+     3807, 3804, 3806, 3787, 3786, 1415, 1438,  421, 1478, 3779,
+     3765,  684, 1501, 1524, 1531, 1554, 3739, 1561, 1584, 1606,
+     3737, 3734, 3689, 1628,  805, 1651, 1673, 3668,    0, 1156,
+        0,  571, 3646, 1163, 1696, 1718, 3644,    0,  747,  750,
+     3651,  601,  813,  832, 1741, 3625, 1764,  425, 3624, 3631,
+      490, 3594, 3581, 3577,    0,    0, 3563, 3565, 3533, 3532,
+     3544, 3526, 3506, 3494, 3485, 3484, 3476, 3476, 3463, 3448,
+      227,  998, 1009, 3455, 3441, 3429, 3411,    0, 3398, 3371,
+        0,    0,    0, 3384, 3362, 3367, 3353,    0,    0,    0,
 
-     3533, 3519,    0,    0,    0,    0,    0, 3523,    0,    0,
-        0, 3512, 1944, 3547, 1967, 1991, 3514, 1998,  325, 2022,
-     2046, 2053, 2077, 3505, 3474, 2085,  452, 3434, 2126,  476,
-     3393, 3386, 3385, 3365, 2167,  513, 3345,  918,  938, 2208,
-     3344, 2232,  542, 3343, 3348, 1142, 1149, 3347, 3314, 1167,
-     1169, 2273, 3305, 2297,  543, 3304, 3310, 1369,    0, 1376,
-        0,  486, 3282, 1410, 2338, 2361, 3278,    0, 2384,  374,
-      115,  389,  150,  672,  205,  610, 3235,  550,  403,  313,
-      783,  553,  761,  522,  800,  451,  578,  893,  633,  829,
-      571, 1108, 1112, 3231, 3228, 1123, 3206, 3189, 1130, 1128,
+        0,    0, 3357,    0,    0,    0, 3346, 1803, 3358, 1825,
+     1848, 3356, 1855,  330, 1878, 1901, 1908, 1931, 3347, 3346,
+     1939,  426, 3343, 1979,  449, 3342, 3324, 3323, 3321, 2019,
+      498, 3320, 1031, 1035, 2059, 3319, 2082,  538, 3318, 3295,
+     1053, 1055, 3294, 3290, 1172, 1236, 2122, 3262, 2145,  564,
+     3261, 3267, 1250,    0, 1257,    0,  624, 3237, 1288, 2185,
+     2207, 3236,    0, 2229,  301,  407,  302,  246, 1012,  522,
+      700, 3191,  539,   19,  538,  661,  569,  790,  650,  682,
+      406,  757, 1015,  834,  887,  454,  999, 1054, 3189, 3188,
+     1168, 3186, 3184, 1214, 1017,  571, 3166, 3164, 2266, 2289,
 
-      593, 3186, 3185, 2422, 2459, 2495, 2531,  634, 2555,  258,
-     2563, 2587, 3194, 2594, 2618, 2641, 3193, 2665, 2688, 3191,
-     3188, 3185, 2711, 1417, 2735, 2758, 3184,    0, 1475,    0,
-      723, 3172, 1482, 2782, 2805, 3147,    0, 1588,    0, 1595,
-        0,  724, 3146, 1927, 2829, 2852, 3135,    0,  661, 1934,
-     3122, 1290, 1425, 3114, 3111, 1490, 1510, 2876, 3101, 2900,
-      662, 3090, 3061,  636,  803,  653, 1290, 1427, 1492, 2095,
-     1604,  708,  849,  937, 2122,  872, 1605, 1944,  804, 1187,
-     1242, 2099,  936,  960, 1532, 2101,  874,  938, 1015,  962,
-     1014, 2124, 2163, 2942, 1016, 2965, 1038, 2988, 2154, 3012,
+     2311, 2346,  617, 2369,  625, 2377, 2400, 3178, 2407, 2430,
+     2452, 3168, 2475, 2497, 3167, 3163, 3133, 2519, 1295, 2542,
+     2564, 3130,    0, 1351,    0, 1119, 3105, 1358, 2587, 2609,
+     3104,    0, 1460,    0, 1467,    0, 1142, 3103, 1786, 2632,
+     2654, 3093,    0,  706, 1793, 3078, 1303, 1366, 3075, 3071,
+     1385, 1415, 2677, 3052, 2700,  752, 3042, 3048,  518,  854,
+      663, 1172, 1305, 1368, 1949, 1476,  907,  832,  930, 1974,
+      702, 1477, 1803,  951, 1950, 1951, 1953,  974,  953, 1990,
+     1993,  769,  831,  952,  997, 1074, 2013, 2018, 2741, 1127,
+     2763, 1407, 2785, 2046, 2808, 2831, 3037, 3005, 2839,  810,
 
-     3036, 3052, 3051, 3044,  686, 3049, 3085,  967, 3047, 3126,
-      969, 3046, 3045, 3020, 3017, 3167,  970, 2967, 1541, 1733,
-     3208, 2966, 3232, 1022, 2947, 2953, 2096, 2163, 2951, 2950,
-     2164, 2182, 3273, 2909, 3297, 1042, 2908, 2915, 1043, 2255,
-     2913, 2183, 2184, 2911, 2892, 2205, 2249, 3338, 2882, 3362,
-     1045, 2881, 2886,    0, 2263,    0, 2320,    0,  756, 2857,
-     2327, 3403, 3426, 2853,    0, 1061, 1062, 1087, 1111, 2337,
-     1188, 1943, 1189, 1244, 2376, 1534, 2377, 2336, 1109, 1243,
-     2402, 2013, 1306, 2096, 2378, 1446, 2375, 1245, 3451, 3474,
-     3498, 1066, 3538, 3562, 3586, 2834, 3593, 3617, 3640, 2830,
+     3004, 2879,  860, 3001, 2919,  861, 2986, 2985, 2983, 2964,
+     2959,  862, 2961, 1600, 2016, 2999, 2960, 3022,  888, 2927,
+     2932, 2054, 2056, 2930, 2929, 2092, 2097, 3062, 2920, 3085,
+      978, 2908, 2895, 1058, 2111, 2892, 2119, 2155, 2890, 2889,
+     2156, 2160, 3125, 2880, 3148, 1081, 2868, 2855,    0, 2174,
+        0, 2251,    0, 1486, 2846, 2318, 3188, 3210, 2844,    0,
+     1188, 1323, 1432, 1577, 2184, 1578, 1802, 1621, 1622, 2243,
+     1645, 2244, 2058, 1666, 1689, 2155, 2329, 1870, 2710, 2246,
+     1668, 2202, 1384, 3234, 3256, 3279, 1082, 3318, 3341, 3364,
+     2842, 3371, 3394, 3416, 2841, 3439, 3461, 2840, 3484, 3506,
 
-     3664, 3687, 2811, 3711, 3734, 2810, 2806, 2791, 3757, 2445,
-     3781, 3804, 2789,    0, 2482,    0, 1008, 2787, 2502, 3828,
-     3851, 2744,    0, 2509,    0, 2516,    0, 1153, 2741, 2523,
-     3875, 3898, 2740,    0,    0, 2923,    0, 2930,    0, 1300,
-     2718, 3067, 3922, 3945, 2717,    0,    0, 1198, 3074, 2724,
-     2399, 2417, 2721, 2701, 2453, 2454, 3969, 2670, 3993, 1285,
-     2649, 2655, 2401, 2438, 3083, 2398, 1558, 2457, 2940, 1708,
-     3084, 1557, 1385, 1709, 1508, 1754, 1710, 1755, 1778, 3120,
-     1779, 3118, 1801, 1803, 1825, 4035, 4059, 4068, 1826, 2646,
-     2643, 4086, 1287, 2624, 4127, 1288, 2600, 4168, 1315, 2599,
+     2815, 2813, 2811, 3528, 2328, 3551, 3573, 2810,    0, 2335,
+        0, 1539, 2790, 2726, 3596, 3618, 2786,    0, 2861,    0,
+     2868,    0, 1863, 2766, 2901, 3641, 3663, 2728,    0,    0,
+     2908,    0, 2941,    0, 1916, 2708, 2948, 3686, 3708, 2707,
+        0,    0, 1108, 2981, 2713, 2263, 2266, 2692, 2691, 2446,
+     2491, 3731, 2682, 3754, 1110, 2680, 2686, 2245, 2328, 2958,
+     2327, 1712, 2738, 2976, 1711, 2998, 2725, 1734, 1758, 1757,
+     2777, 1818, 1955, 1431, 2694, 1871, 3016, 1956, 1995, 2121,
+     3795, 3818, 3827, 2222, 2660, 2659, 3844, 1167, 2655, 3884,
+     1169, 2637, 3924, 1170, 2635, 3964, 1301, 2616, 2614, 2592,
 
-     4209, 1345, 2597, 2596, 2595, 4249, 4273, 1427, 2594, 2635,
-     2682, 4314, 2572, 4338, 1429, 2571, 2578, 2938, 2942, 2577,
-     2576, 3096, 3142, 4379, 2566, 4403, 1489, 2540, 2544, 1600,
-     3156, 2542, 3151, 3164, 2541, 2540, 3183, 3184, 4444, 2531,
-     4468, 1603, 2468, 2469,    0, 1605, 3255, 2438, 3203, 3205,
-     2372, 2371, 3249, 3268, 4509, 2343, 4533, 1606, 2341, 2348,
-        0, 3320,    0, 3327,    0, 1396, 2306, 3385, 4574, 4597,
-     2299,    0, 3095, 3096, 3178, 1827, 3122, 2399, 1848, 3420,
-     2959, 1849, 1850, 1872, 3248, 3380, 1874, 1896, 3490, 2014,
-     3492, 1959, 2016, 3337, 4622, 4646, 4655, 2275, 4672, 4696,
+     4003, 4026, 1306, 2572, 2711, 2738, 4066, 2570, 4089, 1365,
+     2569, 2558, 2956, 2996, 2555, 2553, 3033, 3037, 4129, 2527,
+     4152, 1412, 2525, 2513, 1475, 3051, 2510, 3059, 3095, 2508,
+     2488, 3096, 3100, 4192, 2478, 4215, 1477, 2460, 2465,    0,
+     1501, 3114, 2463, 3122, 3158, 2462, 2441, 3159, 3163, 4255,
+     2413, 4278, 1503, 2412, 2418,    0, 3177,    0, 3301,    0,
+     1962, 2409, 3308, 4318, 4340, 2408,    0, 3158, 3764, 3765,
+     2223, 3078, 3317, 2283, 3204, 2735, 2423, 2424, 2224, 3768,
+     3318, 2445, 2282, 3837, 2490, 3839, 2468, 2513, 3771, 4364,
+     4387, 4396, 2384, 4412, 4435, 4457, 2383, 4480, 4502, 2380,
 
-     4719, 2263, 4743, 4766, 2239, 4790, 4813, 2234, 4837, 4860,
-     2198, 2194, 4884, 1630, 2192, 2145, 3523, 4925, 2144, 2107,
-        0, 3530,    0, 1615, 2106, 4016, 4949, 2103, 2060,    0,
-     4023,    0, 4075,    0, 1639, 2059, 4109, 4973, 2058, 2055,
-        0,    0, 4116,    0, 4150,    0, 1669, 2000, 4157, 4997,
-     1999, 1976,    0,    0, 4191,    0, 4198,    0, 1748, 1951,
-     4232, 5021, 1945, 1913,    0,    0, 1660, 4239, 1917, 3335,
-     3399, 1914, 1897, 3400, 3420, 5045, 1882, 5069, 1661, 1842,
-     1846, 2102, 2177, 2200, 2289, 2103, 2612, 4283, 2226, 2473,
-     4266, 2680, 4348, 4267, 4331, 3249, 3271, 4289, 4332, 3399,
+     4525, 4547, 2349, 4570, 4592, 2348, 2347, 4615, 1530, 2296,
+     2289, 3869, 4655, 2212, 2209,    0, 3906,    0, 1995, 2208,
+     3913, 4678, 2188, 2164,    0, 3946,    0, 3953,    0, 2005,
+     2160, 3986, 4701, 2153, 2130,    0,    0, 3993,    0, 4048,
+        0, 2035, 2101, 4055, 4724, 2100, 2097,    0,    0, 4111,
+        0, 4118,    0, 2385, 2067, 4174, 4747, 2064, 2037,    0,
+        0, 1531, 4181, 2014, 3204, 3410, 2010, 2008, 3455, 3500,
+     4770, 1996, 4793, 1532, 1960, 1964, 2512, 2535, 2557, 2580,
+     2558, 2604, 4225, 2602, 2603, 4209, 2800, 4288, 3838, 4272,
+     3861, 4002, 4065, 4608, 3843, 2626, 2648, 4609, 4834, 1955,
 
-     2610, 2611, 4396, 5111, 1815, 5128, 5152, 1662, 1814, 5193,
-     1689, 1811, 5234, 1736, 1795, 5275, 1879, 1791, 5316, 1880,
-     1747, 1744, 4365, 5357, 1741, 1698,    0, 1697, 3634, 3681,
-     5381, 1670, 1664, 1671, 3728, 4289, 1616, 1580, 4374, 4418,
-     5405, 1568, 1565, 1552, 1938, 4432, 1527, 4441, 4478, 1508,
-     1506, 4479, 4483, 5429, 1494, 1454, 1442,    0, 1940, 4497,
-     1438, 4506, 4543, 1437, 1400, 4544, 4548, 5453, 1390, 1389,
-     1363,    0, 1941, 4562, 1362, 4571, 4591,   83,  110, 4666,
-     4667, 5477,  195,  198,  225,    0, 4907,    0, 4914,    0,
-     2006,  307, 5092, 5501,    0,  348,    0, 2474, 2635, 2657,
+     4850, 4873, 1558, 1915, 4913, 1602, 1914, 4953, 1648, 1913,
+     4993, 1695, 1911, 5033, 1715, 1910, 1909, 4241, 5073, 1880,
+     1806,    0, 1804, 3769, 4002, 5096, 1767, 1747, 1707, 4063,
+     4126, 1706, 1686, 4189, 4250, 5119, 1658, 1652, 1622, 1738,
+     4304, 1619, 4314, 4334, 1617, 1615, 4406, 4407, 5142, 1587,
+     1567, 1574,    0, 1797, 4639, 1541, 4409, 4411, 1511, 1510,
+     4451, 4496, 5165, 1480, 1479, 1446,    0, 1799, 4646,  121,
+     4541, 4803,  145,  164, 4804, 4806, 5188,  168,  308,  373,
+        0, 4820,    0, 4895,    0, 3038,  393, 4902, 5211,    0,
+      450,    0, 2649, 2671, 2757, 2779, 2801, 4803, 4830, 4912,
 
-     2659, 2681, 3003, 5107, 5162, 4670, 2703, 4291, 4356, 2682,
-     4376, 4923, 4443, 2728, 2729, 5108, 5163, 5525, 1943,    0,
-      372, 5566,    0,  399, 5590,    0,  418, 5614,    0,  480,
-     5638,    0,  520, 5662,    0,  544, 4671, 4713, 5686,  551,
-      580,  582,  610,  604, 5180,    0, 2061,  624,  643, 5216,
-        0, 5223,    0, 2062,  696,  697,    0, 5257,    0, 5264,
-        0, 2109,  698,  720,    0, 5298,    0, 5305,    0, 2142,
-      721,  749,    0, 5339,    0, 5346,    0, 2193,  750,  752,
-        0, 1995, 5548,  762, 4760, 4807,  763,  798, 4854, 5086,
-     5710,  793,    0,  804, 4508, 2751, 2752, 2774, 2775, 5146,
+     4128, 3124, 4191, 4317, 3226, 4831, 4930, 4411, 2780, 3250,
+     4832, 4924, 5234, 1802,    0,  505, 5274,    0,  532, 5297,
+        0,  548, 5320,    0,  568, 5343,    0,  600, 5366,    0,
+      618, 4849, 4910, 5389,  619,  621,  622,  657,  650, 4975,
+        0, 3264,  672,  673, 4982,    0, 5015,    0, 3379,  692,
+      755,    0, 5022,    0, 5055,    0, 3777,  759,  761,    0,
+     5062,    0, 5256,    0, 3778,  779,  818,    0, 5263,    0,
+     5411,    0, 3782,  821,  864,    0, 1826, 5418,  904, 5070,
+     5271,  905,  924, 5426, 5427, 5467,  918,    0,  945, 5072,
+     3410, 3455, 3249, 3272, 5429, 2878, 3387, 3432, 3454, 5430,
 
-     2776, 2799, 2822, 2823, 5720, 2845, 5703, 5722, 2846, 3270,
-     3489, 5755,  820,  864,    0,    0,    0,    0,    0,    0,
-     5555,    0, 2282,  880,  887,    0, 5127, 5354,  897,  930,
-        0, 1997, 5739,  931, 5563, 5724,  934,  976,    0,    0,
-     2024, 5778,  985, 5752, 5772, 1012, 1039,    0,    0, 2151,
-     5792, 1063, 5787, 5788, 1102, 1103,    0,    0, 2181, 5802,
-     1107, 5800, 5810, 1132, 1160,    0,    0, 5814,    0, 5828,
-        0, 2347, 1176,    0, 5085, 3553, 2868, 2870, 3103, 5824,
-     5827, 5837, 5838, 5839, 5826, 3379, 5843, 2892, 4573, 5736,
-     2981,    0, 7856,    0,    0,    0,    0,    0,    0, 5845,
+     3499, 5431, 5432, 3409, 4313, 5433, 5490,  939,  983,    0,
+        0,    0,    0,    0,    0, 5432,    0, 4230,  986,  987,
+        0, 5442, 5462, 1014, 1015,    0, 1850, 5512, 1046, 5464,
+     5506, 1068, 1091,    0,    0, 1852, 5520, 1125, 5528, 5529,
+     1144, 1145,    0,    0, 1854, 5529, 1182, 5537, 5538, 1210,
+     1237,    0,    0, 1993, 5552, 1239, 5546, 5547, 1241, 1242,
+        0,    0, 5568,    0, 5577,    0, 4231, 1268,    0, 4927,
+     5588, 5590, 2918, 3500, 5589, 5592, 5593, 5594, 5595, 5591,
+     3545, 5596, 3567, 5273, 5599, 3522,    0, 7626,    0,    0,
+        0,    0,    0,    0, 5622, 5624, 1277, 1279,    0, 7626,
 
-     5847, 1190, 1235,    0, 7856, 5871,    0, 7856,    0, 5887,
-        0, 7856,    0, 5894,    0, 7856,    0, 5901,    0, 7856,
-        0, 5908,    0, 7856,    0, 2270, 5915, 1236, 5923, 5924,
-     1237, 2414,    0, 2980, 5086, 2982, 3004, 5926, 5356, 5565,
-     3201, 5849, 4287, 3005, 5927, 5106, 5850, 3006, 5928,    0,
-     5927,    0, 2272, 5954, 1240,    0, 2273, 5964, 1264,    0,
-     2338, 5971, 1306,    0, 2396, 5978, 1322,    0, 2531, 5985,
-     1356,    0, 5992,    0, 7856, 3177, 6001, 3442, 3444, 3467,
-     6002, 6004, 6005, 6008, 3491, 6006, 3378, 6007, 2532, 6007,
-     1357,    0,    0,    0,    0,    0,    0, 2533, 6043, 1361,
+     5627,    0, 7626,    0, 5638,    0, 7626,    0, 5645,    0,
+     7626,    0, 5652,    0, 7626,    0, 5663,    0, 7626,    0,
+     2030, 5670, 1281, 5678, 5679, 1282, 4293,    0, 3544, 5681,
+     3589, 3590, 5682, 5685, 5686, 3611, 5687, 5688, 3613, 5683,
+     5690, 5695, 3656, 5684,    0, 5730,    0, 2059, 5737, 1316,
+        0, 2093, 5744, 1319,    0, 2096, 5751, 1378,    0, 2159,
+     5758, 1382,    0, 2347, 5765, 1402,    0, 5772,    0, 7626,
+     3657, 5689, 3658, 3680, 3702, 5781, 5783, 5784, 5696, 3703,
+     5785, 3679, 5786, 2348, 5785, 1425,    0,    0,    0,    0,
+        0,    0, 2376, 5802, 1428, 5795, 5797, 5697, 5796, 3724,
 
-     6016, 6037, 5852, 6039, 3554, 6040, 3555, 3556, 6017, 6052,
-     6056, 3419,    0,    0,    0,    0,    0,    0,    0, 3466,
-     6059, 3611, 3658, 3705, 6060, 6062, 6063, 3468, 6065, 6066,
-        0,    0, 3609, 3610, 3634, 3656, 6067, 3680, 6068, 3681,
-     6073, 6082, 6092, 6095, 3727, 6101, 3728, 6103, 3749, 5102,
-     3773, 3774, 3797, 6106, 6111, 6115, 3775, 6116, 6122, 3820,
-     6123, 6126, 6128, 3822, 6114, 6142, 6148, 3844, 3845, 6152,
-     6153, 6154, 6155, 3869, 3890, 6158, 3891, 6162, 3914, 6163,
-     6167, 3915, 3916, 3938, 6169, 6177, 4737, 6191, 3939, 6182,
-     6194, 6197, 6198, 3961, 6204, 6203, 6205, 3963, 6206, 3985,
+     5815, 3725, 4083, 5817, 5818, 5821, 3701,    0,    0,    0,
+        0,    0,    0,    0, 3790, 5824, 4254, 4563, 5825, 5826,
+     5828, 5830, 3841, 5833, 5840,    0,    0, 3881, 4356, 4450,
+     4473, 5839, 4496, 5849, 3883, 5855, 5859, 5861, 5862, 4250,
+     5873, 4406, 5851, 4540, 5874, 4585, 4541, 4586, 5877, 5875,
+     5881, 5880, 5899, 5883, 4671, 5886, 5905, 5906, 3923, 5908,
+     5909, 5912, 4672, 4695, 5919, 5930, 5920, 5931, 4718, 4741,
+     5933, 3963, 5935, 4763, 5934, 5938, 4764, 4252, 5090, 5943,
+     5953, 5956, 5961, 5112, 5958, 5962, 5967, 5971, 4587, 5981,
+     5982, 5983, 5113, 5987, 4866, 5136, 5990, 4992, 5991, 5995,
 
-     4084, 6213, 3987, 6218, 6227, 4125, 4613, 6219, 4308, 4032,
-     6228, 4033, 4615, 4085, 6238, 6229, 6240, 4784, 4166, 6239,
-     4207, 6241, 6268, 4208, 4665, 4666, 4669, 7856, 6296, 6304,
-     6308, 6311, 6314, 6317, 6320, 6323, 6326, 6329, 6332, 6335,
-     6338, 6341, 6344, 6347, 6350, 6353, 6356, 6360, 6364, 6367,
-     6370, 6373, 6376, 6379, 6382, 6385, 6388, 6392, 6396, 6399,
-     6402, 6406, 6408, 6411, 6414, 6417, 6420, 6423, 6426, 6429,
-     6432, 6436, 6438, 6441, 6445, 6450, 6454, 6457, 6461, 6464,
-     6467, 6470, 6473, 6476, 6479, 6482, 6486, 6490, 6493, 6497,
-     6501, 6506, 6510, 6512, 6516, 6519, 6523, 6526, 6529, 6533,
+     5158, 5159, 6001, 5205, 5032, 6002, 5204, 5228, 5227, 6005,
+     6006, 6015, 6009, 5291, 6014, 5313, 6016, 6045, 5314, 5336,
+     5337, 5359, 7626, 6068, 6075, 6079, 6082, 6085, 6088, 6091,
+     6094, 6097, 6100, 6103, 6106, 6109, 6112, 6115, 6118, 6121,
+     6124, 6127, 6131, 6135, 6138, 6141, 6144, 6147, 6150, 6153,
+     6156, 6159, 6163, 6167, 6170, 6173, 6177, 6179, 6182, 6185,
+     6188, 6191, 6194, 6197, 6200, 6203, 6207, 6209, 6212, 6216,
+     6221, 6225, 6228, 6232, 6235, 6238, 6241, 6244, 6247, 6250,
+     6253, 6257, 6261, 6264, 6268, 6272, 6277, 6281, 6283, 6287,
+     6290, 6294, 6297, 6300, 6304, 6306, 6309, 6312, 6315, 6318,
 
-     6535, 6538, 6541, 6544, 6547, 6550, 6553, 6556, 6559, 6562,
-     6566, 6568, 6571, 6574, 6577, 6581, 6583, 6586, 6589, 6594,
-     6598, 6603, 6607, 6609, 6613, 6616, 6620, 6625, 6629, 6632,
-     6635, 6638, 6641, 6644, 6647, 6650, 6654, 6658, 6661, 6665,
-     6669, 6674, 6678, 6680, 6684, 6687, 6691, 6694, 6699, 6703,
-     6708, 6712, 6714, 6718, 6721, 6725, 6728, 6731, 6734, 6738,
-     6740, 6743, 6748, 6752, 6755, 6758, 6761, 6764, 6767, 6770,
-     6773, 6776, 6780, 6782, 6785, 6788, 6791, 6795, 6797, 6800,
-     6803, 6806, 6809, 6813, 6815, 6818, 6821, 6824, 6829, 6833,
-     6838, 6842, 6844, 6848, 6851, 6855, 6860, 6864, 6867, 6870,
+     6321, 6324, 6327, 6330, 6333, 6337, 6339, 6342, 6345, 6348,
+     6352, 6354, 6357, 6360, 6365, 6369, 6374, 6378, 6380, 6384,
+     6387, 6391, 6396, 6400, 6403, 6406, 6409, 6412, 6415, 6418,
+     6421, 6425, 6429, 6432, 6436, 6440, 6445, 6449, 6451, 6455,
+     6458, 6462, 6465, 6470, 6474, 6479, 6483, 6485, 6489, 6492,
+     6496, 6499, 6502, 6505, 6509, 6511, 6514, 6519, 6523, 6526,
+     6529, 6532, 6535, 6538, 6541, 6544, 6547, 6551, 6553, 6556,
+     6559, 6562, 6566, 6568, 6571, 6574, 6577, 6580, 6584, 6586,
+     6589, 6592, 6595, 6600, 6604, 6609, 6613, 6615, 6619, 6622,
+     6626, 6631, 6635, 6638, 6641, 6644, 6647, 6650, 6653, 6656,
 
-     6873, 6876, 6879, 6882, 6885, 6889, 6893, 6896, 6900, 6904,
-     6909, 6913, 6915, 6919, 6922, 6926, 6929, 6934, 6938, 6943,
-     6947, 6949, 6953, 6956, 6960, 6963, 6966, 6971, 6975, 6980,
-     6984, 6986, 6990, 6993, 6997, 7000, 7003, 7006, 7010, 7012,
-     7015, 7020, 7024, 7027, 7030, 7033, 7036, 7039, 7042, 7045,
-     7048, 7051, 7054, 7057, 7061, 7063, 7066, 7069, 7072, 7075,
-     7079, 7081, 7084, 7087, 7090, 7093, 7096, 7100, 7102, 7105,
-     7108, 7111, 7114, 7117, 7121, 7123, 7126, 7129, 7132, 7135,
-     7140, 7144, 7149, 7153, 7155, 7159, 7162, 7166, 7171, 7175,
-     7178, 7181, 7184, 7187, 7190, 7193, 7196, 7199, 7202, 7206,
+     6660, 6664, 6667, 6671, 6675, 6680, 6684, 6686, 6690, 6693,
+     6697, 6700, 6705, 6709, 6714, 6718, 6720, 6724, 6727, 6731,
+     6734, 6737, 6742, 6746, 6751, 6755, 6757, 6761, 6764, 6768,
+     6771, 6774, 6777, 6781, 6783, 6786, 6791, 6795, 6798, 6801,
+     6804, 6807, 6810, 6813, 6816, 6819, 6822, 6825, 6828, 6832,
+     6834, 6837, 6840, 6843, 6846, 6850, 6852, 6855, 6858, 6861,
+     6864, 6867, 6871, 6873, 6876, 6879, 6882, 6885, 6888, 6892,
+     6894, 6897, 6900, 6903, 6906, 6911, 6915, 6920, 6924, 6926,
+     6930, 6933, 6937, 6942, 6946, 6949, 6952, 6955, 6958, 6961,
+     6964, 6967, 6970, 6973, 6977, 6981, 6984, 6988, 6992, 6997,
 
-     7210, 7213, 7217, 7221, 7226, 7230, 7232, 7236, 7239, 7243,
-     7246, 7251, 7255, 7260, 7264, 7266, 7270, 7273, 7277, 7280,
-     7283, 7288, 7292, 7297, 7301, 7303, 7307, 7310, 7314, 7317,
-     7320, 7325, 7329, 7334, 7338, 7340, 7344, 7347, 7351, 7354,
-     7357, 7360, 7364, 7366, 7369, 7372, 7377, 7381, 7384, 7387,
-     7390, 7393, 7396, 7399, 7402, 7405, 7408, 7411, 7414, 7418,
-     7422, 7425, 7428, 7432, 7435, 7438, 7442, 7444, 7447, 7450,
-     7454, 7456, 7459, 7462, 7465, 7469, 7471, 7474, 7477, 7480,
-     7484, 7486, 7489, 7492, 7495, 7499, 7501, 7504, 7507, 7512,
-     7516, 7521, 7525, 7527, 7531, 7534, 7538, 7543, 7547, 7550,
+     7001, 7003, 7007, 7010, 7014, 7017, 7022, 7026, 7031, 7035,
+     7037, 7041, 7044, 7048, 7051, 7054, 7059, 7063, 7068, 7072,
+     7074, 7078, 7081, 7085, 7088, 7091, 7096, 7100, 7105, 7109,
+     7111, 7115, 7118, 7122, 7125, 7128, 7131, 7135, 7137, 7140,
+     7143, 7148, 7152, 7155, 7158, 7161, 7164, 7167, 7170, 7173,
+     7176, 7179, 7182, 7185, 7189, 7193, 7196, 7199, 7203, 7206,
+     7209, 7213, 7215, 7218, 7221, 7225, 7227, 7230, 7233, 7236,
+     7240, 7242, 7245, 7248, 7251, 7255, 7257, 7260, 7263, 7266,
+     7270, 7272, 7275, 7278, 7283, 7287, 7292, 7296, 7298, 7302,
+     7305, 7309, 7314, 7318, 7321, 7324, 7327, 7330, 7333, 7336,
 
-     7553, 7556, 7559, 7562, 7565, 7568, 7571, 7575, 7577, 7580,
-     7584, 7589, 7593, 7594, 7597, 7602, 7606, 7611, 7615, 7616,
-     7619, 7622, 7627, 7631, 7636, 7640, 7641, 7644, 7647, 7652,
-     7656, 7661, 7665, 7666, 7669, 7672, 7677, 7681, 7686, 7690,
-     7691, 7694, 7697, 7700, 7704, 7706, 7711, 7715, 7718, 7721,
-     7724, 7727, 7730, 7733, 7737, 7742, 7746, 7747, 7750, 7753,
-     7756, 7759, 7762, 7765, 7768, 7771, 7774, 7777, 7782, 7786,
-     7789, 7792, 7795, 7799, 7803, 7807, 7811, 7815, 7818, 7821,
-     7825, 7828, 7831, 7834, 7837, 7840, 7844, 7847
+     7339, 7342, 7346, 7348, 7351, 7355, 7360, 7364, 7365, 7368,
+     7373, 7377, 7382, 7386, 7387, 7390, 7393, 7398, 7402, 7407,
+     7411, 7412, 7415, 7418, 7423, 7427, 7432, 7436, 7437, 7440,
+     7443, 7448, 7452, 7457, 7461, 7462, 7465, 7468, 7471, 7475,
+     7477, 7482, 7486, 7489, 7492, 7495, 7498, 7501, 7504, 7508,
+     7513, 7517, 7518, 7521, 7524, 7527, 7530, 7533, 7536, 7539,
+     7542, 7545, 7548, 7553, 7557, 7560, 7563, 7566, 7570, 7574,
+     7578, 7582, 7586, 7589, 7592, 7596, 7599, 7602, 7605, 7608,
+     7611, 7615, 7618
     } ;
 
-static yyconst flex_int16_t yy_def[2189] =
+static const flex_int16_t yy_def[2184] =
     {   0,
-     1728,    1, 1728, 1728, 1728, 1728, 1728, 1728, 1729, 1728,
-     1728, 1728, 1728, 1728,   14, 1728, 1728, 1728, 1728,   14,
-       20, 1730,   20,   20,   20,   20,   20,   20,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21, 1728, 1728, 1728, 1731, 1728,   21,   21,   20,
-     1732,   50,   21,   21,   21, 1728, 1728, 1728, 1728, 1728,
-     1728,   49, 1730, 1730,   52,   52,   52,   21,   21,   21,
-       21,   52,   21,   21,   52,   21,   21,   21,   52,   21,
-       21,   21,   21,   21,   52,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+     1723,    1, 1723, 1723, 1723, 1723, 1723, 1724, 1723, 1723,
+     1723,   11, 1723, 1723, 1723, 1723,   11,   17, 1725,   17,
+       17,   17,   17,   17,   17,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18, 1723,
+     1723, 1726, 1723,   18,   18,   17, 1727,   46,   18,   18,
+       18, 1723, 1723, 1723, 1723, 1723, 1723,   45, 1725,   48,
+       48,   48,   18,   18,   18,   18,   48,   18,   18,   48,
+       18,   18,   18,   48,   18,   18,   18,   18,   18,   48,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-     1728, 1728,   21,   21,  154,   21,   21,  157, 1733, 1728,
-       54, 1728,  162, 1734,   21,   21,  158,   21,   21,   21,
-      158,   21,   21,   21,   21,   21,   21,  158,   21,   21,
-       21,   21,   21,   21,   21,  158,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18, 1723, 1723,   18,   18,  149,
+       18,   18,  152, 1728, 1723,   50, 1723,  157, 1729,   18,
+       18,  153,   18,   18,   18,  153,   18,   18,   18,   18,
+       18,   18,  153,   18,   18,   18,   18,   18,   18,   18,
+      153,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,  262,  263,  158, 1735,  268,
-     1736, 1737, 1728,  273, 1738, 1739, 1728, 1728, 1728, 1740,
-     1741,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+      257,  258,  153, 1730,  263, 1731, 1732, 1723,  268, 1733,
+     1734, 1723, 1723, 1723, 1735, 1736,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-      350,   21,  263,  265,  263,  265,  265,  357, 1742, 1728,
-      356, 1743, 1744, 1728, 1728, 1728, 1728, 1745, 1746, 1747,
-     1748, 1748, 1728, 1749, 1728,  375, 1750, 1741,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,  345,   18,  258,  260,  258,
+      260,  260,  352, 1737, 1723,  351, 1738, 1739, 1723, 1723,
+     1723, 1723, 1740, 1741, 1742, 1743, 1743, 1723, 1744, 1723,
+      370, 1745, 1736,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,  432,  433,  433,  438,  432,
-      357,  441, 1751, 1752, 1728,  445, 1753, 1728, 1754, 1755,
-     1728,  451, 1756, 1757, 1758, 1758, 1728, 1759, 1728,  459,
-     1760, 1746, 1728, 1728, 1761, 1762, 1728, 1728, 1728, 1728,
-     1763, 1764,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+      427,  428,  428,  433,  427,  352,  436, 1746, 1747, 1723,
+      440, 1748, 1723, 1749, 1750, 1723,  446, 1751, 1752, 1753,
+     1753, 1723, 1754, 1723,  454, 1755, 1741, 1723, 1723, 1756,
+     1757, 1723, 1723, 1723, 1723, 1758, 1759,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,  522,   21,  433,  435,  433,  433,  528,  441,
-      530, 1765, 1728, 1728, 1728, 1766, 1767, 1768, 1728, 1728,
-     1728, 1728, 1769, 1770, 1728, 1771, 1772, 1728, 1728, 1728,
-     1728, 1773, 1774, 1775, 1775, 1761, 1762, 1776, 1776, 1728,
-     1777, 1728,  562, 1778, 1779,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,  517,   18,  428,
+      430,  428,  428,  523,  436,  525, 1760, 1723, 1723, 1723,
+     1761, 1762, 1763, 1723, 1723, 1723, 1723, 1764, 1765, 1723,
+     1766, 1767, 1723, 1723, 1723, 1723, 1768, 1769, 1770, 1770,
+     1756, 1757, 1771, 1771, 1723, 1772, 1723,  557, 1773, 1774,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,  616,  616,
-      620,  530,  622, 1780, 1781, 1728,  626, 1782, 1728,  629,
-     1783, 1728, 1784, 1785, 1728,  635, 1786, 1787, 1787, 1728,
-     1788, 1728,  642, 1789, 1790, 1791, 1791, 1792, 1793, 1794,
-     1794, 1728, 1795, 1728,  654, 1796, 1797, 1728, 1798, 1728,
-     1799, 1800, 1728, 1728, 1728, 1728, 1801, 1802,  623,  669,
-      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
-      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
-      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,  611,  611,  615,  525,  617, 1775, 1776,
+     1723,  621, 1777, 1723,  624, 1778, 1723, 1779, 1780, 1723,
+      630, 1781, 1782, 1782, 1723, 1783, 1723,  637, 1784, 1785,
+     1786, 1786, 1787, 1788, 1789, 1789, 1723, 1790, 1723,  649,
+     1791, 1792, 1723, 1793, 1723, 1794, 1795, 1723, 1723, 1723,
+     1723, 1796, 1797,  618,  664,  664,  664,  664,  664,  664,
+      664,  664,  664,  664,  664,  664,  664,  664,  664,  664,
+      664,  664,  664,  664,  664,  664,  664,  664,  664,  664,
+      664,  664,  664,  664,  664,  664,  664,  664,  618,  618,
 
-      669,  669,  669,  669,  669,  669,  706,  706,  706,  669,
-      706,  711, 1803, 1728, 1728, 1728, 1804, 1728, 1728, 1805,
-     1806, 1807, 1728, 1728, 1728, 1728, 1808, 1809, 1728, 1810,
-     1811, 1728, 1728, 1728, 1728, 1812, 1813, 1728, 1814, 1728,
-     1815, 1816, 1728, 1728, 1728, 1728, 1817, 1818, 1819, 1728,
-     1820, 1821, 1821, 1822, 1823, 1824, 1824, 1728, 1825, 1728,
-      760, 1826, 1827, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-     1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-     1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
-     1828, 1828, 1828, 1828, 1828,  794, 1828,  794,  798,  798,
+      664,  701,  701,  701,  664,  701,  706, 1798, 1723, 1723,
+     1723, 1799, 1723, 1723, 1800, 1801, 1802, 1723, 1723, 1723,
+     1723, 1803, 1804, 1723, 1805, 1806, 1723, 1723, 1723, 1723,
+     1807, 1808, 1723, 1809, 1723, 1810, 1811, 1723, 1723, 1723,
+     1723, 1812, 1813, 1814, 1723, 1815, 1816, 1816, 1817, 1818,
+     1819, 1819, 1723, 1820, 1723,  755, 1821, 1822, 1823, 1823,
+     1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+     1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+     1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823, 1823,
+      789, 1823,  789,  793,  793,  795, 1824, 1825, 1723,  799,
 
-      800, 1829, 1830, 1728,  804, 1831, 1728,  807, 1832, 1728,
-      810, 1833, 1728, 1834, 1835, 1728,  816, 1836, 1837, 1837,
-     1728, 1838, 1728,  823, 1839, 1840, 1841, 1841, 1842, 1843,
-     1844, 1844, 1728, 1845, 1728,  835, 1846, 1847, 1848, 1728,
-     1849, 1850, 1850, 1851, 1852, 1853, 1853, 1728, 1854, 1728,
-      850, 1855, 1856, 1857, 1728, 1858, 1728, 1859, 1860, 1728,
-     1728, 1728, 1728, 1861, 1862, 1863, 1863, 1863, 1863, 1863,
-     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
-     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,  889,
-      889,  891,  889,  889,  894, 1864, 1728, 1728, 1728, 1865,
+     1826, 1723,  802, 1827, 1723,  805, 1828, 1723, 1829, 1830,
+     1723,  811, 1831, 1832, 1832, 1723, 1833, 1723,  818, 1834,
+     1835, 1836, 1836, 1837, 1838, 1839, 1839, 1723, 1840, 1723,
+      830, 1841, 1842, 1843, 1723, 1844, 1845, 1845, 1846, 1847,
+     1848, 1848, 1723, 1849, 1723,  845, 1850, 1851, 1852, 1723,
+     1853, 1723, 1854, 1855, 1723, 1723, 1723, 1723, 1856, 1857,
+     1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858,
+     1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858, 1858,
+     1858, 1858, 1858, 1858,  884,  884,  886,  884,  884,  889,
+     1859, 1723, 1723, 1723, 1860, 1723, 1723, 1861, 1723, 1723,
 
-     1728, 1728, 1866, 1728, 1728, 1867, 1868, 1869, 1728, 1728,
-     1728, 1728, 1870, 1871, 1728, 1872, 1873, 1728, 1728, 1728,
-     1728, 1874, 1875, 1728, 1876, 1728, 1877, 1878, 1728, 1728,
-     1728, 1728, 1879, 1880, 1881, 1728, 1882, 1728, 1883, 1884,
-     1728, 1728, 1728, 1728, 1885, 1886, 1887, 1888, 1728, 1889,
-     1890, 1890, 1891, 1892, 1893, 1893, 1728, 1894, 1728,  959,
-     1895, 1896, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897,
-     1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897,
-     1897, 1897, 1897, 1897, 1897, 1897,  986, 1897, 1897, 1898,
-     1899, 1728,  992, 1900, 1728,  995, 1901, 1728,  998, 1902,
+     1862, 1863, 1864, 1723, 1723, 1723, 1723, 1865, 1866, 1723,
+     1867, 1868, 1723, 1723, 1723, 1723, 1869, 1870, 1723, 1871,
+     1723, 1872, 1873, 1723, 1723, 1723, 1723, 1874, 1875, 1876,
+     1723, 1877, 1723, 1878, 1879, 1723, 1723, 1723, 1723, 1880,
+     1881, 1882, 1883, 1723, 1884, 1885, 1885, 1886, 1887, 1888,
+     1888, 1723, 1889, 1723,  954, 1890, 1891, 1892, 1892, 1892,
+     1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892,
+     1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892,
+     1892,  981, 1892, 1892, 1893, 1894, 1723,  987, 1895, 1723,
+      990, 1896, 1723,  993, 1897, 1723,  996, 1898, 1723, 1899,
 
-     1728, 1001, 1903, 1728, 1904, 1728, 1728, 1007, 1905, 1906,
-     1906, 1728, 1907, 1728, 1014, 1908, 1909, 1910, 1910, 1911,
-     1912, 1913, 1913, 1728, 1914, 1728, 1026, 1915, 1916, 1917,
-     1728, 1918, 1919, 1919, 1920, 1921, 1922, 1922, 1728, 1923,
-     1728, 1041, 1924, 1925, 1926, 1927, 1728, 1928, 1929, 1929,
-     1930, 1931, 1932, 1932, 1728, 1933, 1728, 1057, 1934, 1935,
-     1936, 1728, 1937, 1728, 1938, 1939, 1728, 1728, 1728, 1728,
-     1940, 1941, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
-     1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
-     1942, 1942, 1942, 1942, 1942, 1095, 1942, 1943, 1728, 1728,
+     1723, 1723, 1002, 1900, 1901, 1901, 1723, 1902, 1723, 1009,
+     1903, 1904, 1905, 1905, 1906, 1907, 1908, 1908, 1723, 1909,
+     1723, 1021, 1910, 1911, 1912, 1723, 1913, 1914, 1914, 1915,
+     1916, 1917, 1917, 1723, 1918, 1723, 1036, 1919, 1920, 1921,
+     1922, 1723, 1923, 1924, 1924, 1925, 1926, 1927, 1927, 1723,
+     1928, 1723, 1052, 1929, 1930, 1931, 1723, 1932, 1723, 1933,
+     1934, 1723, 1723, 1723, 1723, 1935, 1936, 1937, 1937, 1937,
+     1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937,
+     1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1937,
+     1090, 1937, 1938, 1723, 1723, 1723, 1939, 1723, 1723, 1940,
 
-     1728, 1944, 1728, 1728, 1945, 1728, 1728, 1946, 1728, 1728,
-     1947, 1948, 1728, 1113, 1949, 1950, 1728, 1728, 1951, 1952,
-     1953, 1728, 1954, 1955, 1728, 1728, 1728, 1956, 1957, 1958,
-     1728, 1959, 1728, 1960, 1961, 1728, 1728, 1728, 1962, 1963,
-     1964, 1965, 1728, 1966, 1728, 1967, 1968, 1728, 1728, 1728,
-     1969, 1970, 1971, 1972, 1728, 1973, 1728, 1974, 1975, 1728,
-     1728, 1728, 1976, 1977, 1978, 1979, 1980, 1728, 1981, 1982,
-     1982, 1983, 1984, 1985, 1985, 1728, 1986, 1728, 1178, 1987,
-     1988, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
-     1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+     1723, 1723, 1941, 1723, 1723, 1942, 1943, 1723, 1108, 1944,
+     1945, 1723, 1723, 1946, 1947, 1948, 1723, 1949, 1950, 1723,
+     1723, 1723, 1951, 1952, 1953, 1723, 1954, 1723, 1955, 1956,
+     1723, 1723, 1723, 1957, 1958, 1959, 1960, 1723, 1961, 1723,
+     1962, 1963, 1723, 1723, 1723, 1964, 1965, 1966, 1967, 1723,
+     1968, 1723, 1969, 1970, 1723, 1723, 1723, 1971, 1972, 1973,
+     1974, 1975, 1723, 1976, 1977, 1977, 1978, 1979, 1980, 1980,
+     1723, 1981, 1723, 1173, 1982, 1983, 1984, 1984, 1984, 1984,
+     1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984,
+     1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1985,
 
-     1989, 1989, 1989, 1989, 1990, 1728, 1728, 1207, 1991, 1728,
-     1210, 1992, 1728, 1213, 1993, 1728, 1216, 1994, 1728, 1219,
-     1995, 1728, 1728, 1728, 1996, 1997, 1998, 1999, 2000, 2000,
-     1728, 2001, 2002, 2003, 2004, 2004, 2005, 2006, 2007, 2007,
-     1728, 2008, 2009, 2010, 2011, 1728, 2012, 2013, 2013, 2014,
-     2015, 2016, 2016, 1728, 2017, 2018, 2019, 2020, 2021, 1728,
-     2022, 2023, 2023, 2024, 2025, 2026, 2026, 1728, 2027, 2028,
-     2029, 2030, 2031, 1728, 2032, 2033, 2033, 2034, 2035, 2036,
-     2036, 1728, 2037, 2038, 2039, 2040, 1728, 2041, 1728, 2042,
-     2043, 1728, 1728, 1728, 2044, 2045, 2046, 2047, 2047, 2047,
+     1723, 1723, 1202, 1986, 1723, 1205, 1987, 1723, 1208, 1988,
+     1723, 1211, 1989, 1723, 1214, 1990, 1723, 1723, 1723, 1991,
+     1992, 1993, 1994, 1995, 1995, 1723, 1996, 1997, 1998, 1999,
+     1999, 2000, 2001, 2002, 2002, 1723, 2003, 2004, 2005, 2006,
+     1723, 2007, 2008, 2008, 2009, 2010, 2011, 2011, 1723, 2012,
+     2013, 2014, 2015, 2016, 1723, 2017, 2018, 2018, 2019, 2020,
+     2021, 2021, 1723, 2022, 2023, 2024, 2025, 2026, 1723, 2027,
+     2028, 2028, 2029, 2030, 2031, 2031, 1723, 2032, 2033, 2034,
+     2035, 1723, 2036, 1723, 2037, 2038, 1723, 1723, 1723, 2039,
+     2040, 2041, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042,
 
-     2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
-     2047, 2047, 2047, 2047, 2047, 2047, 2047, 1728, 1318, 2048,
-     2049, 1728, 2050, 2051, 1728, 2052, 2053, 1728, 2054, 2055,
-     1728, 2056, 2057, 1728, 2058, 2059, 2060, 2060, 1728, 2061,
-     2062, 2063, 2064, 2065, 1728, 2066, 2067, 1728, 2068, 1728,
-     2069, 1728, 2070, 2071, 1728, 2072, 2073, 1728, 2074, 1728,
-     2075, 2076, 1728, 2077, 2078, 1728, 2079, 1728, 2080, 2081,
-     1728, 2082, 2083, 1728, 2084, 1728, 2085, 2086, 1728, 2087,
-     2088, 2089, 1728, 2090, 2091, 2091, 2092, 2093, 2094, 2094,
-     1728, 2095, 2096, 2097, 2098, 2098, 2098, 2098, 2098, 2098,
+     2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042,
+     2042, 2042, 1723, 1313, 2043, 2044, 1723, 2045, 2046, 1723,
+     2047, 2048, 1723, 2049, 2050, 1723, 2051, 2052, 1723, 2053,
+     2054, 2055, 2055, 1723, 2056, 2057, 2058, 2059, 2060, 1723,
+     2061, 2062, 1723, 2063, 1723, 2064, 1723, 2065, 2066, 1723,
+     2067, 2068, 1723, 2069, 1723, 2070, 2071, 1723, 2072, 2073,
+     1723, 2074, 1723, 2075, 2076, 1723, 2077, 2078, 1723, 2079,
+     1723, 2080, 2081, 1723, 2082, 2083, 2084, 1723, 2085, 2086,
+     2086, 2087, 2088, 2089, 2089, 1723, 2090, 2091, 2092, 2093,
+     2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093,
 
-     2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098,
-     2098, 1728, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106,
-     1728, 2107, 2108, 1728, 2109, 2110, 2111, 2111, 2112, 2113,
-     2114, 2115, 1728, 2116, 2117, 2117, 2118, 2119, 2120, 2121,
-     2122, 1728, 2123, 2124, 2124, 2125, 2126, 2127, 2128, 2129,
-     1728, 2130, 2131, 2131, 2132, 2133, 2134, 2135, 2136, 1728,
-     2137, 2138, 2138, 2139, 2140, 2141, 2142, 1728, 2143, 1728,
-     2144, 2145, 1728, 2146, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2148, 1728, 2149, 2150, 2151, 2152, 2153, 2154, 2155,
+     2093, 2093, 2093, 2093, 2093, 2093, 1723, 2094, 2095, 2096,
+     2097, 2098, 2099, 2100, 2101, 1723, 2102, 2103, 1723, 2104,
+     2105, 2106, 2106, 2107, 2108, 2109, 2110, 1723, 2111, 2112,
+     2112, 2113, 2114, 2115, 2116, 2117, 1723, 2118, 2119, 2119,
+     2120, 2121, 2122, 2123, 2124, 1723, 2125, 2126, 2126, 2127,
+     2128, 2129, 2130, 2131, 1723, 2132, 2133, 2133, 2134, 2135,
+     2136, 2137, 1723, 2138, 1723, 2139, 2140, 1723, 2141, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2143, 1723, 2144, 2145,
+     2146, 2147, 2148, 2149, 2150, 2150, 2151, 2152, 2153, 1723,
 
-     2155, 2156, 2157, 2158, 1728, 1728, 2159, 1728, 2160, 1728,
-     2161, 1728, 2162, 1728, 2163, 1728, 2164, 1728, 2165, 1728,
-     2166, 1728, 2167, 1728, 2142, 2168, 1728, 2143, 2169, 2169,
-     2144, 2145, 2170, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2171,
-     1728, 2172, 2173, 1728, 2159, 2160, 2174, 1728, 2161, 2162,
-     2175, 1728, 2163, 2164, 2176, 1728, 2165, 2166, 2177, 1728,
-     2167, 2178, 1728, 2179, 1728, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2180, 1728,
-     2172, 2181, 2182, 2183, 2184, 2185, 2178, 2186, 1728, 2179,
+     1723, 2154, 1723, 2155, 1723, 2156, 1723, 2157, 1723, 2158,
+     1723, 2159, 1723, 2160, 1723, 2161, 1723, 2162, 1723, 2137,
+     2163, 1723, 2138, 2164, 2164, 2139, 2140, 2165, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2166, 1723, 2167, 2168, 1723, 2154,
+     2155, 2169, 1723, 2156, 2157, 2170, 1723, 2158, 2159, 2171,
+     1723, 2160, 2161, 2172, 1723, 2162, 2173, 1723, 2174, 1723,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2175, 1723, 2167, 2176, 2177, 2178, 2179,
+     2180, 2173, 2181, 1723, 2174, 2142, 2142, 2142, 2142, 2142,
 
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2187, 2181, 2182, 2183, 2184, 2185, 2188, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2187, 2188, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2182, 2176, 2177,
+     2178, 2179, 2180, 2183, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2182, 2183, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
 
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
-     2147, 2147, 2147, 2147, 2147, 2147, 2147,    0, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
+     2142, 2142,    0, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
 
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
 
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
 
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
 
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723
     } ;
 
-static yyconst flex_uint16_t yy_nxt[7910] =
+static const flex_int16_t yy_nxt[7679] =
     {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,   12,   12,
-       13,   14,   15,   15,   15,   15,   15,   15,   16,   17,
-       18,   19,   20,   21,   21,   12,   22,   13,   23,   24,
-       25,   26,   27,   28,   29,   30,   31,   21,   32,   33,
-       34,   35,   36,   21,   37,   38,   39,   40,   41,   42,
-       21,   21,   43,   44,   53,  211,   44,   44,   44,   44,
-       44,  212,   44,   44,   44,   57,   58,   44,  248,   44,
-       44,   44,   60,   61,   72,   44,   83,   84,  249,   44,
-       53,   44,   44,   44,   44,  206,   44,   44,   73,   85,
-       44,  117,   79, 1157,   86,   74,   80,  686,  195,   44,
+        4,    5,    6,    5,    7,    8,    9,   10,    9,    9,
+        4,   11,   12,   12,   12,   12,   12,   12,   13,   14,
+       15,   16,   17,   18,   18,   19,    4,   20,   21,   22,
+       23,   24,   25,   26,   27,   28,   18,   29,   30,   31,
+       32,   33,   18,   34,   35,   36,   37,   38,   39,   18,
+       18,   40,   44,   45,   46,   46,   46,   46,   46,   46,
+       46,   47,   53,   54,   49,   48,   49,   50,  769,   51,
+       48,   48,   48,   48,   48,   48,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   50,   49,   49,   56,   57,   60,   74,   61,
 
-      118,  196,   81,  687,  197,   82,  198,   44,   48,   49,
-       50,   50,   50,   50,   50,   50,   50,   51,  207,  201,
-      942,   52,   53,   54,  202,  182,   55,   52,   52,   52,
-       52,   52,   52,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
-       53,   44,  183,   75,   44,  766,   44,   44,  184,  236,
-       87,   53,  213,   76,   88,  344,   77,  214,   63,   56,
-       78,   63,  237,   63,   63,  208,   89,   44,   62,   52,
-       52,   52,   52,   52,   52,   52,   63,  242,   65,  345,
-       66,   67,   53,  768,   63,   68,   53,  342,  119,  343,
+       62,  112,   75,  499,   63,   78,   79,   80,   76,   64,
+      113,   77,   81,   65,   67,   66,  192,  500,  193,   49,
+       58,   48,   48,   48,   48,   48,   48,   48,   68,   70,
+      190, 1150,   82,  191,   49,   69,   83,  124,  206,   71,
+      201,  125,   72,   85,  207,   86,   73,  196,   84,  126,
+       87,   88,  197,   89,  127, 1152,  128,   90,  237,   49,
+       51,   49,   49,   49,   49,   49,   49,   49,   49, 1723,
+       99,  100,  202,   49,  937,  136,  238,  137,   49,   49,
+       49,   49,   49,   49,   91,  101, 1330,   92,   93,  102,
+       94,  138,   95,  103,   96,  104,   97,  106,  139,   98,
 
-       69,   90,  209,   91,   70,  243,   71,  210,   92,   93,
-      120,   94,  121, 1335,  122,   95,  453,  123,   53,   55,
-       53,   53,   53,   53,   53,   53,   53,   53, 1728,  104,
-      105,  217,   53,  770,  218, 1161,  219,  245,   53,   53,
-       53,   53,   53,   53,   96,  106,  246,   97,   98,  107,
-       99,   53,  100,  108,  101,  109,  102,  111,  124,  103,
-       53,  112,  110,  125,  126,  129,  127,  128,  799,  130,
-      113,  114, 1728,  134,  115,  324,  116,  131,  141,  135,
-      142,  136,  132,  137,  133,  146,   53,  138,  325,  139,
-      140,   53,  355,  147,  143,   53,  527,  148, 1728,  149,
+      119,  107,  105,  114,   49,  120,  121,  208,  122,  123,
+      108,  109,  209,  141,  110,  115,  111,  116,  129,  117,
+      203,  142,  118,  243,  130,  143,  131,  144,  132,   49,
+      231,  319,  133,  244,  134,  135,  148,  148,  148,  148,
+      148,  148,  148,  232,  320,  212,  204,  148,  213,  339,
+      214,  205,  148,  148,  148,  148,  148,  148,  149,  150,
+      150,  150,  150,  150,  150, 1723,  337,  681,  338,  151,
+       49,  350,  340,  682,  151,  151,  151,  151,  151,  151,
+       45,  152,  152,  152,  152,  152,  152,  152,  763,  412,
+     1723,   49,  153,  177,  413, 1723,   49,  153,  153,  153,
 
-       44,  144,  490,   44,   53,   44,   44,  156,  156,  156,
-      156,  156,  156,  156, 1728,  417,   63,   53,   44,   63,
-      418,   63,   63,  491,  500, 1070,   44,  153,  153,  153,
-      153,  153,  153,  153,   63,   53,  708,  501,  153,  492,
-     1728,  775,   63,   53,  153,  153,  153,  153,  153,  153,
-      154,  155,  155,  155,  155,  155,  155, 1728,   53,   53,
-     1728,  156,  380,  381,  382,  383, 1295,  156,  156,  156,
-      156,  156,  156,   49,  157,  157,  157,  157,  157,  157,
-      157,  277,  384, 1728,   53,  158, 1728, 1728, 1728,  279,
-     1413,  158,  158,  158,  158,  158,  158,   62,  158,  158,
+      153,  153,  153,   58,  153,  153,  153,  153,  153,  153,
+      153,  156,  156,  156,  156,  156,  156,  156, 1723,  178,
+     1723,   49,  156,   49,  522,  179,  448,  156,  156,  156,
+      156,  156,  156,  157,  158,  158,  158,  158,  158,  158,
+       49,  703,  762, 1723,  159,  760,   49,   49,   49,  159,
+      159,  159,  159,  159,  159,  151,  151,  151,  151,  151,
+      151,  151,  240,  347,  347,  347,  347,  347,  347,  347,
+      432,  241,  255,   49,  256,  256,  256,  256,  256,  256,
+      256, 1723, 1723, 1156,  260,  256,  375,  376,  377,  378,
+      256,  256,  256,  256,  256,  256,  257,  258,  258,  258,
 
-      158,  158,  158,  158,  158,  161,  161,  161,  161,  161,
-      161,  161,  576, 1728, 1728,  437,  161, 1323,  504,  765,
-       53,  577,  161,  161,  161,  161,  161,  161,   44,  265,
-      767,   44,  505,   44,   44,   53, 1326,  464,  464,  162,
-      163,  163,  163,  163,  163,  163,   44,   53, 1728,   53,
-      164,  465, 1728,  774,   44,  265,  164,  164,  164,  164,
-      164,  164,  260,  579,  261,  261,  261,  261,  261,  261,
-      261,  365,  580,   53, 1728,  261, 1728,  465, 1728,  535,
-      781,  261,  261,  261,  261,  261,  261,  262,  263,  263,
-      263,  263,  263,  263,  263,  277,  468,   53, 1329,  264,
+      258,  258,  258,  258,  272,  379, 1723, 1723,  259,  260,
+      260, 1065,  274,  259,  259,  259,  259,  259,  259,  366,
+      367,  367,  367,  367,  367,  367,  435,  435,  435,  435,
+      435,  435,  435,  459,  776,  260,  261,  259,  259,  259,
+      259,  259,  259,  259, 1723,   49,  761,  460,  259, 1723,
+     1723,   49,   49,  259,  259,  259,  259,  259,  259,  262,
+      263,  263,  263,  263,  263,  263,  263,  264, 1290, 1723,
+       49,  265,  460, 1723, 1723, 1723,  265,  265,  265,  265,
+      265,  265,   49,  265,  265,  265,  265,  265,  265,  265,
+      268,  269,  269,  269,  269,  269,  269,  270, 1723,   49,
 
-     1728,  265, 1728, 1728,  470,  264,  264,  264,  264,  264,
-      264,  352,  352,  352,  352,  352,  352,  352,  371,  372,
-      372,  372,  372,  372,  372,  545, 1728,  265,  266,  264,
-      264,  264,  264,  264,  264,  264,  688, 1728, 1332,  546,
-      264,  380,  381,  382,  383,  689,  264,  264,  264,  264,
-      264,  264,  267,  268,  268,  268,  268,  268,  268,  268,
-      269,  779, 1335, 1728,  270,  546, 1728, 1728,   53, 1413,
-      270,  270,  270,  270,  270,  270,   53,  270,  270,  270,
-      270,  270,  270,  270,  273,  274,  274,  274,  274,  274,
-      274,  275, 1728, 1728,  773,  276,   53,  777,  453,   53,
+      781,  271,  375,  376,  377,  378,  271,  271,  271,  271,
+      271,  271,  272,  273,  273,  273,  273,  273,  273,  273,
+      274,  459, 1723, 1408,  275,  485,  276,   51,  391,  275,
+      275,  275,  275,  275,  275, 1723,  392,  450,  451,  451,
+      451,  451,  451,  451,   51,  486,  495, 1723,  393,  765,
+     1318,  276,  344,  344,  344,  344,  344,  344,  344,  496,
+     1723,  487, 1723,  344,  394,  770, 1321,   49,  344,  344,
+      344,  344,  344,  344,  345,  346,  346,  346,  346,  346,
+      346,  360,  768,   49,   49,  347, 1324, 1723, 1723,  530,
+      347,  347,  347,  347,  347,  347,  257,  348,  348,  348,
 
-      453,  276,  276,  276,  276,  276,  276,  277,  278,  278,
-      278,  278,  278,  278,  278,  279,  782,   53,  786,  280,
-     1223,  281,  453,  396,   53,  280,  280,  280,  280,  280,
-      280,  397,  440,  440,  440,  440,  440,  440,  440,   53,
-      793,  545, 1323,  619,  398,   55,  771,  281,  349,  349,
-      349,  349,  349,  349,  349, 1728,   53,  435,  618,  349,
-      399,  453,   55,   55,  784,  349,  349,  349,  349,  349,
-      349,  350,  351,  351,  351,  351,  351,  351,  690,   53,
-       55, 1728,  352,  435,  618,  854, 1728,  691,  352,  352,
-      352,  352,  352,  352,  262,  353,  353,  353,  353,  353,
+      348,  348,  348,  348,  349,  349,  349,  349,  349,  349,
+      349,  272,  772, 1723,   49,  349,   49,  788, 1327, 1723,
+      349,  349,  349,  349,  349,  349,  351,  352,  352,  352,
+      352,  352,  352,  352,  463,  794, 1330, 1408,  353,  448,
+      448,  613,  465,  353,  353,  353,  353,  353,  353,  356,
+      353,  353,  353,  353,  353,  353,  353,  360,  361,  361,
+      361,  361,  361,  361,  361,  362,  613, 1218,  448,  363,
+       49,  364,   51,  540,  363,  363,  363,  363,  363,  363,
+      519,  519,  519,  519,  519,  519,  519,  541,  774,   51,
+     1318,  448,  771,  540,  614,   49,  364,  272,  368,  368,
 
-      353,  353,  354,  354,  354,  354,  354,  354,  354,  769,
-     1728,  854, 1728,  354, 1326,  453, 1329,   55,   53,  354,
-      354,  354,  354,  354,  354,  356,  357,  357,  357,  357,
-      357,  357,  357,  540,  549,   55, 1728,  358,  453, 1332,
-      872,  716,  719,  358,  358,  358,  358,  358,  358,  361,
-      358,  358,  358,  358,  358,  358,  358,  365,  366,  366,
-      366,  366,  366,  366,  366,  367,  664,  453, 1335,  368,
-      453,  369, 1287, 1289,  666,  368,  368,  368,  368,  368,
-      368,  455,  456,  456,  456,  456,  456,  456,  524,  524,
-      524,  524,  524,  524,  524,  658,  778,  369,  277,  373,
+      368,  368,  368,  368,  368,  274,   49, 1723,  430,  369,
+     1321,   51,  541,  775,  369,  369,  369,  369,  369,  369,
+      370,  371,  371,  371,  371,  371,  371,   49,   51,  871,
+      849,  372, 1723,  430,  571,  766,  372,  372,  372,  372,
+      372,  372,  416,  572,  417,   49,  418,  419,  549,  550,
+      550,  550,  550,  550,  550,  849,  420,  653,  421,  422,
+      653,  423,  425,  574,  426,  426,  426,  426,  426,  426,
+      426,  654,  575,  448, 1723,  426, 1723, 1324,   51,  448,
+      426,  426,  426,  426,  426,  426,  427,  428,  428,  428,
+      428,  428,  428,  428,  777,   51,  654, 1327,  429, 1723,
 
-      373,  373,  373,  373,  373,  373,  279,   53, 1068,  659,
-      374, 1295,   55,   55, 1293,  776,  374,  374,  374,  374,
-      374,  374,  375,  376,  376,  376,  376,  376,  376,   53,
-       55,   55,  780,  377,  658,  659,  879,  866, 1493,  377,
-      377,  377,  377,  377,  377,  421,   53,  422, 1728,  423,
-      424,  554,  555,  555,  555,  555,  555,  555,   55,  425,
-      785,  426,  427,  660,  428,  430,  660,  431,  431,  431,
-      431,  431,  431,  431, 1728,   53,   55,  661,  431,  873,
-     1728,   55, 1413,   55,  431,  431,  431,  431,  431,  431,
-      432,  433,  433,  433,  433,  433,  433,  433, 1413,   55,
+      430, 1723,   49,  429,  429,  429,  429,  429,  429,  553,
+      554,  554,  554,  554,  554,  554,  633,  634,  634,  634,
+      634,  634,  634,  655,  773,  430,  431,  429,  429,  429,
+      429,  429,  429,  429, 1723,   49,  448,  656,  429, 1330,
+       51,   51,  655,  429,  429,  429,  429,  429,  429,  433,
+      434,  434,  434,  434,  434,  434, 1723,   51,   51, 1723,
+      435,  868,  656,   51,  779,  435,  435,  435,  435,  435,
+      435,  262,  436,  436,  436,  436,  436,  436,  436,   49,
+       51, 1723,  448,  437, 1723, 1723, 1723,  861,  437,  437,
+      437,  437,  437,  437,   49,  437,  437,  437,  437,  437,
 
-      876,   55,  434,  661,  435,  453, 1728, 1345,  434,  434,
-      434,  434,  434,  434,  558,  559,  559,  559,  559,  559,
-      559,  638,  639,  639,  639,  639,  639,  639,  729,  783,
-      435,  436,  434,  434,  434,  434,  434,  434,  434,   53,
-     1117, 1350,  730,  434, 1352,   55,   55,   55,  729,  434,
-      434,  434,  434,  434,  434,  438,  439,  439,  439,  439,
-      439,  439, 1728,   55,   55,   55,  440,  874,  730,   55,
-      883,   55,  440,  440,  440,  440,  440,  440,  267,  441,
-      441,  441,  441,  441,  441,  441, 1126,   55, 1728,   55,
-      442, 1728,  884, 1728, 1728, 1358,  442,  442,  442,  442,
+      437,  437,  440,  441,  441,  441,  441,  441,  441, 1723,
+     1723, 1723, 1723,  442, 1282, 1284,   51,  780,  442,  442,
+      442,  442,  442,  442,  446,  447,  447,  447,  447,  447,
+      447,  448,   49,   51, 1063,  449, 1290, 1723,  867,   51,
+      449,  449,  449,  449,  449,  449,  360,  452,  452,  452,
+      452,  452,  452,  452,  362, 1288,   51, 1488,  453,  869,
+       51,   51,   51,  453,  453,  453,  453,  453,  453,  454,
+      455,  455,  455,  455,  455,  455,  448,   51,   51,   51,
+      456,  882,  874,   51,  879,  456,  456,  456,  456,  456,
+      456,  272,  461,  461,  461,  461,  461,  461,  461,  274,
 
-      442,  442,   53,  442,  442,  442,  442,  442,  442,  442,
-      445,  446,  446,  446,  446,  446,  446, 1728,  724, 1728,
-     1728,  447, 1360,   55,   55,  794,  899,  447,  447,  447,
-      447,  447,  447,  451,  452,  452,  452,  452,  452,  452,
-      453,   55,   55,   55,  454,  887, 1728,   55,  796, 1137,
-      454,  454,  454,  454,  454,  454,  365,  457,  457,  457,
-      457,  457,  457,  457,  367,   55, 1728,  935,  458, 1728,
-       55,   55, 1728, 1366,  458,  458,  458,  458,  458,  458,
-      459,  460,  460,  460,  460,  460,  460,  453,   55,   55,
-       53,  461, 1728,  935,  963, 1728,   55,  461,  461,  461,
+       51, 1408, 1723,  462, 1408,  448,   51,  878,  462,  462,
+      462,  462,  462,  462,  463,  464,  464,  464,  464,  464,
+      464,  464,  465,   51, 1340, 1112,  466, 1723,  467,  683,
+      782,  466,  466,  466,  466,  466,  466,  577,  684,  578,
+      685,  724,  579,  580,   49,  724,  581,  582,  764,  686,
+      778,  583,  787,  467,  477,  725, 1345,   49,  478, 1723,
+       49,  479,   49,  733,  480,  733,  481,  482,  483,  484,
+      516,  516,  516,  516,  516,  516,  516,  734, 1347, 1723,
+      725,  516,  930,   51, 1723,  783,  516,  516,  516,  516,
+      516,  516,  517,  518,  518,  518,  518,  518,  518,   49,
 
-      461,  461,  461,  277,  466,  466,  466,  466,  466,  466,
-      466,  279, 1368, 1149,   55,  467,   53, 1374,   55,  964,
-       55,  467,  467,  467,  467,  467,  467,  468,  469,  469,
-      469,  469,  469,  469,  469,  470,   55,  975,   55,  471,
-      787,  472, 1376,  965,  788,  471,  471,  471,  471,  471,
-      471,  582,  738,  583,   53,  789,  584,  585,   53,  738,
-      586,  587,  791,  733,  792,  588,  739,  472,  482,   53,
-     1161,  902,  483, 1728,   53,  484,   53,  740,  485,  740,
-      486,  487,  488,  489,  521,  521,  521,  521,  521,  521,
-      521,  741,  739, 1728, 1295,  521,   55,   55,   55, 1728,
+       51, 1121,  734,  519, 1723, 1723,   49,  930,  519,  519,
+      519,  519,  519,  519,  427,  520,  520,  520,  520,  520,
+      520,  520,  521,  521,  521,  521,  521,  521,  521,  535,
+     1723,   49, 1056,  521, 1723, 1353,  789,  711,  521,  521,
+      521,  521,  521,  521,  432,  523,  523,  523,  523,  523,
+      523,  523,  544,   51, 1355, 1132,  524, 1056,  260, 1723,
+      714,  524,  524,  524,  524,  524,  524,  641,  642,  642,
+      642,  642,  642,  642,  645,  646,  646,  646,  646,  646,
+      646,   51,  735,  260,  524,  524,  524,  524,  524,  524,
+      524, 1723, 1361, 1723, 1723,  524,  736,   51,   51,  784,
 
-     1421,  521,  521,  521,  521,  521,  521,  522,  523,  523,
-      523,  523,  523,  523,   55,   55,   55,  741,  524, 1728,
-      967,  969, 1061,  880,  524,  524,  524,  524,  524,  524,
-      432,  525,  525,  525,  525,  525,  525,  525,  526,  526,
-      526,  526,  526,  526,  526, 1223, 1468, 1470, 1061,  526,
-     1506,   55,   55,   55,   55,  526,  526,  526,  526,  526,
-      526,  437,  528,  528,  528,  528,  528,  528,  528,   55,
-       55,   55,   55,  529, 1510,  265,  970,  976,  881,  529,
-      529,  529,  529,  529,  529,  646,  647,  647,  647,  647,
-      647,  647,  650,  651,  651,  651,  651,  651,  651,   55,
+      524,  524,  524,  524,  524,  524,  525,  525,  525,  525,
+      525,  525,  525,   49,   51,  862, 1723,  526, 1723, 1723,
+     1363,  736,  526,  526,  526,  526,  526,  526,   49,  526,
+      526,  526,  526,  526,  526,  526,  360,  529,  529,  529,
+      529,  529,  529,  529,  530,  786,  735, 1144,  531, 1369,
+      364, 1371, 1156,  531,  531,  531,  531,  531,  531,   49,
+     1723,  744,  745,  745,  745,  745,  745,  745,  747,  748,
+      748,  748,  748,  748,  748,  364,  535,  536,  536,  536,
+      536,  536,  536,  536,  537, 1723, 1290, 1416,  538, 1218,
+      539, 1463, 1465,  538,  538,  538,  538,  538,  538,  751,
 
-      855,  265,  529,  529,  529,  529,  529,  529,  529, 1728,
-      744, 1728, 1728,  529,  856,   55, 1514,   55,  905,  529,
-      529,  529,  529,  529,  529,  530,  530,  530,  530,  530,
-      530,  530, 1518,   55,  867, 1728,  531, 1728, 1728, 1728,
-      856,  979,  531,  531,  531,  531,  531,  531,   53,  531,
-      531,  531,  531,  531,  531,  531,  365,  534,  534,  534,
-      534,  534,  534,  534,  535, 1728, 1522, 1551,  536, 1728,
-      369, 1573, 1155, 1149,  536,  536,  536,  536,  536,  536,
-      749,  750,  750,  750,  750,  750,  750,  752,  753,  753,
-      753,  753,  753,  753,   55, 1728,  369,  540,  541,  541,
+      752,  752,  752,  752,  752,  752,  814,  815,  815,  815,
+      815,  815,  815,  850,   51,  539,  360,  542,  542,  542,
+      542,  542,  542,  542,  530, 1723, 1501,  851,  543, 1505,
+     1723,   51,   51,  543,  543,  543,  543,  543,  543,  544,
+      545,  545,  545,  545,  545,  545,  545,  546,  863,   51,
+     1723,  547,  851,  548,  958, 1723,  547,  547,  547,  547,
+      547,  547,  822,  823,  823,  823,  823,  823,  823,  826,
+      827,  827,  827,  827,  827,  827,  850,   51,  548,  463,
+      555,  555,  555,  555,  555,  555,  555,  465, 1509, 1723,
+     1723,  556, 1513,   51,   51,  852,  556,  556,  556,  556,
 
-      541,  541,  541,  541,  541,  542,  861,  453, 1332,  543,
-      930,  544,   55, 1085,  863,  543,  543,  543,  543,  543,
-      543,  756,  757,  757,  757,  757,  757,  757,  819,  820,
-      820,  820,  820,  820,  820,  855,   55,  544,  365,  547,
-      547,  547,  547,  547,  547,  547,  535, 1145, 1143, 1728,
-      548, 1728, 1137, 1728,   55,   55,  548,  548,  548,  548,
-      548,  548,  549,  550,  550,  550,  550,  550,  550,  550,
-      551,  868,  453,   55,  552, 1728,  553, 1728,  982, 1728,
-      552,  552,  552,  552,  552,  552,  827,  828,  828,  828,
-      828,  828,  828,  831,  832,  832,  832,  832,  832,  832,
+      556,  556,  557,  558,  558,  558,  558,  558,  558,  853,
+       51,  864, 1517,  559, 1723, 1723,   51,  791,  559,  559,
+      559,  559,  559,  559,  608,  852,  609,  609,  609,  609,
+      609,  609,  609,   51,  853, 1546, 1723,  609, 1568, 1723,
+       51,   51,  609,  609,  609,  609,  609,  609,  610,  611,
+      611,  611,  611,  611,  611,  611, 1144,   51,   51, 1086,
+      612, 1723,  613,  959, 1723,  612,  612,  612,  612,  612,
+      612,  834,  835,  835,  835,  835,  835,  835,  837,  838,
+      838,  838,  838,  838,  838,   51,   51,  613,  610,  612,
+      612,  612,  612,  612,  612,  612,  659,  448, 1327, 1137,
 
-      857,   55,  553,  468,  560,  560,  560,  560,  560,  560,
-      560,  470, 1329, 1728,  858,  561,  919,   55, 1133,   55,
-      857,  561,  561,  561,  561,  561,  561,  562,  563,  563,
-      563,  563,  563,  563, 1728,   55,  869, 1131,  564, 1728,
-      858,   55, 1087,   55,  564,  564,  564,  564,  564,  564,
-      613,  915,  614,  614,  614,  614,  614,  614,  614,   55,
-     1728,   55, 1126,  614,  972,  916,   55,   55,  885,  614,
-      614,  614,  614,  614,  614,  615,  616,  616,  616,  616,
-      616,  616,  616,  453,   55,   55, 1326,  617, 1078,  618,
-      910,  916, 1084,  617,  617,  617,  617,  617,  617,  839,
+      612, 1723,   51,   51,  661,  612,  612,  612,  612,  612,
+      612,  432,  615,  615,  615,  615,  615,  615,  615,  866,
+      925, 1140,  872,  616, 1137, 1149, 1723, 1723,  616,  616,
+      616,  616,  616,  616,   49,  616,  616,  616,  616,  616,
+      616,  616,  617,  617,  617,  617,  617,  617,  617,  719,
+     1149, 1138, 1723,  618, 1723, 1281, 1723,  894,  618,  618,
+      618,  618,  618,  618,   49,  618,  618,  618,  618,  618,
+      618,  618,  621,  622,  622,  622,  622,  622,  622, 1723,
+     1281, 1723, 1723,  623, 1132,  448,   51,   51,  623,  623,
+      623,  623,  623,  623,  360,  452,  452,  452,  452,  452,
 
-      840,  840,  840,  840,  840,  840,  842,  843,  843,  843,
-      843,  843,  843,   55,   55,  618,  615,  617,  617,  617,
-      617,  617,  617,  617, 1142,  910, 1122, 1728,  617, 1154,
-     1728,   55,   55, 1101,  617,  617,  617,  617,  617,  617,
-      437,  620,  620,  620,  620,  620,  620,  620,  871,  919,
-     1142,  877,  621, 1728, 1728, 1154, 1728, 1104,  621,  621,
-      621,  621,  621,  621,   53,  621,  621,  621,  621,  621,
-      621,  621,  622,  622,  622,  622,  622,  622,  622,  930,
-     1728, 1117,  453,  623, 1286, 1728, 1728, 1107, 1323,  623,
-      623,  623,  623,  623,  623,   53,  623,  623,  623,  623,
+      452,  452,  530,   51,   51, 1324,  453, 1723,  960,  962,
+      910,  453,  453,  453,  453,  453,  453,  624,  625,  625,
+      625,  625,  625,  625,  911,  914, 1723, 1128,  626, 1126,
+       51,   51, 1121,  626,  626,  626,  626,  626,  626,  630,
+      631,  631,  631,  631,  631,  631,  448,   51,   51,  911,
+      632, 1723,  964,  965,   51,  632,  632,  632,  632,  632,
+      632,  535,  635,  635,  635,  635,  635,  635,  635,  537,
+      448,   51, 1723,  636,  967,   51, 1321,   51,  636,  636,
+      636,  636,  636,  636,  637,  638,  638,  638,  638,  638,
+      638,  448,   51,  970,   51,  639,  905, 1723,   51,  977,
 
-      623,  623,  623,  626,  627,  627,  627,  627,  627,  627,
-     1286, 1728, 1728, 1728,  628,  453, 1225,   55,   55,   55,
-      628,  628,  628,  628,  628,  628,  365,  457,  457,  457,
-      457,  457,  457,  457,  535,   55,   55,   55,  458, 1728,
-     1082, 1086, 1089,  915,  458,  458,  458,  458,  458,  458,
-      629,  630,  630,  630,  630,  630,  630, 1728,  942, 1342,
-     1728,  631, 1206,   55,   55, 1335, 1110,  631,  631,  631,
-      631,  631,  631,  635,  636,  636,  636,  636,  636,  636,
-      453,   55,   55, 1728,  637, 1090, 1728,   55,   55, 1088,
-      637,  637,  637,  637,  637,  637,  540,  640,  640,  640,
+      639,  639,  639,  639,  639,  639,  544,  647,  647,  647,
+      647,  647,  647,  647,  546,   51, 1117, 1112,  648, 1723,
+       51,   51,  971,  648,  648,  648,  648,  648,  648,  649,
+      650,  650,  650,  650,  650,  650,  448,   51,   51, 1723,
+      651, 1073, 1077,   51, 1723,  651,  651,  651,  651,  651,
+      651,  463,  657,  657,  657,  657,  657,  657,  657,  465,
+       51, 1080, 1352,  658, 1723,  448,   51,   51,  658,  658,
+      658,  658,  658,  658,  659,  660,  660,  660,  660,  660,
+      660,  660,  661,   51,   51, 1318,  662, 1352,  663, 1081,
+     1082,  662,  662,  662,  662,  662,  662,  841,  842,  842,
 
-      640,  640,  640,  640,  542,   55,   55, 1091,  641, 1332,
-       55, 1093,   55, 1329,  641,  641,  641,  641,  641,  641,
-      642,  643,  643,  643,  643,  643,  643,  453,   55, 1326,
-       55,  644, 1323, 1206,   55,   55,   55,  644,  644,  644,
-      644,  644,  644,  549,  652,  652,  652,  652,  652,  652,
-      652,  551,   55,   55,   55,  653, 1068,   55,   55,   55,
-     1295,  653,  653,  653,  653,  653,  653,  654,  655,  655,
-      655,  655,  655,  655,  453,   55,   55,   55,  656, 1187,
-     1190,   55, 1191,   55,  656,  656,  656,  656,  656,  656,
-      468,  662,  662,  662,  662,  662,  662,  662,  470,   55,
+      842,  842,  842,  842,  745,  745,  745,  745,  745,  745,
+      745,   51,   51,  663,  699,  699,  699,  699,  699,  699,
+      699, 1360,  448, 1368, 1220,  699, 1723,   51,   51,   51,
+      699,  699,  699,  699,  699,  699,  700,  700,  700,  700,
+      700,  700,  700,  873,   51,  963, 1360,  700, 1368, 1084,
+     1462, 1723,  700,  700,  700,  700,  700,  700,  610,  701,
+      701,  701,  701,  701,  701,  701,  702,  702,  702,  702,
+      702,  702,  702,  728, 1504, 1462, 1508,  702, 1512,   51,
+       51,  897,  702,  702,  702,  702,  702,  702,  432,  704,
+      704,  704,  704,  704,  704,  704,   51,   51, 1337, 1504,
 
-     1070,   55,  663, 1728, 1728,   55, 1194,  861,  663,  663,
-      663,  663,  663,  663,  664,  665,  665,  665,  665,  665,
-      665,  665,  666,   55, 1064, 1195,  667, 1062,  668, 1728,
-     1728, 1163,  667,  667,  667,  667,  667,  667,  846,  847,
-      847,  847,  847,  847,  847,  750,  750,  750,  750,  750,
-      750,  750,   55,   55,  668,  704,  704,  704,  704,  704,
-      704,  704, 1357,  453, 1365, 1373,  704, 1728,   55, 1110,
-       55,   55,  704,  704,  704,  704,  704,  704,  705,  705,
-      705,  705,  705,  705,  705,  878,   55,  968, 1357,  705,
-     1365, 1373, 1199, 1728, 1151,  705,  705,  705,  705,  705,
+      705, 1508, 1088, 1512,  974,  705,  705,  705,  705,  705,
+      705,   49,  705,  705,  705,  705,  705,  705,  705,  706,
+      706,  706,  706,  706,  706,  706,  739, 1201, 1330, 1327,
+      707, 1324, 1321, 1318,  900,  707,  707,  707,  707,  707,
+      707,   49,  707,  707,  707,  707,  707,  707,  707,  535,
+      710,  710,  710,  710,  710,  710,  710,  711,   51,   51,
+       51,  712,   51,  539,   51,   51,  712,  712,  712,  712,
+      712,  712,  856, 1201, 1063,   51,   51,   51, 1290,   51,
+      858,   51,   51,   51, 1085,  875,  876,  865,  539,  544,
+      713,  713,  713,  713,  713,  713,  713,  714,  877,   51,
 
-      705,  615,  706,  706,  706,  706,  706,  706,  706,  707,
-      707,  707,  707,  707,  707,  707, 1068,  453, 1107, 1467,
-      707, 1509,   55,   55, 1070,   55,  707,  707,  707,  707,
-      707,  707,  437,  709,  709,  709,  709,  709,  709,  709,
-       55,   55, 1197,   55,  710, 1467, 1200, 1509, 1513,  978,
-      710,  710,  710,  710,  710,  710,   53,  710,  710,  710,
-      710,  710,  710,  710,  711,  711,  711,  711,  711,  711,
-      711, 1117, 1126, 1139, 1513,  712,  453, 1104, 1128, 1323,
-     1326,  712,  712,  712,  712,  712,  712,   53,  712,  712,
-      712,  712,  712,  712,  712,  540,  715,  715,  715,  715,
+       51,  715,   51,  548,   51,  905,  715,  715,  715,  715,
+      715,  715,  870, 1096, 1065,  914,   51, 1516,  856,   51,
+     1059,   51,   51, 1099, 1057,  880,  910,   51,  548,  719,
+      720,  720,  720,  720,  720,  720,  720,  721,  881,   51,
+     1723,  722, 1516,  723,   51,  925,  722,  722,  722,  722,
+      722,  722,  883, 1102, 1567, 1158,  336,  888,  888,  888,
+      888,  888,  888,  888,  919, 1723,  919,   51,  723,  535,
+      726,  726,  726,  726,  726,  726,  726,  711,  920, 1567,
+     1723,  727,  448, 1587,   51, 1105,  727,  727,  727,  727,
+      727,  727,  728,  729,  729,  729,  729,  729,  729,  729,
 
-      715,  715,  715,  716,   55,   55,  924,  717,   55,  544,
-       55,   55,   55,  717,  717,  717,  717,  717,  717, 1137,
-      925,  453,   55,   55, 1101, 1119,   55, 1329,   55,   55,
-       55,   55,  980,   55,  870,  544,  549,  718,  718,  718,
-      718,  718,  718,  718,  719,  882,  925,  886,  720,   55,
-      553,   55, 1149, 1298,  720,  720,  720,  720,  720,  720,
-     1332,  875,  453, 1225,  888,  893,  893,  893,  893,  893,
-      893,  893,   55,  924,  926, 1517,  553,  724,  725,  725,
-      725,  725,  725,  725,  725,  726,   55, 1728,  927,  727,
-       55,  728,  926,  936,  936,  727,  727,  727,  727,  727,
+      730,  969,  921,  920,  731, 1723,  732,  921, 1587,  731,
+      731,  731,  731,  731,  731, 1146,  922, 1588,  448, 1102,
+     1589, 1723,  835,  835,  835,  835,  835,  835,  835,  931,
+       51,  732,  544,  737,  737,  737,  737,  737,  737,  737,
+      714,  922, 1588,  932,  738, 1589, 1723,   51, 1134,  738,
+      738,  738,  738,  738,  738,  739,  740,  740,  740,  740,
+      740,  740,  740,  741,   51,  931,  933,  742,  932,  743,
+      933,  448,  742,  742,  742,  742,  742,  742, 1099, 1723,
+      934,   51, 1123, 1590, 1723,  943,  944,  944,  944,  944,
+      944,  944,  972,   51,  743,  659,  753,  753,  753,  753,
 
-      727, 1517,  341, 1161,   55, 1521, 1728,  937, 1728,   55,
-      453, 1335, 1206, 1728,  927,  938, 1110,  728,  540,  731,
-      731,  731,  731,  731,  731,  731,  716,   55, 1299,  939,
-      732, 1521, 1728,  937, 1728,   55,  732,  732,  732,  732,
-      732,  732,  733,  734,  734,  734,  734,  734,  734,  734,
-      735, 1300, 1107,   55,  736,  939,  737, 1104, 1304,  938,
-      736,  736,  736,  736,  736,  736,  840,  840,  840,  840,
-      840,  840,  840, 1728,  948,  949,  949,  949,  949,  949,
-      949, 1101,  737,  549,  742,  742,  742,  742,  742,  742,
-      742,  719, 1223, 1206, 1572,  743, 1592, 1593,   55, 1728,
+      753,  753,  753,  661, 1723,  934,  448,  754, 1590, 1723,
+       51,   51,  754,  754,  754,  754,  754,  754,  755,  756,
+      756,  756,  756,  756,  756,  961, 1096, 1114,   51,  757,
+      448,   51,   51,   51,  757,  757,  757,  757,  757,  757,
+       49,   49,   49,   49,   49,   49,   49,  978,   51,   51,
+       51,   49,   51,   51,   51,   51,   49,   49,   49,   49,
+       49,   49,  946,  947,  947,  947,  947,  947,  947,   51,
+       51,   51,   51, 1057,  759,  789, 1057,  790,  790,  790,
+      790,  790,  790,  790,  966,  968, 1068, 1058,  790,  976,
+     1723,   51,   51,  790,  790,  790,  790,  790,  790,  791,
 
-     1413,  743,  743,  743,  743,  743,  743,  744,  745,  745,
-      745,  745,  745,  745,  745,  746,   55, 1070, 1301,  747,
-     1572,  748, 1592, 1593,  863,  747,  747,  747,  747,  747,
-      747,  951,  952,  952,  952,  952,  952,  952,  955,  956,
-      956,  956,  956,  956,  956,   55,   55,  748,  664,  758,
-      758,  758,  758,  758,  758,  758,  666, 1293,  942, 1163,
-      759, 1110, 1594,   55,   55, 1295,  759,  759,  759,  759,
-      759,  759,  760,  761,  761,  761,  761,  761,  761,  966,
-      974,  744,  938,  762,   55,   55,   55,   55, 1594,  762,
-      762,  762,  762,  762,  762,   53,   53,   53,   53,   53,
+      792,  792,  792,  792,  792,  792,  792, 1220,   51,   51,
+     1190,  792, 1058, 1182,  448, 1723,  792,  792,  792,  792,
+      792,  792,  701,  701,  701,  701,  701,  701,  701,  950,
+      951,  951,  951,  951,  951,  951,   51,   51,   51, 1005,
+     1006, 1006, 1006, 1006, 1006, 1006, 1013, 1014, 1014, 1014,
+     1014, 1014, 1014,   51,   51,   51,   49,  702,  702,  702,
+      702,  702,  702,  702,  973, 1201, 1105, 1102,  702, 1069,
+     1072, 1591, 1608,  702,  702,  702,  702,  702,  702,  793,
+      348,  348,  348,  348,  348,  348,  348,  262,  795,  795,
+      795,  795,  795,  795,  795,  937, 1591, 1608, 1099,  796,
 
-       53,   53,   55,   55,   55,   55,   53,   55,   55, 1062,
-       55,   55,   53,   53,   53,   53,   53,   53,  971,  973,
-     1595,  983,  981, 1063, 1293,   55,   55, 1062,   55,   55,
-      764,  794, 1728,  795,  795,  795,  795,  795,  795,  795,
-      977, 1728, 1077, 1073,  795, 1186, 1595,   55,  936, 1063,
-      795,  795,  795,  795,  795,  795, 1010, 1011, 1011, 1011,
-     1011, 1011, 1011, 1064, 1064,   55,   55, 1728,   53,  796,
-      797,  797,  797,  797,  797,  797,  797, 1065, 1728,  930,
-     1074,  797,   55,   55,   55, 1079, 1151,  797,  797,  797,
-      797,  797,  797, 1018, 1019, 1019, 1019, 1019, 1019, 1019,
+     1614, 1096, 1201, 1105,  796,  796,  796,  796,  796,  796,
+       49,  796,  796,  796,  796,  796,  796,  796,  799,  800,
+      800,  800,  800,  800,  800, 1614, 1065,  858,  937,  801,
+     1158, 1105,   51,   51,  801,  801,  801,  801,  801,  801,
+      535,  635,  635,  635,  635,  635,  635,  635,  711,   51,
+       51,  739,  636, 1185,   51, 1186, 1059,  636,  636,  636,
+      636,  636,  636,  802,  803,  803,  803,  803,  803,  803,
+     1060,   51,  933,  931,  804,  925, 1189,   51, 1146,  804,
+      804,  804,  804,  804,  804,  544,  647,  647,  647,  647,
+      647,  647,  647,  714,   51, 1060, 1102,  648,  728,   51,
 
-       55,   55, 1080, 1065, 1728,   53,  706,  706,  706,  706,
-      706,  706,  706, 1022, 1023, 1023, 1023, 1023, 1023, 1023,
-     1030, 1031, 1031, 1031, 1031, 1031, 1031, 1033, 1034, 1034,
-     1034, 1034, 1034, 1034, 1037, 1038, 1038, 1038, 1038, 1038,
-     1038,   53,  707,  707,  707,  707,  707,  707,  707, 1107,
-      733,  926,  924,  707,  919, 1596, 1613, 1619, 1139,  707,
-      707,  707,  707,  707,  707,  798,  353,  353,  353,  353,
-      353,  353,  353,  267,  800,  800,  800,  800,  800,  800,
-      800, 1596, 1613, 1619, 1104,  801,  724,  915,  910, 1128,
-     1101,  801,  801,  801,  801,  801,  801,   53,  801,  801,
+     1194, 1059,  648,  648,  648,  648,  648,  648,  805,  806,
+      806,  806,  806,  806,  806, 1723,   51, 1192,  921,  807,
+      919,   51,   51,  914,  807,  807,  807,  807,  807,  807,
+      811,  812,  812,  812,  812,  812,  812,  448,   51,   51,
+     1723,  813, 1195, 1134,   51, 1099,  813,  813,  813,  813,
+      813,  813,  719,  816,  816,  816,  816,  816,  816,  816,
+      721,   51, 1293,  719,  817,  910,   51,   51,  905,  817,
+      817,  817,  817,  817,  817,  818,  819,  819,  819,  819,
+      819,  819,  448,   51,   51, 1294,  820, 1123, 1096,   51,
+     1114,  820,  820,  820,  820,  820,  820,  728,  828,  828,
 
-      801,  801,  801,  801,  801,  804,  805,  805,  805,  805,
-      805,  805, 1119, 1006,  991, 1110,  806, 1107, 1104,   55,
-       55,   55,  806,  806,  806,  806,  806,  806,  540,  640,
-      640,  640,  640,  640,  640,  640,  716,   55,   55,   55,
-      641, 1315, 1101, 1316,   55, 1122,  641,  641,  641,  641,
-      641,  641,  807,  808,  808,  808,  808,  808,  808, 1123,
-     1302, 1099,   55,  809,  991,  861,   55, 1070,   55,  809,
-      809,  809,  809,  809,  809,  549,  652,  652,  652,  652,
-      652,  652,  652,  719,   55, 1123,   55,  653,  863,   55,
-       55,   55, 1122,  653,  653,  653,  653,  653,  653,  810,
+      828,  828,  828,  828,  828,  730,   51, 1295, 1296,  829,
+     1001,   51,   51,   51,  829,  829,  829,  829,  829,  829,
+      830,  831,  831,  831,  831,  831,  831,  448,   51,   51,
+       51,  832,  986, 1299, 1105,   51,  832,  832,  832,  832,
+      832,  832,  739,  843,  843,  843,  843,  843,  843,  843,
+      741, 1297,   51, 1102,  844, 1099, 1310,   51,   51,  844,
+      844,  844,  844,  844,  844,  845,  846,  846,  846,  846,
+      846,  846,  448, 1096,   51,   51,  847, 1094,  986, 1311,
+       51,  847,  847,  847,  847,  847,  847,  659,  854,  854,
+      854,  854,  854,  854,  854,  661,  856,   51, 1065,  855,
 
-      811,  811,  811,  811,  811,  811, 1728,   55,   55,   55,
-      812,  664,   55, 1395, 1404, 1306,  812,  812,  812,  812,
-      812,  812,  816,  817,  817,  817,  817,  817,  817,  453,
-       55,  857, 1728,  818,  855,  944,  905,   55,   55,  818,
-      818,  818,  818,  818,  818,  724,  821,  821,  821,  821,
-      821,  821,  821,  726, 1401,   55,   55,  822,  932,  902,
-       55,   55,  921,  822,  822,  822,  822,  822,  822,  823,
-      824,  824,  824,  824,  824,  824,  453, 1409,   55,   55,
-      825, 1476, 1477,   55,   55,   55,  825,  825,  825,  825,
-      825,  825,  733,  833,  833,  833,  833,  833,  833,  833,
+      858,  659,  852,   51,  855,  855,  855,  855,  855,  855,
+      856,  857,  857,  857,  857,  857,  857,  857,  858,   51,
+       51, 1117,  859,  850,  860,  939,  900,  859,  859,  859,
+      859,  859,  859, 1087,   51, 1118,   51, 1017, 1018, 1018,
+     1018, 1018, 1018, 1018,   51,  975,  927,   51, 1117,  860,
+       51,   51,  884,  884,  884,  884,  884,  884,  884, 1079,
+     1118,   51, 1723,  884,   51, 1074,   51,   51,  884,  884,
+      884,  884,  884,  884,  885,  885,  885,  885,  885,  885,
+      885, 1184, 1075,   51,  897,  885,   51, 1723,   51,   51,
+      885,  885,  885,  885,  885,  885,  886,  887,  887,  887,
 
-      735,   55,   55,   55,  834,  899, 1479,  912,   55, 1006,
-      834,  834,  834,  834,  834,  834,  835,  836,  836,  836,
-      836,  836,  836,  453,  991, 1478,   55,  837,  905,  902,
-     1481,   55,   55,  837,  837,  837,  837,  837,  837,  744,
-      848,  848,  848,  848,  848,  848,  848,  746,  899,   55,
-       55,  849,  991, 1482,   55,   55, 1483,  849,  849,  849,
-      849,  849,  849,  850,  851,  851,  851,  851,  851,  851,
-      453,  863,   55,   55,  852,  666, 1486,   55, 1489,   55,
-      852,  852,  852,  852,  852,  852,  664,  859,  859,  859,
-      859,  859,  859,  859,  666,   55,  744,   55,  860,  944,
+      887,  887,  887,   51,  916,   51,   51,  888,  894,   51,
+       51, 1083,  888,  888,  888,  888,  888,  888,  262,  889,
+      889,  889,  889,  889,  889,  889,   51,   51,  907, 1001,
+      890,  986, 1390,  900, 1301,  890,  890,  890,  890,  890,
+      890,   49,  890,  890,  890,  890,  890,  890,  890,  719,
+      893,  893,  893,  893,  893,  893,  893,  894,  897,  894,
+      986,  895,  858,  723,  661,  739,  895,  895,  895,  895,
+      895,  895, 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1028,
+     1029, 1029, 1029, 1029, 1029, 1029,  939,   51,  723,  728,
+      896,  896,  896,  896,  896,  896,  896,  897,  900,  544,
 
-      905,   55,  549, 1536,  860,  860,  860,  860,  860,  860,
-      861,  862,  862,  862,  862,  862,  862,  862,  863,   55,
-     1546,  740,  864,  738,  865,  733,  932,  902,  864,  864,
-      864,  864,  864,  864, 1046, 1047, 1047, 1047, 1047, 1047,
-     1047, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1131,   55,
-      865,   55, 1131,  889,  889,  889,  889,  889,  889,  889,
-      540,  729, 1132,  724,  889,  921, 1728,   55,   55,   55,
-      889,  889,  889,  889,  889,  889,  890,  890,  890,  890,
-      890,  890,  890, 1081,  899,  912,   55,  890, 1132,   55,
-       55,   55, 1728,  890,  890,  890,  890,  890,  890,  891,
+      735,  898,  733,  732,   51,  728,  898,  898,  898,  898,
+      898,  898, 1032, 1033, 1033, 1033, 1033, 1033, 1033, 1041,
+     1042, 1042, 1042, 1042, 1042, 1042,  927,   51,  732,  739,
+      899,  899,  899,  899,  899,  899,  899,  900,  897,  535,
+      724,  901,  719,  743,   51,  916,  901,  901,  901,  901,
+      901,  901, 1044, 1045, 1045, 1045, 1045, 1045, 1045, 1048,
+     1049, 1049, 1049, 1049, 1049, 1049, 1126,   51,  743,  905,
+      906,  906,  906,  906,  906,  906,  906,  907,  894,  907,
+     1127,  908,  904,  909,   51,   51,  908,  908,  908,  908,
+      908,  908,  944,  944,  944,  944,  944,  944,  944, 1070,
 
-      892,  892,  892,  892,  892,  892, 1189,   55,   55,   55,
-      893, 1549,   55,   55,   55,   55,  893,  893,  893,  893,
-      893,  893,  267,  894,  894,  894,  894,  894,  894,  894,
-       55,   55,   55,   55,  895,  909, 1577, 1584,  815, 1396,
-      895,  895,  895,  895,  895,  895,   53,  895,  895,  895,
-      895,  895,  895,  895,  724,  898,  898,  898,  898,  898,
-      898,  898,  899,  803,  905,  902,  900,  899,  728,  897,
-      803,  664,  900,  900,  900,  900,  900,  900, 1053, 1054,
-     1054, 1054, 1054, 1054, 1054,  949,  949,  949,  949,  949,
-      949,  949,   55,   55,  728,  733,  901,  901,  901,  901,
+     1071,  810,   51,  798,  900, 1127, 1126,   51,  909,  719,
+      912,  912,  912,  912,  912,  912,  912,  894, 1076,  897,
+     1723,  913,  894,  892,   51,   51,  913,  913,  913,  913,
+      913,  913,  914,  915,  915,  915,  915,  915,  915,  915,
+      916, 1078,   51, 1128,  917, 1723,  918, 1128, 1063,  917,
+      917,  917,  917,  917,  917,  798, 1065, 1129,  659, 1089,
+      858, 1723, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1138,
+      661,  918,  728,  923,  923,  923,  923,  923,  923,  923,
+      897,  463, 1129, 1139,  924,  655, 1723,   51,  653,  924,
+      924,  924,  924,  924,  924,  925,  926,  926,  926,  926,
 
-      901,  901,  901,  902,   55,   55, 1133,  903,  863,  737,
-       55,   55,   55,  903,  903,  903,  903,  903,  903,  666,
-     1134,  468,   55,   55,  660, 1075, 1076,   55, 1083,   55,
-       55,   55,  658, 1182, 1183,  737,  744,  904,  904,  904,
-      904,  904,  904,  904,  905,   55, 1134,   55,  906,   55,
-      748, 1537, 1133,  746,  906,  906,  906,  906,  906,  906,
-     1092, 1143, 1094, 1185,  719,  735, 1728, 1031, 1031, 1031,
-     1031, 1031, 1031, 1031, 1143, 1144,  748,  910,  911,  911,
-      911,  911,  911,  911,  911,  912,   55,   55, 1728,  913,
-      716,  914, 1728, 1145, 1145,  913,  913,  913,  913,  913,
+      926,  926,  926,  927,   51, 1138, 1140,  928, 1139,  929,
+     1140,  741,  928,  928,  928,  928,  928,  928, 1180, 1723,
+     1141,  714,  730,  711, 1723, 1042, 1042, 1042, 1042, 1042,
+     1042, 1042, 1150,   51,  929,  739,  935,  935,  935,  935,
+      935,  935,  935,  900, 1723, 1141, 1151,  936,  721, 1723,
+       51,  810,  936,  936,  936,  936,  936,  936,  937,  938,
+      938,  938,  938,  938,  938,  938,  939,   51, 1150, 1152,
+      940, 1151,  941, 1152, 1396,  940,  940,  940,  940,  940,
+      940,  798, 1723, 1153,   51,  714,  711, 1723, 1162, 1163,
+     1163, 1163, 1163, 1163, 1163, 1177,  798,  941,  856,  952,
 
-      913, 1144,  726,  815,   55,   55,  803, 1146, 1728,  719,
-       55,  716,  803, 1155, 1728, 1155, 1184,  914,  724,  917,
-      917,  917,  917,  917,  917,  917,  899, 1156,   55, 1728,
-      918,   53,   53, 1146, 1728,   53,  918,  918,  918,  918,
-      918,  918,  919,  920,  920,  920,  920,  920,  920,  920,
-      921, 1581,  790, 1156,  922, 1728,  923,   55,   55, 1157,
-      922,  922,  922,  922,  922,  922, 1047, 1047, 1047, 1047,
-     1047, 1047, 1047, 1158,   53,   55,   55,   53, 1157,   55,
-       55,  772,  923,  733,  928,  928,  928,  928,  928,  928,
-      928,  902, 1728, 1310, 1192,  929,  666,   55,   55, 1158,
+      952,  952,  952,  952,  952,  952,  858, 1723, 1153,   49,
+      953,   49, 1723,   51, 1282,  953,  953,  953,  953,  953,
+      953,  954,  955,  955,  955,  955,  955,  955, 1283,   49,
+       51,  785,  956,   49,   49,   51,  767,  956,  956,  956,
+      956,  956,  956,   51, 1183,  979,  979,  979,  979,  979,
+      979,  979,   51, 1283,  661,  465,  979, 1399,   51,   51,
+       51,  979,  979,  979,  979,  979,  979,  980,  980,  980,
+      980,  980,  980,  980, 1112,   51,   51,  544,  980,  741,
+      714,   51, 1318,  980,  980,  980,  980,  980,  980,  614,
+      981,  981,  981,  981,  981,  981,  981, 1404,   51, 1473,
 
-      470,  929,  929,  929,  929,  929,  929,  930,  931,  931,
-      931,  931,  931,  931,  931,  932, 1311, 1490, 1728,  933,
-      549,  934,  746,  719,  365,  933,  933,  933,  933,  933,
-      933, 1167, 1168, 1168, 1168, 1168, 1168, 1168, 1170, 1171,
-     1171, 1171, 1171, 1171, 1171, 1287,   55,  934,  744,  940,
-      940,  940,  940,  940,  940,  940,  905,  545,  540, 1288,
-      941,  735,  716,  726,   55, 1201,  941,  941,  941,  941,
-      941,  941,  942,  943,  943,  943,  943,  943,  943,  943,
-      944, 1202, 1203,  723,  945, 1288,  946,   55,   55,   55,
-      945,  945,  945,  945,  945,  945, 1174, 1175, 1175, 1175,
+      360,  982, 1474,  430,  540,  535,  982,  982,  982,  982,
+      982,  982, 1165, 1166, 1166, 1166, 1166, 1166, 1166, 1169,
+     1170, 1170, 1170, 1170, 1170, 1170,   51,   51,  430,  982,
+      982,  982,  982,  982,  982,  982,  730,  711,  721,  718,
+      982,  629,  620,   51,   51,  982,  982,  982,  982,  982,
+      982,  262,  983,  983,  983,  983,  983,  983,  983, 1188,
+      714,  711, 1181,  984,  709,  620,  610,  608,  984,  984,
+      984,  984,  984,  984,   49,  984,  984,  984,  984,  984,
+      984,  984,  987,  988,  988,  988,  988,  988,  988, 1121,
+      698,  697,  696,  989,  695,  694,   51, 1321,  989,  989,
 
-     1175, 1175, 1175,  634,  625,   55,   55,   55,   55, 1287,
-     1289,  719,  946,  861,  957,  957,  957,  957,  957,  957,
-      957,  863, 1193, 1728, 1290,  958,   55, 1544,   55,   55,
-     1289,  958,  958,  958,  958,  958,  958,  959,  960,  960,
-      960,  960,  960,  960, 1728, 1314,   55,   55,  961, 1728,
-     1290,   55,  716,   55,  961,  961,  961,  961,  961,  961,
-       55, 1188,  984,  984,  984,  984,  984,  984,  984,   55,
-     1728,   55, 1602,  984, 1603,   55,   55,   55,   55,  984,
-      984,  984,  984,  984,  984,  985,  985,  985,  985,  985,
-      985,  985,  714,   55,   55,   55,  985, 1604,   55,   55,
+      989,  989,  989,  989,  719,  816,  816,  816,  816,  816,
+      816,  816,  894,   51,  693,  692,  817, 1476,   51,   51,
+     1282,  817,  817,  817,  817,  817,  817,  990,  991,  991,
+      991,  991,  991,  991, 1723,   51,   51,  691,  992, 1471,
+     1484,   51,  690,  992,  992,  992,  992,  992,  992,  728,
+      828,  828,  828,  828,  828,  828,  828,  897,   51, 1723,
+      689,  829, 1477,   51,   51, 1284,  829,  829,  829,  829,
+      829,  829,  993,  994,  994,  994,  994,  994,  994, 1285,
+       51,   51,  688,  995, 1472,  687, 1478,  680,  995,  995,
+      995,  995,  995,  995,  739,  843,  843,  843,  843,  843,
 
-       55,   55,  985,  985,  985,  985,  985,  985,  619,  986,
-      986,  986,  986,  986,  986,  986,   55,   55,   55,   55,
-      987, 1610,  435,  625,  615, 1491,  987,  987,  987,  987,
-      987,  987, 1196, 1198, 1229, 1230, 1230, 1230, 1230, 1230,
-     1230, 1235, 1236, 1236, 1236, 1236, 1236, 1236,  435,  987,
-      987,  987,  987,  987,  987,  987,  613,  703,  702,  701,
-      987,  700,   55,   55,   55,   55,  987,  987,  987,  987,
-      987,  987,  267,  988,  988,  988,  988,  988,  988,  988,
-       55,   55,   55,   55,  989, 1624,  699, 1626, 1627, 1535,
-      989,  989,  989,  989,  989,  989,   53,  989,  989,  989,
+      843,  843,  900,  679, 1285,  678,  844,  677,   51,   51,
+     1284,  844,  844,  844,  844,  844,  844,  996,  997,  997,
+      997,  997,  997,  997, 1723,   51,   51,  676,  998, 1481,
+      675,   51,  674,  998,  998,  998,  998,  998,  998, 1002,
+     1003, 1003, 1003, 1003, 1003, 1003,  448, 1532,   51, 1723,
+     1004, 1544,  673,   51,   51, 1004, 1004, 1004, 1004, 1004,
+     1004,  905, 1007, 1007, 1007, 1007, 1007, 1007, 1007,  907,
+       51,   51,  672, 1008,  671,  670,   51,  669, 1008, 1008,
+     1008, 1008, 1008, 1008, 1009, 1010, 1010, 1010, 1010, 1010,
+     1010,  448, 1539,   51, 1541, 1011,  668,  667,   51,   51,
 
-      989,  989,  989,  989,  992,  993,  993,  993,  993,  993,
-      993,  698,  697,  696,  695,  994,  694,  693,   55,   55,
-       55,  994,  994,  994,  994,  994,  994,  724,  821,  821,
-      821,  821,  821,  821,  821,  899,   55,   55,   55,  822,
-      692,  685, 1642,   55, 1345,  822,  822,  822,  822,  822,
-      822,  995,  996,  996,  996,  996,  996,  996, 1346, 1634,
-      684,   55,  997,  683,  682,   55, 1643,   55,  997,  997,
-      997,  997,  997,  997,  733,  833,  833,  833,  833,  833,
-      833,  833,  902,   55, 1346,   55,  834,  681, 1644,   55,
-       55, 1345,  834,  834,  834,  834,  834,  834,  998,  999,
+     1011, 1011, 1011, 1011, 1011, 1011,  914, 1019, 1019, 1019,
+     1019, 1019, 1019, 1019,  916,   51,   51,  666, 1020,  665,
+       51, 1572,   51, 1020, 1020, 1020, 1020, 1020, 1020, 1021,
+     1022, 1022, 1022, 1022, 1022, 1022,  448,   51,  664,   51,
+     1023,  463,  661,  465, 1579, 1023, 1023, 1023, 1023, 1023,
+     1023,  925, 1034, 1034, 1034, 1034, 1034, 1034, 1034,  927,
+     1576,  459,  546, 1035,  530,   51,   51,   51, 1035, 1035,
+     1035, 1035, 1035, 1035, 1036, 1037, 1037, 1037, 1037, 1037,
+     1037,  448,   51,   51,   51, 1038,  537, 1597,   51,   51,
+     1038, 1038, 1038, 1038, 1038, 1038,  937, 1050, 1050, 1050,
 
-      999,  999,  999,  999,  999, 1728, 1635,   55,   55, 1000,
-      680,  679, 1646,  678,   55, 1000, 1000, 1000, 1000, 1000,
-     1000,  744,  848,  848,  848,  848,  848,  848,  848,  905,
-      677, 1728,   55,  849,  676,  675,   55,   55, 1350,  849,
-      849,  849,  849,  849,  849, 1001, 1002, 1002, 1002, 1002,
-     1002, 1002, 1351, 1636,   55,   55, 1003, 1655,   55, 1657,
-      674,  673, 1003, 1003, 1003, 1003, 1003, 1003, 1007, 1008,
-     1008, 1008, 1008, 1008, 1008,  453,   55,  672, 1351, 1009,
-      671, 1659,   55,   55,   55, 1009, 1009, 1009, 1009, 1009,
-     1009,  910, 1012, 1012, 1012, 1012, 1012, 1012, 1012,  912,
+     1050, 1050, 1050, 1050,  939,   51,   51,  629, 1051, 1598,
+       51,   51,   51, 1051, 1051, 1051, 1051, 1051, 1051, 1052,
+     1053, 1053, 1053, 1053, 1053, 1053,  448,   51,   51,   51,
+     1054, 1599, 1605,   51,   51, 1054, 1054, 1054, 1054, 1054,
+     1054,  856, 1061, 1061, 1061, 1061, 1061, 1061, 1061,  858,
+       51,   51,  620, 1062, 1619,  530, 1621,  620, 1062, 1062,
+     1062, 1062, 1062, 1062, 1063, 1064, 1064, 1064, 1064, 1064,
+     1064, 1064, 1065,   51,   51,  614, 1066,   51, 1067, 1340,
+       51, 1066, 1066, 1066, 1066, 1066, 1066, 1132, 1144,  614,
+       51,   51, 1156, 1341,   51, 1324, 1327,   51, 1196,   51,
 
-       55,   55,   55, 1013,  670, 1661,   55,  669,  468, 1013,
-     1013, 1013, 1013, 1013, 1013, 1014, 1015, 1015, 1015, 1015,
-     1015, 1015,  453, 1669,   55, 1662, 1016,  666,  470,   55,
-      464,   55, 1016, 1016, 1016, 1016, 1016, 1016,  919, 1024,
-     1024, 1024, 1024, 1024, 1024, 1024,  921,   55, 1663,   55,
-     1025,  551, 1672,   55,   55,  535, 1025, 1025, 1025, 1025,
-     1025, 1025, 1026, 1027, 1027, 1027, 1027, 1027, 1027,  453,
-      542,   55,   55, 1028,  634,  625, 1680, 1681,   55, 1028,
-     1028, 1028, 1028, 1028, 1028,  930, 1039, 1039, 1039, 1039,
-     1039, 1039, 1039,  932,  535,  625,   55, 1040,  619,   55,
+     1330, 1178, 1179, 1067,   51,  614, 1090, 1090, 1090, 1090,
+     1090, 1090, 1090, 1187, 1197, 1198,   51, 1091, 1341,  607,
+      606,   51, 1091, 1091, 1091, 1091, 1091, 1091,   49, 1091,
+     1091, 1091, 1091, 1091, 1091, 1091,   51,  262, 1092, 1092,
+     1092, 1092, 1092, 1092, 1092,  605,   51,   51,   51,  604,
+       51,  603,   51,   51,  905, 1095, 1095, 1095, 1095, 1095,
+     1095, 1095, 1096,   51,   51,   51, 1097,   51,  909,   51,
+       51, 1097, 1097, 1097, 1097, 1097, 1097, 1303, 1191, 1193,
+     1224, 1225, 1225, 1225, 1225, 1225, 1225,   51, 1309,  602,
+       51,  601,   51,  909,  914, 1098, 1098, 1098, 1098, 1098,
 
-       55, 1686,  619, 1040, 1040, 1040, 1040, 1040, 1040, 1041,
-     1042, 1042, 1042, 1042, 1042, 1042,  453,   55,   55,  612,
-     1043, 1687,  611,   55,   55,   55, 1043, 1043, 1043, 1043,
-     1043, 1043,  942, 1055, 1055, 1055, 1055, 1055, 1055, 1055,
-      944,   55,   55,   55, 1056, 1693, 1690,   55,   55,  610,
-     1056, 1056, 1056, 1056, 1056, 1056, 1057, 1058, 1058, 1058,
-     1058, 1058, 1058,  453,  609,   55,   55, 1059,  608,  607,
-       55, 1700,   55, 1059, 1059, 1059, 1059, 1059, 1059,  861,
-     1066, 1066, 1066, 1066, 1066, 1066, 1066,  863,   55, 1694,
-       55, 1067,  606,  605,   55, 1708,   55, 1067, 1067, 1067,
-
-     1067, 1067, 1067, 1068, 1069, 1069, 1069, 1069, 1069, 1069,
-     1069, 1070,   55,  604,   55, 1071,  603, 1072,  602,  338,
-      239, 1071, 1071, 1071, 1071, 1071, 1071, 1239, 1240, 1240,
-     1240, 1240, 1240, 1240, 1245, 1246, 1246, 1246, 1246, 1246,
-     1246,   55,   55, 1072,   55,  619, 1095, 1095, 1095, 1095,
-     1095, 1095, 1095,  601,  600,  599,  598, 1096,  597,   55,
-       55,  596,   55, 1096, 1096, 1096, 1096, 1096, 1096,   53,
-     1096, 1096, 1096, 1096, 1096, 1096, 1096,   55,  267, 1097,
-     1097, 1097, 1097, 1097, 1097, 1097, 1248, 1249, 1249, 1249,
-     1249, 1249, 1249,   55,   55,   55,  910, 1100, 1100, 1100,
-
-     1100, 1100, 1100, 1100, 1101,  595,  594,  593, 1102,  592,
-      914,   55,   55,  591, 1102, 1102, 1102, 1102, 1102, 1102,
-     1252, 1253, 1253, 1253, 1253, 1253, 1253, 1259, 1260, 1260,
-     1260, 1260, 1260, 1260,   55, 1710,  914,  919, 1103, 1103,
-     1103, 1103, 1103, 1103, 1103, 1104,  590,  589,  581, 1105,
-      578,  923,   55,  575,  574, 1105, 1105, 1105, 1105, 1105,
-     1105, 1262, 1263, 1263, 1263, 1263, 1263, 1263, 1266, 1267,
-     1267, 1267, 1267, 1267, 1267,   55, 1714,  923,  930, 1106,
-     1106, 1106, 1106, 1106, 1106, 1106, 1107,  573,  572,  571,
-     1108,  570,  934,   55,  569,  568, 1108, 1108, 1108, 1108,
-
-     1108, 1108, 1273, 1274, 1274, 1274, 1274, 1274, 1274, 1276,
-     1277, 1277, 1277, 1277, 1277, 1277,   55,   55,  934,  942,
-     1109, 1109, 1109, 1109, 1109, 1109, 1109, 1110,  567,  566,
-      470, 1111,  279,  946,   55,   55,  453, 1111, 1111, 1111,
-     1111, 1111, 1111, 1280, 1281, 1281, 1281, 1281, 1281, 1281,
-     1168, 1168, 1168, 1168, 1168, 1168, 1168,  365,  551,  946,
-     1113, 1114, 1114, 1114, 1114, 1114, 1114, 1115,  535,  542,
-      453, 1116,  539,  450,  444,   55,   55, 1116, 1116, 1116,
-     1116, 1116, 1116, 1117, 1118, 1118, 1118, 1118, 1118, 1118,
-     1118, 1119,   55,   55,   55, 1120,   55, 1121,   55, 1350,
+     1098, 1098, 1099,  600, 1305,  599, 1100,   51,  918,   51,
+      598, 1100, 1100, 1100, 1100, 1100, 1100, 1230, 1231, 1231,
+     1231, 1231, 1231, 1231, 1234, 1235, 1235, 1235, 1235, 1235,
+     1235,  597,   51,  918,  925, 1101, 1101, 1101, 1101, 1101,
+     1101, 1101, 1102,  333,  234,  596, 1103,  595,  929,   51,
+      594, 1103, 1103, 1103, 1103, 1103, 1103, 1240, 1241, 1241,
+     1241, 1241, 1241, 1241, 1243, 1244, 1244, 1244, 1244, 1244,
+     1244,  593,   51,  929,  937, 1104, 1104, 1104, 1104, 1104,
+     1104, 1104, 1105,  592,  591,  590, 1106,  589,  941,   51,
+      588, 1106, 1106, 1106, 1106, 1106, 1106, 1247, 1248, 1248,
 
-       55, 1120, 1120, 1120, 1120, 1120, 1120, 1308, 1305,  535,
-       55,  533,  444, 1728,   55,  436,   55,   55,   55,  430,
-      520, 1303,  519, 1121,  910, 1124, 1124, 1124, 1124, 1124,
-     1124, 1124, 1101, 1312, 1583,   55, 1125, 1402, 1717, 1728,
-       55,   55, 1125, 1125, 1125, 1125, 1125, 1125, 1126, 1127,
-     1127, 1127, 1127, 1127, 1127, 1127, 1128,   55,   55,   55,
-     1129,  518, 1130,  517,  516,   55, 1129, 1129, 1129, 1129,
-     1129, 1129, 1309, 1313,  515,   55, 1337, 1338, 1338, 1338,
-     1338, 1338, 1338,   55, 1352,   55, 1307,  514, 1130,  919,
-     1135, 1135, 1135, 1135, 1135, 1135, 1135, 1104, 1353,  513,
+     1248, 1248, 1248, 1248, 1254, 1255, 1255, 1255, 1255, 1255,
+     1255,   51, 1340,  941, 1108, 1109, 1109, 1109, 1109, 1109,
+     1109, 1110,  587,  586,  585, 1111, 1723,  584,   51,  576,
+     1111, 1111, 1111, 1111, 1111, 1111, 1112, 1113, 1113, 1113,
+     1113, 1113, 1113, 1113, 1114,  573, 1306,  570, 1115,  569,
+     1116, 1723,  568, 1115, 1115, 1115, 1115, 1115, 1115, 1257,
+     1258, 1258, 1258, 1258, 1258, 1258, 1261, 1262, 1262, 1262,
+     1262, 1262, 1262, 1345,   51, 1116,  905, 1119, 1119, 1119,
+     1119, 1119, 1119, 1119, 1096,  567,  566, 1346, 1120,  565,
+      564,   51,   51, 1120, 1120, 1120, 1120, 1120, 1120, 1121,
 
-     1403, 1136,  512,   55,  511,   55,  510, 1136, 1136, 1136,
-     1136, 1136, 1136, 1137, 1138, 1138, 1138, 1138, 1138, 1138,
-     1138, 1139, 1405,   55, 1353, 1140,  509, 1141, 1352,  508,
-      507, 1140, 1140, 1140, 1140, 1140, 1140, 1317,  506,  503,
-      502,  499, 1728, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
-      498, 1358,   55, 1141,  930, 1147, 1147, 1147, 1147, 1147,
-     1147, 1147, 1107,  497,  496, 1359, 1148,  495, 1728,  120,
-       55,  494, 1148, 1148, 1148, 1148, 1148, 1148, 1149, 1150,
-     1150, 1150, 1150, 1150, 1150, 1150, 1151, 1408, 1358, 1360,
-     1152, 1359, 1153, 1360,  493,  481, 1152, 1152, 1152, 1152,
+     1122, 1122, 1122, 1122, 1122, 1122, 1122, 1123, 1307,   51,
+      563, 1124, 1346, 1125, 1622,  562, 1124, 1124, 1124, 1124,
+     1124, 1124, 1268, 1269, 1269, 1269, 1269, 1269, 1269, 1271,
+     1272, 1272, 1272, 1272, 1272, 1272, 1345,   51, 1125,  914,
+     1130, 1130, 1130, 1130, 1130, 1130, 1130, 1099,  561,  465,
+     1723, 1131,  274,  448,   51, 1394, 1131, 1131, 1131, 1131,
+     1131, 1131, 1132, 1133, 1133, 1133, 1133, 1133, 1133, 1133,
+     1134,  360, 1395,  546, 1135, 1723, 1136,  530,  537, 1135,
+     1135, 1135, 1135, 1135, 1135, 1275, 1276, 1276, 1276, 1276,
+     1276, 1276, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1347,
 
-     1152, 1152, 1728, 1361,  480,  479,  478, 1728, 1260, 1260,
-     1260, 1260, 1260, 1260, 1260,  477, 1366,   55, 1153,  942,
-     1159, 1159, 1159, 1159, 1159, 1159, 1159, 1110, 1728, 1361,
-     1367, 1160,  476, 1728,  475,   55,  474, 1160, 1160, 1160,
-     1160, 1160, 1160, 1161, 1162, 1162, 1162, 1162, 1162, 1162,
-     1162, 1163, 1475, 1366, 1368, 1164, 1367, 1165, 1368,  473,
-      277, 1164, 1164, 1164, 1164, 1164, 1164, 1728, 1369,  470,
-      279,  453, 1728, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
-      367, 1374,   55, 1165, 1068, 1176, 1176, 1176, 1176, 1176,
-     1176, 1176, 1070, 1728, 1369, 1375, 1177,  450, 1728,  444,
+       51, 1136,  925, 1142, 1142, 1142, 1142, 1142, 1142, 1142,
+     1102,  448,  534, 1348, 1143,  445,  439,   51,   51, 1143,
+     1143, 1143, 1143, 1143, 1143, 1144, 1145, 1145, 1145, 1145,
+     1145, 1145, 1145, 1146,   51,   51, 1397, 1147, 1348, 1148,
+     1218, 1288, 1147, 1147, 1147, 1147, 1147, 1147, 1408, 1290,
+     1300,   51, 1332, 1333, 1333, 1333, 1333, 1333, 1333,   51,
+     1347,   51, 1298,   51, 1148,  937, 1154, 1154, 1154, 1154,
+     1154, 1154, 1154, 1105, 1723,  530,   51, 1155,   51, 1650,
+       51,   51, 1155, 1155, 1155, 1155, 1155, 1155, 1156, 1157,
+     1157, 1157, 1157, 1157, 1157, 1157, 1158,   51,   51, 1723,
 
-       55, 1374, 1177, 1177, 1177, 1177, 1177, 1177, 1178, 1179,
-     1179, 1179, 1179, 1179, 1179, 1728,  444, 1547,  437, 1180,
-      437, 1375,   55,  429,   55, 1180, 1180, 1180, 1180, 1180,
-     1180,   55,  619, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
-       55, 1728,   55,  420,  989, 1715,  419, 1719,  416,   55,
-      989,  989,  989,  989,  989,  989,   53,  989,  989,  989,
-      989,  989,  989,  989,   55,  267, 1097, 1097, 1097, 1097,
-     1097, 1097, 1097,  415,   55,   55, 1376, 1376,   55,   55,
-      414, 1421,   55, 1207, 1208, 1208, 1208, 1208, 1208, 1208,
-     1377, 1728,   55,   55, 1209, 1422,   55,   55, 1399,  413,
+     1159, 1629, 1160, 1288,  528, 1159, 1159, 1159, 1159, 1159,
+     1159, 1723, 1304,  439,   51, 1241, 1241, 1241, 1241, 1241,
+     1241, 1241,   51,  431, 1353, 1302,   51, 1160, 1063, 1171,
+     1171, 1171, 1171, 1171, 1171, 1171, 1065,  425, 1354,   51,
+     1172,  515,  514,   51, 1353, 1172, 1172, 1172, 1172, 1172,
+     1172, 1173, 1174, 1174, 1174, 1174, 1174, 1174, 1723, 1485,
+     1398,  513, 1175, 1354,  512,   51,  511, 1175, 1175, 1175,
+     1175, 1175, 1175,   51,  614, 1199, 1199, 1199, 1199, 1199,
+     1199, 1199,   51, 1723,  510,  509,  984, 1637,  508,  507,
+       51,  984,  984,  984,  984,  984,  984,   49,  984,  984,
 
-     1209, 1209, 1209, 1209, 1209, 1209,  910, 1012, 1012, 1012,
-     1012, 1012, 1012, 1012, 1101, 1400, 1377, 1728, 1013,  412,
-      411, 1422,  410, 1421, 1013, 1013, 1013, 1013, 1013, 1013,
-     1210, 1211, 1211, 1211, 1211, 1211, 1211, 1728,  409,  408,
-      407, 1212,  406,  405,  404,  403,   55, 1212, 1212, 1212,
-     1212, 1212, 1212,  919, 1024, 1024, 1024, 1024, 1024, 1024,
-     1024, 1104,  402, 1728,   55, 1025,  401,  400,  395,  394,
-     1468, 1025, 1025, 1025, 1025, 1025, 1025, 1213, 1214, 1214,
-     1214, 1214, 1214, 1214, 1469, 1698,  393,  392, 1215,  391,
-      320,  390,  389,   55, 1215, 1215, 1215, 1215, 1215, 1215,
+      984,  984,  984,  984,  984,   51,  262, 1092, 1092, 1092,
+     1092, 1092, 1092, 1092,  506,   51, 1355, 1355,  505, 1361,
+       51, 1361,   51, 1202, 1203, 1203, 1203, 1203, 1203, 1203,
+     1356, 1723,   51, 1362, 1204, 1723, 1652,   51,  504, 1204,
+     1204, 1204, 1204, 1204, 1204,  905, 1007, 1007, 1007, 1007,
+     1007, 1007, 1007, 1096, 1403, 1356, 1723, 1008, 1362,   51,
+     1723, 1363, 1008, 1008, 1008, 1008, 1008, 1008, 1205, 1206,
+     1206, 1206, 1206, 1206, 1206, 1364,   51,  503,  502, 1207,
+      501, 1638,   51,  498, 1207, 1207, 1207, 1207, 1207, 1207,
+      914, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1099,   51,
 
-      930, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1107,  388,
-     1469,   55, 1040,  387,  386,  385,  379, 1468, 1040, 1040,
-     1040, 1040, 1040, 1040, 1216, 1217, 1217, 1217, 1217, 1217,
-     1217, 1728, 1723,  279,  367, 1218,  275,  364,  272,  360,
-      266, 1218, 1218, 1218, 1218, 1218, 1218,  942, 1055, 1055,
-     1055, 1055, 1055, 1055, 1055, 1110,  260, 1728,  143, 1056,
-      348,  347,  346,  341, 1470, 1056, 1056, 1056, 1056, 1056,
-     1056, 1219, 1220, 1220, 1220, 1220, 1220, 1220, 1471,  320,
-      340,  339, 1221,  338,  337,  336,  335,  334, 1221, 1221,
-     1221, 1221, 1221, 1221, 1223, 1224, 1224, 1224, 1224, 1224,
+     1364,  497, 1020,  494, 1639,   51, 1363, 1020, 1020, 1020,
+     1020, 1020, 1020, 1208, 1209, 1209, 1209, 1209, 1209, 1209,
+     1723,  493,   51,  492, 1210,  491,  490, 1641,  115, 1210,
+     1210, 1210, 1210, 1210, 1210,  925, 1034, 1034, 1034, 1034,
+     1034, 1034, 1034, 1102,  489, 1723,  488, 1035,  476,   51,
+       51, 1369, 1035, 1035, 1035, 1035, 1035, 1035, 1211, 1212,
+     1212, 1212, 1212, 1212, 1212, 1370,   51,   51,  475, 1213,
+      474, 1654,   51,  473, 1213, 1213, 1213, 1213, 1213, 1213,
+      937, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1105,   51,
+     1370, 1657, 1051,  472,   51,   51,   51, 1051, 1051, 1051,
 
-     1224, 1224, 1225,  333, 1471,  332, 1226,  331, 1227,  330,
-      329,  328, 1226, 1226, 1226, 1226, 1226, 1226, 1382, 1383,
-     1383, 1383, 1383, 1383, 1383, 1385, 1386, 1386, 1386, 1386,
-     1386, 1386,   55,  327, 1227, 1117, 1231, 1231, 1231, 1231,
-     1231, 1231, 1231, 1119,  326,  323,  322, 1232,  321,  320,
-       55, 1406,  319, 1232, 1232, 1232, 1232, 1232, 1232, 1126,
-     1241, 1241, 1241, 1241, 1241, 1241, 1241, 1128, 1407,  318,
-      317, 1242,  316,  315,  314,  313,  312, 1242, 1242, 1242,
-     1242, 1242, 1242, 1137, 1254, 1254, 1254, 1254, 1254, 1254,
-     1254, 1139,  311,  310,  309, 1255,  308,  307,  306,  305,
+     1051, 1051, 1051, 1214, 1215, 1215, 1215, 1215, 1215, 1215,
+     1630,   51,   51,   51, 1216,  471, 1656,   51,   51, 1216,
+     1216, 1216, 1216, 1216, 1216, 1218, 1219, 1219, 1219, 1219,
+     1219, 1219, 1219, 1220,   51,   51, 1658, 1221,  470, 1222,
+      469,  468, 1221, 1221, 1221, 1221, 1221, 1221, 1308, 1312,
+     1255, 1255, 1255, 1255, 1255, 1255, 1255, 1269, 1269, 1269,
+     1269, 1269, 1269, 1269, 1222, 1112, 1226, 1226, 1226, 1226,
+     1226, 1226, 1226, 1114,  272,  465,  274, 1227,  448,  362,
+       51,   51, 1227, 1227, 1227, 1227, 1227, 1227, 1121, 1236,
+     1236, 1236, 1236, 1236, 1236, 1236, 1123,   51,   51,  445,
 
-      304, 1255, 1255, 1255, 1255, 1255, 1255, 1149, 1268, 1268,
-     1268, 1268, 1268, 1268, 1268, 1151,  303,  302,  301, 1269,
-      300,  299,  298,  297,  143, 1269, 1269, 1269, 1269, 1269,
-     1269, 1161, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1163,
-      296,  295,  294, 1283,  293,  292,  291,  290,  289, 1283,
-     1283, 1283, 1283, 1283, 1283, 1068, 1291, 1291, 1291, 1291,
-     1291, 1291, 1291, 1070,  288,  287,  286, 1292,  285,  284,
-      283,  282,  279, 1292, 1292, 1292, 1292, 1292, 1292, 1293,
-     1294, 1294, 1294, 1294, 1294, 1294, 1294, 1295,  267,  272,
-      259, 1296,  258, 1297,   55,   55, 1470, 1296, 1296, 1296,
+     1237,  439, 1667, 1675,   51, 1237, 1237, 1237, 1237, 1237,
+     1237, 1132, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1134,
+      439,   51,  432, 1250,  432,  424, 1676,   51, 1250, 1250,
+     1250, 1250, 1250, 1250, 1144, 1263, 1263, 1263, 1263, 1263,
+     1263, 1263, 1146,  415,   51,  414, 1264,  411,  410, 1681,
+       51, 1264, 1264, 1264, 1264, 1264, 1264, 1156, 1277, 1277,
+     1277, 1277, 1277, 1277, 1277, 1158,  409,   51,  408, 1278,
+      407, 1682,   51,   51, 1278, 1278, 1278, 1278, 1278, 1278,
+     1063, 1286, 1286, 1286, 1286, 1286, 1286, 1286, 1065,   51,
+       51,  406, 1287, 1688, 1685,  405,  404, 1287, 1287, 1287,
 
-     1296, 1296, 1296, 1389, 1390, 1390, 1390, 1390, 1390, 1390,
-     1728,   55,   55,   55,  257,   55,   55,   55,  256, 1297,
-       55,  619,  525,  525,  525,  525,  525,  525,  525,   55,
-      255, 1534, 1576,   55,   55,   55, 1728, 1506,   55, 1318,
-     1319, 1319, 1319, 1319, 1319, 1319, 1320, 1397, 1410, 1660,
-     1321, 1507, 1586,  254,  253,   55, 1321, 1321, 1321, 1321,
-     1321, 1321, 1117, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
-     1323,   55,   55,   55, 1324,  252, 1121, 1507,  251,  250,
-     1324, 1324, 1324, 1324, 1324, 1324,  247, 1480,  244,   55,
-       55, 1427, 1428, 1428, 1428, 1428, 1428, 1428,  241,  240,
+     1287, 1287, 1287, 1288, 1289, 1289, 1289, 1289, 1289, 1289,
+     1289, 1290,   51, 1369, 1371, 1291, 1371, 1292,  403,  402,
+     1291, 1291, 1291, 1291, 1291, 1291,  401, 1723, 1372,   51,
+     1723, 1377, 1378, 1378, 1378, 1378, 1378, 1378, 1391,   51,
+       51,   51, 1292,   51,  614,  520,  520,  520,  520,  520,
+      520,  520, 1723, 1372,  400, 1723,   51,   51,   51, 1416,
+       51, 1313, 1314, 1314, 1314, 1314, 1314, 1314, 1315, 1392,
+      399, 1405, 1316, 1417,  398,   51, 1400, 1316, 1316, 1316,
+     1316, 1316, 1316, 1112, 1317, 1317, 1317, 1317, 1317, 1317,
+     1317, 1318,   51,  397,  396, 1319,  395, 1116, 1417,  390,
 
-     1398, 1411, 1121, 1126, 1325, 1325, 1325, 1325, 1325, 1325,
-     1325, 1326,  239,  238,  235, 1327,  234, 1130,  233,  232,
-      231, 1327, 1327, 1327, 1327, 1327, 1327, 1432, 1433, 1433,
-     1433, 1433, 1433, 1433, 1435, 1436, 1436, 1436, 1436, 1436,
-     1436,  230,  229, 1130, 1137, 1328, 1328, 1328, 1328, 1328,
-     1328, 1328, 1329,  228,  227,  226, 1330,  225, 1141,  224,
-      223,  222, 1330, 1330, 1330, 1330, 1330, 1330, 1441, 1442,
-     1442, 1442, 1442, 1442, 1442, 1444, 1445, 1445, 1445, 1445,
-     1445, 1445,  221,  220, 1141, 1149, 1331, 1331, 1331, 1331,
-     1331, 1331, 1331, 1332,  216,  215,  205, 1333,  204, 1153,
+     1319, 1319, 1319, 1319, 1319, 1319, 1380, 1381, 1381, 1381,
+     1381, 1381, 1381, 1384, 1385, 1385, 1385, 1385, 1385, 1385,
+     1416,   51, 1116, 1121, 1320, 1320, 1320, 1320, 1320, 1320,
+     1320, 1321,  389,   51, 1723, 1322,   51, 1125,   51,   51,
+     1322, 1322, 1322, 1322, 1322, 1322,  388,  387,  386, 1393,
+       51,  315,  385,   51,  384,  383,   51, 1401,  382, 1723,
+      381, 1406, 1125, 1132, 1323, 1323, 1323, 1323, 1323, 1323,
+     1323, 1324, 1529,  380, 1402, 1325,  374, 1136,  274,  362,
+     1325, 1325, 1325, 1325, 1325, 1325, 1422, 1423, 1423, 1423,
+     1423, 1423, 1423, 1427, 1428, 1428, 1428, 1428, 1428, 1428,
 
-      203,  200,  199, 1333, 1333, 1333, 1333, 1333, 1333, 1450,
-     1451, 1451, 1451, 1451, 1451, 1451, 1453, 1454, 1454, 1454,
-     1454, 1454, 1454,  194,  193, 1153, 1161, 1334, 1334, 1334,
-     1334, 1334, 1334, 1334, 1335,  192,  191,  190, 1336,  189,
-     1165,  188,  187,  186, 1336, 1336, 1336, 1336, 1336, 1336,
-     1459, 1460, 1460, 1460, 1460, 1460, 1460, 1462, 1463, 1463,
-     1463, 1463, 1463, 1463, 1506,   55, 1165, 1223, 1339, 1339,
-     1339, 1339, 1339, 1339, 1339, 1225,  185,  181, 1728, 1340,
-      180,  179,  178,   55,  177, 1340, 1340, 1340, 1340, 1340,
-     1340, 1117, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1323,
+      270,   51, 1136, 1144, 1326, 1326, 1326, 1326, 1326, 1326,
+     1326, 1327,  359,  267,  355, 1328,  261, 1148,   51,  255,
+     1328, 1328, 1328, 1328, 1328, 1328, 1430, 1431, 1431, 1431,
+     1431, 1431, 1431, 1436, 1437, 1437, 1437, 1437, 1437, 1437,
+      138,   51, 1148, 1156, 1329, 1329, 1329, 1329, 1329, 1329,
+     1329, 1330,  343,  342,  341, 1331,  336, 1160,   51,  315,
+     1331, 1331, 1331, 1331, 1331, 1331, 1439, 1440, 1440, 1440,
+     1440, 1440, 1440, 1445, 1446, 1446, 1446, 1446, 1446, 1446,
+     1463,   51, 1160, 1218, 1334, 1334, 1334, 1334, 1334, 1334,
+     1334, 1220,  335,  334, 1464, 1335,  333,  332,   51,   51,
 
-      176, 1579,  175, 1348, 1728,  174,  173,  172,  171, 1348,
-     1348, 1348, 1348, 1348, 1348, 1126, 1354, 1354, 1354, 1354,
-     1354, 1354, 1354, 1326,  170,  169,  168, 1355,  167,  166,
-      165,  160,  151, 1355, 1355, 1355, 1355, 1355, 1355, 1137,
-     1362, 1362, 1362, 1362, 1362, 1362, 1362, 1329,  150,  145,
-       59, 1363,   47,   45, 1728, 1728, 1728, 1363, 1363, 1363,
-     1363, 1363, 1363, 1149, 1370, 1370, 1370, 1370, 1370, 1370,
-     1370, 1332, 1728, 1728, 1728, 1371, 1728, 1728, 1728, 1728,
-     1728, 1371, 1371, 1371, 1371, 1371, 1371, 1161, 1378, 1378,
-     1378, 1378, 1378, 1378, 1378, 1335, 1728, 1728, 1728, 1379,
+     1335, 1335, 1335, 1335, 1335, 1335, 1112, 1342, 1342, 1342,
+     1342, 1342, 1342, 1342, 1318, 1470,   51,  331, 1343, 1464,
+      330,   51,   51, 1343, 1343, 1343, 1343, 1343, 1343, 1121,
+     1349, 1349, 1349, 1349, 1349, 1349, 1349, 1321,   51,   51,
+     1689, 1350,  329, 1695, 1703,   51, 1350, 1350, 1350, 1350,
+     1350, 1350, 1132, 1357, 1357, 1357, 1357, 1357, 1357, 1357,
+     1324,  328,   51,  327, 1358,  326,  325,   51,   51, 1358,
+     1358, 1358, 1358, 1358, 1358, 1144, 1365, 1365, 1365, 1365,
+     1365, 1365, 1365, 1327,   51,   51, 1705, 1366,  324,  323,
+     1710,  322, 1366, 1366, 1366, 1366, 1366, 1366, 1156, 1373,
 
-     1728, 1728, 1728, 1728, 1728, 1379, 1379, 1379, 1379, 1379,
-     1379, 1293, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1295,
-     1728, 1728, 1728, 1392, 1728, 1728, 1728, 1728, 1728, 1392,
-     1392, 1392, 1392, 1392, 1392, 1223, 1412, 1412, 1412, 1412,
-     1412, 1412, 1412, 1413, 1728, 1728, 1728, 1414, 1728, 1227,
-     1728, 1728, 1728, 1414, 1414, 1414, 1414, 1414, 1414, 1383,
-     1383, 1383, 1383, 1383, 1383, 1383, 1500, 1501, 1501, 1501,
-     1501, 1501, 1501, 1510,   55, 1227, 1117, 1231, 1231, 1231,
-     1231, 1231, 1231, 1231, 1323, 1728, 1728, 1511, 1232, 1728,
-     1728, 1728,   55, 1728, 1232, 1232, 1232, 1232, 1232, 1232,
+     1373, 1373, 1373, 1373, 1373, 1373, 1330,  321, 1709,  318,
+     1374,  317,  316,   51,   51, 1374, 1374, 1374, 1374, 1374,
+     1374, 1288, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1290,
+       51,   51,  315, 1387, 1712,  314,   51,   51, 1387, 1387,
+     1387, 1387, 1387, 1387, 1218, 1407, 1407, 1407, 1407, 1407,
+     1407, 1407, 1408,   51,   51,  313, 1409,  312, 1222, 1714,
+      311, 1409, 1409, 1409, 1409, 1409, 1409, 1448, 1449, 1449,
+     1449, 1449, 1449, 1449, 1454, 1455, 1455, 1455, 1455, 1455,
+     1455, 1463,   51, 1222, 1112, 1226, 1226, 1226, 1226, 1226,
+     1226, 1226, 1318,  310,  309, 1723, 1227,  308,  307,   51,
 
-     1126, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1326, 1728,
-     1580, 1728, 1242, 1511, 1728, 1728, 1728, 1728, 1242, 1242,
-     1242, 1242, 1242, 1242, 1137, 1254, 1254, 1254, 1254, 1254,
-     1254, 1254, 1329, 1728, 1728, 1728, 1255, 1728, 1728, 1728,
-     1728, 1728, 1255, 1255, 1255, 1255, 1255, 1255, 1149, 1268,
-     1268, 1268, 1268, 1268, 1268, 1268, 1332, 1728, 1728, 1728,
-     1269, 1728, 1728, 1728, 1728, 1728, 1269, 1269, 1269, 1269,
-     1269, 1269, 1161, 1282, 1282, 1282, 1282, 1282, 1282, 1282,
-     1335, 1728, 1728, 1728, 1283, 1728, 1728, 1728, 1728, 1728,
-     1283, 1283, 1283, 1283, 1283, 1283, 1223, 1423, 1423, 1423,
+       51, 1227, 1227, 1227, 1227, 1227, 1227, 1121, 1236, 1236,
+     1236, 1236, 1236, 1236, 1236, 1321, 1542,   51,  306, 1237,
+     1723,  305,   51,   51, 1237, 1237, 1237, 1237, 1237, 1237,
+     1132, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1324,   51,
+       51,  304, 1250,  303,  302,   51,   51, 1250, 1250, 1250,
+     1250, 1250, 1250, 1144, 1263, 1263, 1263, 1263, 1263, 1263,
+     1263, 1327,   51,   51,  301, 1264,  300,  299,   51,  298,
+     1264, 1264, 1264, 1264, 1264, 1264, 1156, 1277, 1277, 1277,
+     1277, 1277, 1277, 1277, 1330,   51,  297,  296, 1278,  295,
+      294,  293,  292, 1278, 1278, 1278, 1278, 1278, 1278, 1218,
 
-     1423, 1423, 1423, 1423, 1413, 1728, 1728, 1728, 1424, 1728,
-     1728, 1728,   55, 1728, 1424, 1424, 1424, 1424, 1424, 1424,
-     1293, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1295,   55,
-       55,   55, 1473, 1728, 1510, 1728, 1728, 1728, 1473, 1473,
-     1473, 1473, 1473, 1473, 1487,   55, 1728,   55, 1728,   55,
-     1433, 1433, 1433, 1433, 1433, 1433, 1433, 1728, 1484, 1728,
-     1728, 1488, 1514,   55, 1485, 1223, 1339, 1339, 1339, 1339,
-     1339, 1339, 1339, 1413, 1728, 1548, 1515, 1340, 1728, 1728,
-     1728, 1728, 1514, 1340, 1340, 1340, 1340, 1340, 1340, 1442,
-     1442, 1442, 1442, 1442, 1442, 1442, 1728, 1518, 1518, 1728,
+     1418, 1418, 1418, 1418, 1418, 1418, 1418, 1408,  138,  291,
+      290, 1419,  289,  288,  287,  286, 1419, 1419, 1419, 1419,
+     1419, 1419, 1457, 1458, 1458, 1458, 1458, 1458, 1458, 1378,
+     1378, 1378, 1378, 1378, 1378, 1378, 1465, 1465,   51,   51,
+       51,   51,   51, 1495, 1496, 1496, 1496, 1496, 1496, 1496,
+     1466, 1723, 1501,  285,  284,   51,   51,   51,   51,   51,
+      283,  282,  281,  280,  279,  278, 1502, 1479, 1486, 1475,
+     1483, 1482, 1501, 1480, 1505, 1466, 1723, 1288, 1467, 1467,
+     1467, 1467, 1467, 1467, 1467, 1290, 1723,  277, 1506, 1468,
+      274, 1502,  262,  267, 1468, 1468, 1468, 1468, 1468, 1468,
 
-     1728, 1728, 1515, 1451, 1451, 1451, 1451, 1451, 1451, 1451,
-     1522, 1519, 1728, 1460, 1460, 1460, 1460, 1460, 1460, 1460,
-     1522, 1728, 1728, 1728, 1523, 1526, 1527, 1527, 1527, 1527,
-     1527, 1527, 1728,   55, 1728,   55,   55, 1519, 1728, 1529,
-     1530, 1530, 1530, 1530, 1530, 1530,   55,   55,   55, 1728,
-     1523,   55,   55,   55,   55, 1551, 1728, 1551,   55,   55,
-     1728,   55, 1538, 1539,   55,   55,   55, 1543, 1728, 1552,
-       55, 1728, 1728, 1540, 1541, 1542,   55,   55, 1728,   55,
-     1728, 1545, 1553, 1554, 1554, 1554, 1554, 1554, 1554, 1728,
-     1728, 1728, 1728, 1622, 1582, 1552, 1587, 1728, 1557, 1558,
+     1218, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1408,  254,
+      253, 1723, 1335, 1506,  252,  251, 1505, 1335, 1335, 1335,
+     1335, 1335, 1335, 1428, 1428, 1428, 1428, 1428, 1428, 1428,
+     1723, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1509, 1509,
+     1446, 1446, 1446, 1446, 1446, 1446, 1446, 1513, 1513,  250,
+      249,  248, 1510, 1723,  247, 1723, 1517, 1517,  246,  245,
+      242, 1514, 1723, 1455, 1455, 1455, 1455, 1455, 1455, 1455,
+     1518, 1723,  239,  236,  235,  234,  233, 1510, 1723, 1521,
+     1522, 1522, 1522, 1522, 1522, 1522, 1514, 1723, 1524, 1525,
+     1525, 1525, 1525, 1525, 1525, 1518, 1723,   51,   51,   51,
 
-     1558, 1558, 1558, 1558, 1558, 1561, 1562, 1562, 1562, 1562,
-     1562, 1562, 1565, 1566, 1566, 1566, 1566, 1566, 1566, 1569,
-     1570, 1570, 1570, 1570, 1570, 1570, 1527, 1527, 1527, 1527,
-     1527, 1527, 1527, 1573, 1573,   55,   55,   55, 1589, 1590,
-     1590, 1590, 1590, 1590, 1590, 1728, 1728, 1574, 1728, 1728,
-     1728, 1728, 1728,   55,   55,   55, 1728, 1728, 1728, 1728,
-     1728, 1728, 1578, 1585, 1588, 1554, 1554, 1554, 1554, 1554,
-     1554, 1554, 1728, 1574, 1728, 1558, 1558, 1558, 1558, 1558,
-     1558, 1558, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1566,
-     1566, 1566, 1566, 1566, 1566, 1566, 1570, 1570, 1570, 1570,
+       51,   51,   51,   51,   51,   51,  230,  229,   51,  228,
+      227,  226,  225,  224,   51,   51,   51,   51,   51,   51,
+       51,   51,   51, 1530, 1531,   51, 1533, 1534, 1535, 1536,
+     1537, 1538, 1546, 1540, 1546,  223,  222, 1543, 1548, 1549,
+     1549, 1549, 1549, 1549, 1549,  221, 1547,  220, 1723, 1552,
+     1553, 1553, 1553, 1553, 1553, 1553, 1556, 1557, 1557, 1557,
+     1557, 1557, 1557, 1560, 1561, 1561, 1561, 1561, 1561, 1561,
+      219, 1547,  218, 1723, 1564, 1565, 1565, 1565, 1565, 1565,
+     1565, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1568, 1568,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
 
-     1570, 1570, 1570, 1598, 1599, 1599, 1599, 1599, 1599, 1599,
-       55,   55, 1728,   55,   55,   55,   55,   55, 1590, 1590,
-     1590, 1590, 1590, 1590, 1590,   55,   55, 1728,   55,   55,
-     1605,   55,   55,   55,   55,   55, 1728, 1728, 1728, 1728,
-     1728, 1728, 1611,   55,   55, 1601,   55, 1606,   55,   55,
-     1607, 1608, 1609, 1612, 1599, 1599, 1599, 1599, 1599, 1599,
-     1599,   55, 1620, 1628,   55,   55,   55,   55,   55,   55,
-     1728,   55,   55, 1621,   55,   55,   55,   55, 1728,   55,
-     1623, 1625,   55,   55, 1728, 1728,   55,   55, 1629,   55,
-       55,   55,   55,   55,   55,   55, 1647, 1630, 1637, 1728,
+      217,  216, 1569, 1723,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51, 1573, 1580, 1583,
+      215,   51,   51,   51,  211,  210, 1571, 1569, 1723, 1574,
+     1575, 1577, 1596,  200, 1578, 1581,  199, 1617,  198, 1604,
+     1582, 1584, 1585, 1585, 1585, 1585, 1585, 1585, 1549, 1549,
+     1549, 1549, 1549, 1549, 1549, 1553, 1553, 1553, 1553, 1553,
+     1553, 1553, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1561,
+     1561, 1561, 1561, 1561, 1561, 1561, 1565, 1565, 1565, 1565,
+     1565, 1565, 1565, 1593, 1594, 1594, 1594, 1594, 1594, 1594,
+       51,  195,   51,   51,   51,   51, 1585, 1585, 1585, 1585,
 
-       55,   55, 1638, 1645,   55, 1633, 1641, 1639, 1728,   55,
-       55, 1640,   55, 1648, 1649,   55, 1650, 1651, 1728,   55,
-       55, 1728,   55,   55,   55,   55, 1652, 1728,   55, 1728,
-       55,   55,   55,   55, 1728,   55, 1653,   55,   55, 1654,
-     1728,   55,   55,   55, 1658, 1656, 1666, 1665, 1728,   55,
-       55,   55, 1664,   55, 1670,   55, 1675,   55, 1667, 1668,
-     1677,   55,   55,   55,   55, 1728, 1671,   55, 1673,   55,
-     1674,   55,   55, 1676, 1728,   55,   55, 1728,   55,   55,
-       55,   55,   55, 1678, 1728,   55,   55, 1728, 1682,   55,
-       55,   55, 1683, 1728,   55, 1679,   55, 1685, 1684, 1688,
+     1585, 1585, 1585,  194,   51,   51,   51,   51, 1600,   51,
+       51,   51,   51, 1594, 1594, 1594, 1594, 1594, 1594, 1594,
+     1606,   51,   51,   51,   51, 1601,   51,   51, 1602, 1603,
+       51, 1607, 1616,   51,   51,   51, 1618,   51,  189,   51,
+     1615,   51,   51,   51,   51,  188,  187,   51,   51,   51,
+       51,   51,   51, 1624,   51, 1620,   51,  186,   51,   51,
+       51, 1625, 1623, 1632,   51,   51,   51, 1633,   51, 1628,
+       51,   51, 1631, 1634, 1640,   51, 1642,   51, 1635, 1636,
+      185,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51, 1653,   51, 1643, 1644,   51,  184, 1645, 1646,   51,
 
-       55, 1728, 1689,   55,   55, 1691,   55,   55, 1728,   55,
-     1695, 1692,   55,   55,   55,   55, 1728, 1728,   55, 1696,
-     1697,   55,   55, 1728,   55,   55, 1701,   55,   55, 1699,
-       55,   55,   55,   55, 1704, 1702,   55,   55,   55, 1728,
-       55, 1706, 1709, 1703, 1705,   55,   55,   55,   55,   55,
-       55, 1728, 1707, 1728,   55,   55,   55, 1711, 1728, 1728,
-     1728, 1728, 1728, 1716, 1712,   55,   55,   55,   55, 1728,
-     1728, 1728, 1713, 1728, 1718, 1721, 1722,   55, 1728, 1728,
-     1726, 1727, 1728, 1720, 1728, 1724, 1728, 1725, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728,   55,   46, 1728, 1728, 1728,
+       51,   51, 1647,   51, 1648, 1649,   51,   51,   51,   51,
+     1660, 1661,   51,  183,   51,   51, 1651,   51,   51,  182,
+     1655,   51, 1659, 1662, 1663,   51, 1666, 1664,   51,   51,
+     1668,   51,   51, 1670,   51,   51, 1665,  181,   51,   51,
+       51,  180,   51,   51,   51,   51,   51,   51, 1669, 1673,
+     1671,  176,   51, 1672, 1677,  175,   51,   51, 1674,   51,
+       51,   51,   51, 1679,   51,   51,  174,   51, 1678,   51,
+       51,   51, 1680, 1683, 1684, 1686,   51,  173,  172,   51,
+       51, 1687,   51, 1690,   51,  171,  170,   51,   51,  169,
+       51,   51,   51,   51, 1691, 1692,   51,   51, 1694,   51,
 
-     1728,   46,   46,   46,   64, 1728,   64,   64,   64,   64,
-       64,   64,   64,  152, 1728,  152,  159,  159,  159,  271,
-      271,  271,  280,  280,  280,  359,  359,  359,  362,  362,
-      362,  363,  363,  363,  370,  370,  370,  368,  368,  368,
-      374,  374,  374,  378, 1728,  378,  443,  443,  443,  448,
-      448,  448,  449,  449,  449,  458,  458,  458,  462, 1728,
-      462,  463,  463,  463,  372,  372, 1728, 1728,  372,  467,
-      467,  467,  471,  471,  471,  362,  362,  362,  532,  532,
-      532,  536,  536,  536,  537,  537,  537,  538,  538,  538,
-      370,  370,  370,  543,  543,  543,  456,  456, 1728, 1728,
+       51, 1696, 1697, 1693,   51,  168, 1699,   51,   51,   51,
+       51,   51, 1698,   51,   51,   51,   51,   51,   51, 1701,
+     1700,   51, 1704,   51,   51,   51,  167,   51,   51, 1702,
+      166,   51,   51, 1706,  165,   51, 1707,  164,  163, 1708,
+       51,   51,   51,  162, 1711,  161,  160, 1713,  155, 1715,
+     1717, 1716,  146,  145,   51,  140, 1718, 1721, 1722, 1719,
+       55, 1720,   52,   43,   41, 1723, 1723, 1723, 1723, 1723,
+     1723,   51,   42, 1723,   42,   59, 1723,   59,   59,   59,
+       59,   59,   59,  147, 1723,  147,  154,  154,  154,  266,
+      266,  266,  275,  275,  275,  354,  354,  354,  357,  357,
 
-      456,  548,  548,  548,  552,  552,  552,  556, 1728,  556,
-      557,  557,  557,  561,  561,  561,  565, 1728,  565,  624,
-      624,  624,  458,  458,  458,  632,  632,  632,  633,  633,
-      633,  641,  641,  641,  645, 1728,  645,  648, 1728,  648,
-      649,  649,  649,  653,  653,  653,  657, 1728,  657,  555,
-      555, 1728, 1728,  555,  559,  559, 1728, 1728,  559,  663,
-      663,  663,  667,  667,  667,  565,  565, 1728,  565,  537,
-      537,  537,  713,  713,  713,  717,  717,  717,  720,  720,
-      720,  721,  721,  721,  722,  722,  722,  727,  727,  727,
-      639,  639, 1728, 1728,  639,  732,  732,  732,  736,  736,
+      357,  358,  358,  358,  365,  365,  365,  363,  363,  363,
+      369,  369,  369,  373, 1723,  373,  438,  438,  438,  443,
+      443,  443,  444,  444,  444,  453,  453,  453,  457, 1723,
+      457,  458,  458,  458,  367,  367, 1723, 1723,  367,  462,
+      462,  462,  466,  466,  466,  357,  357,  357,  527,  527,
+      527,  531,  531,  531,  532,  532,  532,  533,  533,  533,
+      365,  365,  365,  538,  538,  538,  451,  451, 1723, 1723,
+      451,  543,  543,  543,  547,  547,  547,  551, 1723,  551,
+      552,  552,  552,  556,  556,  556,  560, 1723,  560,  619,
+      619,  619,  453,  453,  453,  627,  627,  627,  628,  628,
 
-      736,  645,  645, 1728,  645,  647,  647, 1728, 1728,  647,
-      648,  648, 1728,  648,  649,  649,  651,  651, 1728, 1728,
-      651,  743,  743,  743,  747,  747,  747,  657,  657, 1728,
-      657,  751, 1728,  751,  754, 1728,  754,  755,  755,  755,
-      759,  759,  759,  763, 1728,  763,  802,  802,  802,  641,
-      641,  641,  653,  653,  653,  813,  813,  813,  814,  814,
-      814,  822,  822,  822,  826, 1728,  826,  829, 1728,  829,
-      830,  830,  830,  834,  834,  834,  838, 1728,  838,  841,
-     1728,  841,  844, 1728,  844,  845,  845,  845,  849,  849,
-      849,  853, 1728,  853,  750, 1728, 1728,  750,  751,  751,
+      628,  636,  636,  636,  640, 1723,  640,  643, 1723,  643,
+      644,  644,  644,  648,  648,  648,  652, 1723,  652,  550,
+      550, 1723, 1723,  550,  554,  554, 1723, 1723,  554,  658,
+      658,  658,  662,  662,  662,  560,  560, 1723,  560,  532,
+      532,  532,  708,  708,  708,  712,  712,  712,  715,  715,
+      715,  716,  716,  716,  717,  717,  717,  722,  722,  722,
+      634,  634, 1723, 1723,  634,  727,  727,  727,  731,  731,
+      731,  640,  640, 1723,  640,  642,  642, 1723, 1723,  642,
+      643,  643, 1723,  643,  644,  644,  646,  646, 1723, 1723,
+      646,  738,  738,  738,  742,  742,  742,  652,  652, 1723,
 
-     1728,  751,  753,  753, 1728, 1728,  753,  754,  754, 1728,
-      754,  755,  755,  757,  757, 1728, 1728,  757,  860,  860,
-      860,  864,  864,  864,  763,  763, 1728,  763,   53,   53,
-       53, 1728,   53,   53,  721,  721,  721,  896,  896,  896,
-      900,  900,  900,  903,  903,  903,  906,  906,  906,  907,
-      907,  907,  908,  908,  908,  913,  913,  913,  820,  820,
-     1728, 1728,  820,  918,  918,  918,  922,  922,  922,  826,
-      826, 1728,  826,  828,  828, 1728, 1728,  828,  829,  829,
-     1728,  829,  830,  830,  832,  832, 1728, 1728,  832,  929,
-      929,  929,  933,  933,  933,  838,  838, 1728,  838,  840,
+      652,  746, 1723,  746,  749, 1723,  749,  750,  750,  750,
+      754,  754,  754,  758, 1723,  758,  797,  797,  797,  636,
+      636,  636,  648,  648,  648,  808,  808,  808,  809,  809,
+      809,  817,  817,  817,  821, 1723,  821,  824, 1723,  824,
+      825,  825,  825,  829,  829,  829,  833, 1723,  833,  836,
+     1723,  836,  839, 1723,  839,  840,  840,  840,  844,  844,
+      844,  848, 1723,  848,  745, 1723, 1723,  745,  746,  746,
+     1723,  746,  748,  748, 1723, 1723,  748,  749,  749, 1723,
+      749,  750,  750,  752,  752, 1723, 1723,  752,  855,  855,
+      855,  859,  859,  859,  758,  758, 1723,  758,   49,   49,
 
-     1728, 1728,  840,  841,  841, 1728,  841,  843,  843, 1728,
-     1728,  843,  844,  844, 1728,  844,  845,  845,  847,  847,
-     1728, 1728,  847,  941,  941,  941,  945,  945,  945,  853,
-      853, 1728,  853,  947, 1728,  947,  950, 1728,  950,  953,
-     1728,  953,  954,  954,  954,  958,  958,  958,  962, 1728,
-      962,   53,   53,   53, 1728,   53,   53,  990,  990,  990,
-      822,  822,  822,  834,  834,  834,  849,  849,  849, 1004,
-     1004, 1004, 1005, 1005, 1005, 1013, 1013, 1013, 1017, 1728,
-     1017, 1020, 1728, 1020, 1021, 1021, 1021, 1025, 1025, 1025,
-     1029, 1728, 1029, 1032, 1728, 1032, 1035, 1728, 1035, 1036,
+       49, 1723,   49,   49,  716,  716,  716,  891,  891,  891,
+      895,  895,  895,  898,  898,  898,  901,  901,  901,  902,
+      902,  902,  903,  903,  903,  908,  908,  908,  815,  815,
+     1723, 1723,  815,  913,  913,  913,  917,  917,  917,  821,
+      821, 1723,  821,  823,  823, 1723, 1723,  823,  824,  824,
+     1723,  824,  825,  825,  827,  827, 1723, 1723,  827,  924,
+      924,  924,  928,  928,  928,  833,  833, 1723,  833,  835,
+     1723, 1723,  835,  836,  836, 1723,  836,  838,  838, 1723,
+     1723,  838,  839,  839, 1723,  839,  840,  840,  842,  842,
+     1723, 1723,  842,  936,  936,  936,  940,  940,  940,  848,
 
-     1036, 1036, 1040, 1040, 1040, 1044, 1728, 1044, 1045, 1728,
-     1045, 1048, 1728, 1048, 1051, 1728, 1051, 1052, 1052, 1052,
-     1056, 1056, 1056, 1060, 1728, 1060,  947, 1728,  947,  949,
-     1728, 1728,  949,  950,  950, 1728,  950,  952,  952, 1728,
-     1728,  952,  953,  953, 1728,  953,  954,  954,  956,  956,
-     1728, 1728,  956, 1067, 1067, 1067, 1071, 1071, 1071,  962,
-      962, 1728,  962,   53,   53,   53, 1728,   53,   53,  907,
-      907,  907, 1098, 1098, 1098, 1102, 1102, 1102, 1105, 1105,
-     1105, 1108, 1108, 1108, 1111, 1111, 1111, 1112, 1112, 1112,
-     1120, 1120, 1120, 1011, 1011, 1728, 1728, 1011, 1125, 1125,
+      848, 1723,  848,  942, 1723,  942,  945, 1723,  945,  948,
+     1723,  948,  949,  949,  949,  953,  953,  953,  957, 1723,
+      957,   49,   49,   49, 1723,   49,   49,  985,  985,  985,
+      817,  817,  817,  829,  829,  829,  844,  844,  844,  999,
+      999,  999, 1000, 1000, 1000, 1008, 1008, 1008, 1012, 1723,
+     1012, 1015, 1723, 1015, 1016, 1016, 1016, 1020, 1020, 1020,
+     1024, 1723, 1024, 1027, 1723, 1027, 1030, 1723, 1030, 1031,
+     1031, 1031, 1035, 1035, 1035, 1039, 1723, 1039, 1040, 1723,
+     1040, 1043, 1723, 1043, 1046, 1723, 1046, 1047, 1047, 1047,
+     1051, 1051, 1051, 1055, 1723, 1055,  942, 1723,  942,  944,
 
-     1125, 1129, 1129, 1129, 1017, 1017, 1728, 1017, 1019, 1019,
-     1728, 1728, 1019, 1020, 1020, 1728, 1020, 1021, 1021, 1023,
-     1023, 1728, 1728, 1023, 1136, 1136, 1136, 1140, 1140, 1140,
-     1029, 1029, 1728, 1029, 1031, 1728, 1728, 1031, 1032, 1032,
-     1728, 1032, 1034, 1034, 1728, 1728, 1034, 1035, 1035, 1728,
-     1035, 1036, 1036, 1038, 1038, 1728, 1728, 1038, 1148, 1148,
-     1148, 1152, 1152, 1152, 1044, 1044, 1728, 1044, 1045, 1728,
-     1045, 1047, 1728, 1728, 1047, 1048, 1048, 1728, 1048, 1050,
-     1050, 1728, 1728, 1050, 1051, 1051, 1728, 1051, 1052, 1052,
-     1054, 1054, 1728, 1728, 1054, 1160, 1160, 1160, 1164, 1164,
+     1723, 1723,  944,  945,  945, 1723,  945,  947,  947, 1723,
+     1723,  947,  948,  948, 1723,  948,  949,  949,  951,  951,
+     1723, 1723,  951, 1062, 1062, 1062, 1066, 1066, 1066,  957,
+      957, 1723,  957,   49,   49,   49, 1723,   49,   49,  902,
+      902,  902, 1093, 1093, 1093, 1097, 1097, 1097, 1100, 1100,
+     1100, 1103, 1103, 1103, 1106, 1106, 1106, 1107, 1107, 1107,
+     1115, 1115, 1115, 1006, 1006, 1723, 1723, 1006, 1120, 1120,
+     1120, 1124, 1124, 1124, 1012, 1012, 1723, 1012, 1014, 1014,
+     1723, 1723, 1014, 1015, 1015, 1723, 1015, 1016, 1016, 1018,
+     1018, 1723, 1723, 1018, 1131, 1131, 1131, 1135, 1135, 1135,
 
-     1164, 1060, 1060, 1728, 1060, 1166, 1728, 1166, 1169, 1728,
-     1169, 1172, 1728, 1172, 1173, 1173, 1173, 1177, 1177, 1177,
-     1181, 1728, 1181,   53,   53,   53, 1728,   53,   53, 1205,
-     1205, 1205, 1013, 1013, 1013, 1025, 1025, 1025, 1040, 1040,
-     1040, 1056, 1056, 1056, 1222, 1222, 1222, 1228, 1228, 1228,
-     1226, 1226, 1226, 1233, 1233, 1233, 1232, 1232, 1232, 1234,
-     1728, 1234, 1237, 1728, 1237, 1238, 1238, 1238, 1243, 1243,
-     1243, 1242, 1242, 1242, 1244, 1728, 1244, 1247, 1728, 1247,
-     1250, 1728, 1250, 1251, 1251, 1251, 1256, 1256, 1256, 1255,
-     1255, 1255, 1257, 1728, 1257, 1258, 1728, 1258, 1261, 1728,
+     1024, 1024, 1723, 1024, 1026, 1723, 1723, 1026, 1027, 1027,
+     1723, 1027, 1029, 1029, 1723, 1723, 1029, 1030, 1030, 1723,
+     1030, 1031, 1031, 1033, 1033, 1723, 1723, 1033, 1143, 1143,
+     1143, 1147, 1147, 1147, 1039, 1039, 1723, 1039, 1040, 1723,
+     1040, 1042, 1723, 1723, 1042, 1043, 1043, 1723, 1043, 1045,
+     1045, 1723, 1723, 1045, 1046, 1046, 1723, 1046, 1047, 1047,
+     1049, 1049, 1723, 1723, 1049, 1155, 1155, 1155, 1159, 1159,
+     1159, 1055, 1055, 1723, 1055, 1161, 1723, 1161, 1164, 1723,
+     1164, 1167, 1723, 1167, 1168, 1168, 1168, 1172, 1172, 1172,
+     1176, 1723, 1176,   49,   49,   49, 1723,   49,   49, 1200,
 
-     1261, 1264, 1728, 1264, 1265, 1265, 1265, 1270, 1270, 1270,
-     1269, 1269, 1269, 1271, 1728, 1271, 1272, 1728, 1272, 1275,
-     1728, 1275, 1278, 1728, 1278, 1279, 1279, 1279, 1284, 1284,
-     1284, 1283, 1283, 1283, 1285, 1728, 1285, 1166, 1728, 1166,
-     1168, 1728, 1728, 1168, 1169, 1169, 1728, 1169, 1171, 1171,
-     1728, 1728, 1171, 1172, 1172, 1728, 1172, 1173, 1173, 1175,
-     1175, 1728, 1728, 1175, 1292, 1292, 1292, 1296, 1296, 1296,
-     1181, 1181, 1728, 1181,   53,   53,   53, 1728,   53,   53,
-     1112, 1112, 1112, 1324, 1324, 1324, 1327, 1327, 1327, 1330,
-     1330, 1330, 1333, 1333, 1333, 1336, 1336, 1336, 1341, 1341,
+     1200, 1200, 1008, 1008, 1008, 1020, 1020, 1020, 1035, 1035,
+     1035, 1051, 1051, 1051, 1217, 1217, 1217, 1223, 1223, 1223,
+     1221, 1221, 1221, 1228, 1228, 1228, 1227, 1227, 1227, 1229,
+     1723, 1229, 1232, 1723, 1232, 1233, 1233, 1233, 1238, 1238,
+     1238, 1237, 1237, 1237, 1239, 1723, 1239, 1242, 1723, 1242,
+     1245, 1723, 1245, 1246, 1246, 1246, 1251, 1251, 1251, 1250,
+     1250, 1250, 1252, 1723, 1252, 1253, 1723, 1253, 1256, 1723,
+     1256, 1259, 1723, 1259, 1260, 1260, 1260, 1265, 1265, 1265,
+     1264, 1264, 1264, 1266, 1723, 1266, 1267, 1723, 1267, 1270,
+     1723, 1270, 1273, 1723, 1273, 1274, 1274, 1274, 1279, 1279,
 
-     1341, 1340, 1340, 1340, 1343, 1728, 1343, 1344, 1344, 1344,
-     1230, 1230, 1728, 1728, 1230, 1348, 1348, 1348, 1349, 1349,
-     1349, 1234, 1234, 1728, 1234, 1236, 1236, 1728, 1728, 1236,
-     1237, 1237, 1728, 1237, 1238, 1238, 1240, 1240, 1728, 1728,
-     1240, 1355, 1355, 1355, 1356, 1356, 1356, 1244, 1244, 1728,
-     1244, 1246, 1728, 1728, 1246, 1247, 1247, 1728, 1247, 1249,
-     1249, 1728, 1728, 1249, 1250, 1250, 1728, 1250, 1251, 1251,
-     1253, 1253, 1728, 1728, 1253, 1363, 1363, 1363, 1364, 1364,
-     1364, 1257, 1257, 1728, 1257, 1258, 1728, 1258, 1260, 1728,
-     1728, 1260, 1261, 1261, 1728, 1261, 1263, 1263, 1728, 1728,
+     1279, 1278, 1278, 1278, 1280, 1723, 1280, 1161, 1723, 1161,
+     1163, 1723, 1723, 1163, 1164, 1164, 1723, 1164, 1166, 1166,
+     1723, 1723, 1166, 1167, 1167, 1723, 1167, 1168, 1168, 1170,
+     1170, 1723, 1723, 1170, 1287, 1287, 1287, 1291, 1291, 1291,
+     1176, 1176, 1723, 1176,   49,   49,   49, 1723,   49,   49,
+     1107, 1107, 1107, 1319, 1319, 1319, 1322, 1322, 1322, 1325,
+     1325, 1325, 1328, 1328, 1328, 1331, 1331, 1331, 1336, 1336,
+     1336, 1335, 1335, 1335, 1338, 1723, 1338, 1339, 1339, 1339,
+     1225, 1225, 1723, 1723, 1225, 1343, 1343, 1343, 1344, 1344,
+     1344, 1229, 1229, 1723, 1229, 1231, 1231, 1723, 1723, 1231,
 
-     1263, 1264, 1264, 1728, 1264, 1265, 1265, 1267, 1267, 1728,
-     1728, 1267, 1371, 1371, 1371, 1372, 1372, 1372, 1271, 1271,
-     1728, 1271, 1272, 1728, 1272, 1274, 1728, 1728, 1274, 1275,
-     1275, 1728, 1275, 1277, 1277, 1728, 1728, 1277, 1278, 1278,
-     1728, 1278, 1279, 1279, 1281, 1281, 1728, 1728, 1281, 1379,
-     1379, 1379, 1380, 1380, 1380, 1285, 1285, 1728, 1285, 1381,
-     1728, 1381, 1384, 1728, 1384, 1387, 1728, 1387, 1388, 1388,
-     1388, 1393, 1728, 1393, 1392, 1392, 1392, 1394, 1728, 1394,
-       53,   53,   53, 1728,   53,   53, 1415, 1728, 1415, 1414,
-     1414, 1414, 1416, 1728, 1416, 1232, 1232, 1232, 1417, 1728,
+     1232, 1232, 1723, 1232, 1233, 1233, 1235, 1235, 1723, 1723,
+     1235, 1350, 1350, 1350, 1351, 1351, 1351, 1239, 1239, 1723,
+     1239, 1241, 1723, 1723, 1241, 1242, 1242, 1723, 1242, 1244,
+     1244, 1723, 1723, 1244, 1245, 1245, 1723, 1245, 1246, 1246,
+     1248, 1248, 1723, 1723, 1248, 1358, 1358, 1358, 1359, 1359,
+     1359, 1252, 1252, 1723, 1252, 1253, 1723, 1253, 1255, 1723,
+     1723, 1255, 1256, 1256, 1723, 1256, 1258, 1258, 1723, 1723,
+     1258, 1259, 1259, 1723, 1259, 1260, 1260, 1262, 1262, 1723,
+     1723, 1262, 1366, 1366, 1366, 1367, 1367, 1367, 1266, 1266,
+     1723, 1266, 1267, 1723, 1267, 1269, 1723, 1723, 1269, 1270,
 
-     1417, 1242, 1242, 1242, 1418, 1728, 1418, 1255, 1255, 1255,
-     1419, 1728, 1419, 1269, 1269, 1269, 1420, 1728, 1420, 1283,
-     1283, 1283, 1338, 1338, 1728, 1728, 1338, 1424, 1424, 1424,
-     1425, 1425, 1425,  370,  370,  370, 1343, 1343, 1728, 1343,
-     1426, 1426, 1426, 1429, 1728, 1429, 1430, 1430, 1430, 1431,
-     1431, 1431, 1434, 1728, 1434, 1437, 1728, 1437, 1438, 1438,
-     1438, 1439, 1439, 1439, 1440, 1728, 1440, 1443, 1728, 1443,
-     1446, 1728, 1446, 1447, 1447, 1447, 1448, 1448, 1448, 1449,
-     1728, 1449, 1452, 1728, 1452, 1455, 1728, 1455, 1456, 1456,
-     1456, 1457, 1457, 1457, 1458, 1728, 1458, 1461, 1728, 1461,
+     1270, 1723, 1270, 1272, 1272, 1723, 1723, 1272, 1273, 1273,
+     1723, 1273, 1274, 1274, 1276, 1276, 1723, 1723, 1276, 1374,
+     1374, 1374, 1375, 1375, 1375, 1280, 1280, 1723, 1280, 1376,
+     1723, 1376, 1379, 1723, 1379, 1382, 1723, 1382, 1383, 1383,
+     1383, 1388, 1723, 1388, 1387, 1387, 1387, 1389, 1723, 1389,
+       49,   49,   49, 1723,   49,   49, 1410, 1723, 1410, 1409,
+     1409, 1409, 1411, 1723, 1411, 1227, 1227, 1227, 1412, 1723,
+     1412, 1237, 1237, 1237, 1413, 1723, 1413, 1250, 1250, 1250,
+     1414, 1723, 1414, 1264, 1264, 1264, 1415, 1723, 1415, 1278,
+     1278, 1278, 1333, 1333, 1723, 1723, 1333, 1419, 1419, 1419,
 
-     1464, 1728, 1464, 1465, 1465, 1465, 1466, 1466, 1466, 1381,
-     1728, 1381, 1383, 1728, 1728, 1383, 1384, 1384, 1728, 1384,
-     1386, 1386, 1728, 1728, 1386, 1387, 1387, 1728, 1387, 1388,
-     1388, 1390, 1390, 1728, 1728, 1390, 1473, 1473, 1473, 1474,
-     1728, 1474, 1394, 1394, 1728, 1394,   53,   53,   53, 1728,
-       53,   53, 1492, 1492, 1492, 1340, 1340, 1340, 1494, 1728,
-     1494, 1495, 1728, 1495, 1496, 1728, 1496, 1497, 1728, 1497,
-     1498, 1728, 1498, 1499, 1728, 1499, 1502, 1728, 1502, 1503,
-     1503, 1503, 1504, 1504, 1504, 1505, 1728, 1505, 1428, 1428,
-     1728, 1728, 1428, 1429, 1429, 1728, 1429, 1430, 1430, 1508,
+     1420, 1420, 1420,  365,  365,  365, 1338, 1338, 1723, 1338,
+     1421, 1421, 1421, 1424, 1723, 1424, 1425, 1425, 1425, 1426,
+     1426, 1426, 1429, 1723, 1429, 1432, 1723, 1432, 1433, 1433,
+     1433, 1434, 1434, 1434, 1435, 1723, 1435, 1438, 1723, 1438,
+     1441, 1723, 1441, 1442, 1442, 1442, 1443, 1443, 1443, 1444,
+     1723, 1444, 1447, 1723, 1447, 1450, 1723, 1450, 1451, 1451,
+     1451, 1452, 1452, 1452, 1453, 1723, 1453, 1456, 1723, 1456,
+     1459, 1723, 1459, 1460, 1460, 1460, 1461, 1461, 1461, 1376,
+     1723, 1376, 1378, 1723, 1723, 1378, 1379, 1379, 1723, 1379,
+     1381, 1381, 1723, 1723, 1381, 1382, 1382, 1723, 1382, 1383,
 
-     1728, 1508, 1433, 1728, 1728, 1433, 1434, 1434, 1728, 1434,
-     1436, 1436, 1728, 1728, 1436, 1437, 1437, 1728, 1437, 1438,
-     1438, 1512, 1728, 1512, 1440, 1728, 1440, 1442, 1728, 1728,
-     1442, 1443, 1443, 1728, 1443, 1445, 1445, 1728, 1728, 1445,
-     1446, 1446, 1728, 1446, 1447, 1447, 1516, 1728, 1516, 1449,
-     1728, 1449, 1451, 1728, 1728, 1451, 1452, 1452, 1728, 1452,
-     1454, 1454, 1728, 1728, 1454, 1455, 1455, 1728, 1455, 1456,
-     1456, 1520, 1728, 1520, 1458, 1728, 1458, 1460, 1728, 1728,
-     1460, 1461, 1461, 1728, 1461, 1463, 1463, 1728, 1728, 1463,
-     1464, 1464, 1728, 1464, 1465, 1465, 1524, 1728, 1524, 1525,
+     1383, 1385, 1385, 1723, 1723, 1385, 1468, 1468, 1468, 1469,
+     1723, 1469, 1389, 1389, 1723, 1389,   49,   49,   49, 1723,
+       49,   49, 1487, 1487, 1487, 1335, 1335, 1335, 1489, 1723,
+     1489, 1490, 1723, 1490, 1491, 1723, 1491, 1492, 1723, 1492,
+     1493, 1723, 1493, 1494, 1723, 1494, 1497, 1723, 1497, 1498,
+     1498, 1498, 1499, 1499, 1499, 1500, 1723, 1500, 1423, 1423,
+     1723, 1723, 1423, 1424, 1424, 1723, 1424, 1425, 1425, 1503,
+     1723, 1503, 1428, 1723, 1723, 1428, 1429, 1429, 1723, 1429,
+     1431, 1431, 1723, 1723, 1431, 1432, 1432, 1723, 1432, 1433,
+     1433, 1507, 1723, 1507, 1435, 1723, 1435, 1437, 1723, 1723,
 
-     1728, 1525, 1528, 1728, 1528, 1531, 1728, 1531, 1532, 1532,
-     1532, 1533, 1728, 1533,   53,   53,   53, 1728,   53,   53,
-     1550, 1728, 1550, 1426, 1728, 1426, 1431, 1728, 1431, 1439,
-     1728, 1439, 1448, 1728, 1448, 1457, 1728, 1457, 1466, 1728,
-     1466, 1501, 1501, 1728, 1728, 1501, 1502, 1502, 1728, 1502,
-     1503, 1503, 1493, 1728, 1493, 1555, 1728, 1555, 1556, 1728,
-     1556, 1559, 1728, 1559, 1560, 1728, 1560, 1563, 1728, 1563,
-     1564, 1728, 1564, 1567, 1728, 1567, 1568, 1728, 1568, 1571,
-     1728, 1571, 1527, 1728, 1728, 1527, 1530, 1530, 1728, 1728,
-     1530, 1575, 1728, 1575, 1504, 1728, 1504, 1591, 1728, 1591,
+     1437, 1438, 1438, 1723, 1438, 1440, 1440, 1723, 1723, 1440,
+     1441, 1441, 1723, 1441, 1442, 1442, 1511, 1723, 1511, 1444,
+     1723, 1444, 1446, 1723, 1723, 1446, 1447, 1447, 1723, 1447,
+     1449, 1449, 1723, 1723, 1449, 1450, 1450, 1723, 1450, 1451,
+     1451, 1515, 1723, 1515, 1453, 1723, 1453, 1455, 1723, 1723,
+     1455, 1456, 1456, 1723, 1456, 1458, 1458, 1723, 1723, 1458,
+     1459, 1459, 1723, 1459, 1460, 1460, 1519, 1723, 1519, 1520,
+     1723, 1520, 1523, 1723, 1523, 1526, 1723, 1526, 1527, 1527,
+     1527, 1528, 1723, 1528,   49,   49,   49, 1723,   49,   49,
+     1545, 1723, 1545, 1421, 1723, 1421, 1426, 1723, 1426, 1434,
 
-     1554, 1728, 1728, 1554, 1558, 1728, 1728, 1558, 1562, 1728,
-     1728, 1562, 1566, 1728, 1728, 1566, 1570, 1728, 1728, 1570,
-     1597, 1728, 1597, 1600, 1728, 1600, 1590, 1728, 1728, 1590,
-     1614, 1728, 1614, 1615, 1728, 1615, 1616, 1728, 1616, 1617,
-     1728, 1617, 1618, 1728, 1618, 1599, 1728, 1728, 1599, 1631,
-     1728, 1631, 1632, 1728, 1632,    3, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1723, 1434, 1443, 1723, 1443, 1452, 1723, 1452, 1461, 1723,
+     1461, 1496, 1496, 1723, 1723, 1496, 1497, 1497, 1723, 1497,
+     1498, 1498, 1488, 1723, 1488, 1550, 1723, 1550, 1551, 1723,
+     1551, 1554, 1723, 1554, 1555, 1723, 1555, 1558, 1723, 1558,
+     1559, 1723, 1559, 1562, 1723, 1562, 1563, 1723, 1563, 1566,
+     1723, 1566, 1522, 1723, 1723, 1522, 1525, 1525, 1723, 1723,
+     1525, 1570, 1723, 1570, 1499, 1723, 1499, 1586, 1723, 1586,
+     1549, 1723, 1723, 1549, 1553, 1723, 1723, 1553, 1557, 1723,
+     1723, 1557, 1561, 1723, 1723, 1561, 1565, 1723, 1723, 1565,
+     1592, 1723, 1592, 1595, 1723, 1595, 1585, 1723, 1723, 1585,
 
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
+     1609, 1723, 1609, 1610, 1723, 1610, 1611, 1723, 1611, 1612,
+     1723, 1612, 1613, 1723, 1613, 1594, 1723, 1723, 1594, 1626,
+     1723, 1626, 1627, 1723, 1627,    3, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723
     } ;
 
-static yyconst flex_int16_t yy_chk[7910] =
+static const flex_int16_t yy_chk[7679] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    4,   15,  106,    4,    7,    4,    4,
-        7,  106,    7,    7,    9,   17,   17,    9,  138,    9,
-        9,    4,   19,   19,   24,    7,   27,   27,  138,    4,
-       15,   10,    9,    7,   10,  102,   10,   10,   24,   28,
-        9,   34,   26, 1278,   28,   24,   26,  586,   94,   10,
+        1,    1,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   14,   14,  674,   11,   11,   11,  674,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   12,   16,   16,   20,   23,   20,
 
-       34,   94,   26,  586,   95,   26,   95,   10,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,  102,   98,
-     1279,   14,   14,   14,   98,   83,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   16,   83,   25,   16,  671,   16,   16,   83,  129,
-       29,  671,  107,   25,   29,  252,   25,  107,   22,   16,
-       25,   22,  129,   22,   22,  103,   29,   16,   20,   20,
-       20,   20,   20,   20,   20,   20,   22,  134,   23,  252,
-       23,   23,   20,  673,   22,   23,  673,  251,   35,  251,
+       20,   31,   23,  408,   20,   24,   24,   25,   23,   20,
+       31,   23,   25,   20,   21,   20,   90,  408,   90,   12,
+       17,   17,   17,   17,   17,   17,   17,   17,   21,   22,
+       89, 1270,   26,   89,   17,   21,   26,   34,  101,   22,
+       97,   34,   22,   27,  101,   27,   22,   93,   26,   34,
+       27,   27,   93,   27,   34, 1273,   34,   27,  129,   17,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       29,   29,   97,   18, 1274,   36,  129,   36,   18,   18,
+       18,   18,   18,   18,   28,   29, 1278,   28,   28,   29,
+       28,   36,   28,   29,   28,   29,   28,   30,   36,   28,
 
-       23,   30,  103,   30,   23,  134,   23,  103,   30,   30,
-       35,   30,   35, 1283,   35,   30, 1284,   35,   20,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   32,
-       32,  110,   21,  675,  110, 1285,  110,  136,   21,   21,
-       21,   21,   21,   21,   31,   32,  136,   31,   31,   32,
-       31,  675,   31,   32,   31,   32,   31,   33,   36,   31,
-      155,   33,   32,   36,   36,   37,   36,   36,  710,   37,
-       33,   33,  163,   38,   33,  222,   33,   37,   39,   38,
-       39,   38,   37,   38,   37,   41,  155,   38,  222,   38,
-       38,  267,  267,   41,   39,  437,  437,   41,  163,   41,
+       33,   30,   29,   32,  150,   33,   33,  102,   33,   33,
+       30,   30,  102,   38,   30,   32,   30,   32,   35,   32,
+       98,   38,   32,  133,   35,   38,   35,   38,   35,  150,
+      124,  217,   35,  133,   35,   35,   44,   44,   44,   44,
+       44,   44,   44,  124,  217,  105,   98,   44,  105,  247,
+      105,   98,   44,   44,   44,   44,   44,   44,   45,   45,
+       45,   45,   45,   45,   45,  158,  246,  581,  246,   45,
+      262,  262,  247,  581,   45,   45,   45,   45,   45,   45,
+       46,   46,   46,   46,   46,   46,   46,   46,  668,  334,
+      158,  668,   46,   78,  334,  269,  346,   46,   46,   46,
 
-       44,   39,  397,   44,  710,   44,   44,   62,   62,   62,
-       62,   62,   62,   62,  274,  339,   63,  351,   44,   63,
-      339,   63,   63,  397,  410, 1292,   44,   48,   48,   48,
-       48,   48,   48,   48,   63,  619,  619,  410,   48,  397,
-      274,  680,   63,  351,   48,   48,   48,   48,   48,   48,
-       49,   49,   49,   49,   49,   49,   49,  376,  439,  680,
-      446,   49,  284,  284,  284,  284, 1296,   49,   49,   49,
-       49,   49,   49,   50,   50,   50,   50,   50,   50,   50,
-       50,  466,  284,  376,  439,   50,  446,  452,  460,  466,
-     1321,   50,   50,   50,   50,   50,   50,   52,   52,   52,
+       46,   46,   46,   48,   48,   48,   48,   48,   48,   48,
+       48,   50,   50,   50,   50,   50,   50,   50,  371,   78,
+      269,  346,   50,  432,  432,   78, 1279,   50,   50,   50,
+       50,   50,   50,   52,   52,   52,   52,   52,   52,   52,
+      614,  614,  667,  371,   52,  665,  665,  667,  434,   52,
+       52,   52,   52,   52,   52,   58,   58,   58,   58,   58,
+       58,   58,  131,  261,  261,  261,  261,  261,  261,  261,
+      350,  131,  148,  434,  148,  148,  148,  148,  148,  148,
+      148,  441,  447, 1280,  350,  148,  279,  279,  279,  279,
+      148,  148,  148,  148,  148,  148,  149,  149,  149,  149,
 
-       52,   52,   52,   52,   52,   54,   54,   54,   54,   54,
-       54,   54,  486,  452,  460,  355,   54, 1324,  413,  670,
-      670,  486,   54,   54,   54,   54,   54,   54,   56,  355,
-      672,   56,  413,   56,   56,  672, 1327,  371,  372,   56,
-       56,   56,   56,   56,   56,   56,   56,  523,  563,  679,
-       56,  371,  372,  679,   56,  355,   56,   56,   56,   56,
-       56,   56,  153,  488,  153,  153,  153,  153,  153,  153,
-      153,  547,  488,  523,  563,  153,  627,  371,  372,  547,
-      686,  153,  153,  153,  153,  153,  153,  154,  154,  154,
-      154,  154,  154,  154,  154,  557,  662,  686, 1330,  154,
+      149,  149,  149,  149,  461,  279,  441,  447,  149,  350,
+      149, 1287,  461,  149,  149,  149,  149,  149,  149,  272,
+      272,  272,  272,  272,  272,  272,  356,  356,  356,  356,
+      356,  356,  356,  366,  681,  149,  151,  151,  151,  151,
+      151,  151,  151,  151,  455,  518,  666,  366,  151,  558,
+      622,  681,  666,  151,  151,  151,  151,  151,  151,  152,
+      152,  152,  152,  152,  152,  152,  152,  152, 1291,  455,
+      518,  152,  366,  625,  558,  622,  152,  152,  152,  152,
+      152,  152,  153,  153,  153,  153,  153,  153,  153,  153,
+      155,  155,  155,  155,  155,  155,  155,  155,  625,  686,
 
-      630,  154,  627,  557,  662,  154,  154,  154,  154,  154,
-      154,  266,  266,  266,  266,  266,  266,  266,  277,  277,
-      277,  277,  277,  277,  277,  455,  630,  154,  156,  156,
-      156,  156,  156,  156,  156,  156,  587,  636, 1333,  455,
-      156,  566,  566,  566,  566,  587,  156,  156,  156,  156,
-      156,  156,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  684, 1336,  636,  157,  455,  643,  655,  684, 1340,
-      157,  157,  157,  157,  157,  157,  158,  158,  158,  158,
-      158,  158,  158,  158,  160,  160,  160,  160,  160,  160,
-      160,  160,  643,  655,  678,  160,  678,  682, 1341,  682,
+      686,  155,  561,  561,  561,  561,  155,  155,  155,  155,
+      155,  155,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  367,  631, 1316,  157,  392,  157,  759,  304,  157,
+      157,  157,  157,  157,  157,  367,  304,  360,  360,  360,
+      360,  360,  360,  360,  759,  392,  405,  631,  304,  670,
+     1319,  157,  255,  255,  255,  255,  255,  255,  255,  405,
+      367,  392,  638,  255,  304,  675, 1322,  670,  255,  255,
+      255,  255,  255,  255,  257,  257,  257,  257,  257,  257,
+      257,  542,  673,  675,  673,  257, 1325,  638,  650,  542,
+      257,  257,  257,  257,  257,  257,  258,  258,  258,  258,
 
-     1342,  160,  160,  160,  160,  160,  160,  162,  162,  162,
-      162,  162,  162,  162,  162,  162,  687,  691,  691,  162,
-     1343,  162, 1344,  309,  687,  162,  162,  162,  162,  162,
-      162,  309,  361,  361,  361,  361,  361,  361,  361,  701,
-      701,  456, 1348,  527,  309,  764,  676,  162,  260,  260,
-      260,  260,  260,  260,  260,  456,  676,  527,  708,  260,
-      309, 1349,  766,  764,  689,  260,  260,  260,  260,  260,
-      260,  262,  262,  262,  262,  262,  262,  262,  588,  689,
-      766,  456,  262,  527,  708,  749,  761,  588,  262,  262,
-      262,  262,  262,  262,  263,  263,  263,  263,  263,  263,
+      258,  258,  258,  258,  260,  260,  260,  260,  260,  260,
+      260,  552,  677,  650,  677,  260,  696,  696, 1328,  552,
+      260,  260,  260,  260,  260,  260,  263,  263,  263,  263,
+      263,  263,  263,  263,  657,  705, 1331, 1335,  263, 1336,
+     1337,  703,  657,  263,  263,  263,  263,  263,  263,  265,
+      265,  265,  265,  265,  265,  265,  265,  268,  268,  268,
+      268,  268,  268,  268,  268,  268,  703, 1338, 1339,  268,
+      705,  268,  761,  450,  268,  268,  268,  268,  268,  268,
+      431,  431,  431,  431,  431,  431,  431,  450,  679,  761,
+     1343, 1344,  676,  451,  522,  679,  268,  273,  273,  273,
 
-      263,  263,  265,  265,  265,  265,  265,  265,  265,  674,
-      805,  749,  761,  265, 1355, 1356, 1363,  772,  674,  265,
-      265,  265,  265,  265,  265,  268,  268,  268,  268,  268,
-      268,  268,  268,  731,  742,  772,  805,  268, 1364, 1371,
-      772,  731,  742,  268,  268,  268,  268,  268,  268,  270,
-      270,  270,  270,  270,  270,  270,  270,  273,  273,  273,
-      273,  273,  273,  273,  273,  273,  859, 1372, 1379,  273,
-     1380,  273, 1384, 1387,  859,  273,  273,  273,  273,  273,
-      273,  365,  365,  365,  365,  365,  365,  365,  436,  436,
-      436,  436,  436,  436,  436,  554,  683,  273,  278,  278,
+      273,  273,  273,  273,  273,  273,  676,  451,  522,  273,
+     1350,  771,  450,  680,  273,  273,  273,  273,  273,  273,
+      274,  274,  274,  274,  274,  274,  274,  680,  771,  771,
+      744,  274,  451,  522,  481,  671,  274,  274,  274,  274,
+      274,  274,  339,  481,  339,  671,  339,  339,  459,  459,
+      459,  459,  459,  459,  459,  744,  339,  549,  339,  339,
+      550,  339,  344,  483,  344,  344,  344,  344,  344,  344,
+      344,  549,  483, 1351,  550,  344,  756, 1358,  782, 1359,
+      344,  344,  344,  344,  344,  344,  345,  345,  345,  345,
+      345,  345,  345,  345,  682,  782,  549, 1366,  345,  550,
 
-      278,  278,  278,  278,  278,  278,  278,  683, 1388,  554,
-      278, 1392,  765,  779, 1394,  681,  278,  278,  278,  278,
-      278,  278,  279,  279,  279,  279,  279,  279,  279,  681,
-      765,  779,  685,  279,  555,  554,  779,  765, 1413,  279,
-      279,  279,  279,  279,  279,  344,  685,  344,  555,  344,
-      344,  464,  464,  464,  464,  464,  464,  464,  773,  344,
-      690,  344,  344,  558,  344,  349,  559,  349,  349,  349,
-      349,  349,  349,  349,  555,  690,  773,  558,  349,  773,
-      559,  776, 1414,  787,  349,  349,  349,  349,  349,  349,
-      350,  350,  350,  350,  350,  350,  350,  350, 1424,  776,
+      345,  756,  682,  345,  345,  345,  345,  345,  345,  463,
+      463,  463,  463,  463,  463,  463,  535,  535,  535,  535,
+      535,  535,  535,  553,  678,  345,  347,  347,  347,  347,
+      347,  347,  347,  347,  800,  678, 1367,  553,  347, 1374,
+      783,  768,  554,  347,  347,  347,  347,  347,  347,  351,
+      351,  351,  351,  351,  351,  351,  554,  783,  768,  800,
+      351,  768,  553,  760,  684,  351,  351,  351,  351,  351,
+      351,  352,  352,  352,  352,  352,  352,  352,  352,  684,
+      760,  554, 1375,  352,  803,  806,  812,  760,  352,  352,
+      352,  352,  352,  352,  353,  353,  353,  353,  353,  353,
 
-      776,  787,  350,  558,  350, 1425,  559, 1429,  350,  350,
-      350,  350,  350,  350,  468,  468,  468,  468,  468,  468,
-      468,  540,  540,  540,  540,  540,  540,  540,  638,  688,
-      350,  352,  352,  352,  352,  352,  352,  352,  352,  688,
-     1430, 1434,  638,  352, 1437,  783,  774,  788,  639,  352,
-      352,  352,  352,  352,  352,  356,  356,  356,  356,  356,
-      356,  356,  639,  783,  774,  788,  356,  774,  638,  784,
-      783,  790,  356,  356,  356,  356,  356,  356,  357,  357,
-      357,  357,  357,  357,  357,  357, 1438,  784,  639,  790,
-      357,  808,  784,  811,  817, 1443,  357,  357,  357,  357,
+      353,  353,  355,  355,  355,  355,  355,  355,  355,  803,
+      806,  812,  819,  355, 1379, 1382,  767,  685,  355,  355,
+      355,  355,  355,  355,  359,  359,  359,  359,  359,  359,
+      359,  359,  685,  767, 1383,  359, 1387,  819,  767,  769,
+      359,  359,  359,  359,  359,  359,  361,  361,  361,  361,
+      361,  361,  361,  361,  361, 1389,  769, 1408,  361,  769,
+      774,  784,  779,  361,  361,  361,  361,  361,  361,  362,
+      362,  362,  362,  362,  362,  362,  362,  774,  784,  779,
+      362,  784,  774,  778,  779,  362,  362,  362,  362,  362,
+      362,  368,  368,  368,  368,  368,  368,  368,  368,  368,
 
-      357,  357,  358,  358,  358,  358,  358,  358,  358,  358,
-      360,  360,  360,  360,  360,  360,  360,  808,  917,  811,
-      817,  360, 1446,  791,  789,  795,  917,  360,  360,  360,
-      360,  360,  360,  364,  364,  364,  364,  364,  364,  364,
-      364,  791,  789,  795,  364,  789,  824,  797,  797, 1447,
-      364,  364,  364,  364,  364,  364,  366,  366,  366,  366,
-      366,  366,  366,  366,  366,  797,  836,  839,  366,  851,
-      866,  867,  824, 1452,  366,  366,  366,  366,  366,  366,
-      367,  367,  367,  367,  367,  367,  367,  367,  866,  867,
-      892,  367,  836,  839,  867,  851,  868,  367,  367,  367,
+      778, 1409,  831,  368, 1419, 1420,  785,  778,  368,  368,
+      368,  368,  368,  368,  370,  370,  370,  370,  370,  370,
+      370,  370,  370,  785, 1424, 1425,  370,  831,  370,  582,
+      687,  370,  370,  370,  370,  370,  370,  485,  582,  485,
+      583,  633,  485,  485,  687,  634,  485,  485,  669,  583,
+      683,  485,  695,  370,  391,  633, 1429,  669,  391,  634,
+      683,  391,  695,  641,  391,  642,  391,  391,  391,  391,
+      425,  425,  425,  425,  425,  425,  425,  641, 1432,  642,
+      633,  425,  834,  786,  634,  688,  425,  425,  425,  425,
+      425,  425,  427,  427,  427,  427,  427,  427,  427,  688,
 
-      367,  367,  367,  373,  373,  373,  373,  373,  373,  373,
-      373,  373, 1455, 1456,  868,  373,  892, 1461,  879,  868,
-      869,  373,  373,  373,  373,  373,  373,  375,  375,  375,
-      375,  375,  375,  375,  375,  375,  879,  879,  869,  375,
-      692,  375, 1464,  869,  693,  375,  375,  375,  375,  375,
-      375,  490,  646,  490,  692,  696,  490,  490,  693,  647,
-      490,  490,  699,  928,  700,  490,  646,  375,  396,  696,
-     1465,  928,  396,  647,  700,  396,  699,  650,  396,  651,
-      396,  396,  396,  396,  430,  430,  430,  430,  430,  430,
-      430,  650,  646,  651, 1473,  430,  780,  871,  873,  647,
+      786, 1433,  641,  427,  642,  846,  887,  834,  427,  427,
+      427,  427,  427,  427,  428,  428,  428,  428,  428,  428,
+      428,  428,  430,  430,  430,  430,  430,  430,  430,  726,
+      846,  887,  943,  430,  955, 1438,  790,  726,  430,  430,
+      430,  430,  430,  430,  433,  433,  433,  433,  433,  433,
+      433,  433,  737,  790, 1441, 1442,  433,  943,  433,  955,
+      737,  433,  433,  433,  433,  433,  433,  540,  540,  540,
+      540,  540,  540,  540,  544,  544,  544,  544,  544,  544,
+      544,  762,  645,  433,  435,  435,  435,  435,  435,  435,
+      435,  988, 1447,  991,  994,  435,  645,  861,  762,  691,
 
-     1502,  430,  430,  430,  430,  430,  430,  432,  432,  432,
-      432,  432,  432,  432,  780,  871,  873,  650,  432,  651,
-      871,  873,  948,  780,  432,  432,  432,  432,  432,  432,
-      433,  433,  433,  433,  433,  433,  433,  433,  435,  435,
-      435,  435,  435,  435,  435, 1503, 1528, 1531,  948,  435,
-     1555,  781,  880,  874,  888,  435,  435,  435,  435,  435,
-      435,  438,  438,  438,  438,  438,  438,  438,  438,  781,
-      880,  874,  888,  438, 1559,  438,  874,  880,  781,  438,
-      438,  438,  438,  438,  438,  545,  545,  545,  545,  545,
-      545,  545,  549,  549,  549,  549,  549,  549,  549,  767,
+      435,  435,  435,  435,  435,  435,  436,  436,  436,  436,
+      436,  436,  436,  691,  861,  762,  988,  436,  991,  994,
+     1450,  645,  436,  436,  436,  436,  436,  436,  437,  437,
+      437,  437,  437,  437,  437,  437,  440,  440,  440,  440,
+      440,  440,  440,  440,  440,  694,  646, 1451,  440, 1456,
+      440, 1459, 1460,  440,  440,  440,  440,  440,  440,  694,
+      646,  653,  653,  653,  653,  653,  653,  653,  655,  655,
+      655,  655,  655,  655,  655,  440,  446,  446,  446,  446,
+      446,  446,  446,  446,  446,  646, 1468, 1497,  446, 1498,
+      446, 1523, 1526,  446,  446,  446,  446,  446,  446,  659,
 
-      752,  438,  440,  440,  440,  440,  440,  440,  440,  960,
-      940,  993,  996,  440,  752,  883, 1563,  767,  940,  440,
-      440,  440,  440,  440,  440,  441,  441,  441,  441,  441,
-      441,  441, 1567,  883,  767,  960,  441,  993,  996,  999,
-      752,  883,  441,  441,  441,  441,  441,  441,  442,  442,
-      442,  442,  442,  442,  442,  442,  445,  445,  445,  445,
-      445,  445,  445,  445,  445,  999, 1571, 1591,  445, 1002,
-      445, 1600, 1275, 1271,  445,  445,  445,  445,  445,  445,
-      658,  658,  658,  658,  658,  658,  658,  660,  660,  660,
-      660,  660,  660,  660,  973, 1002,  445,  451,  451,  451,
+      659,  659,  659,  659,  659,  659,  719,  719,  719,  719,
+      719,  719,  719,  747,  763,  446,  452,  452,  452,  452,
+      452,  452,  452,  452,  452,  997, 1550,  747,  452, 1554,
+     1003,  763,  862,  452,  452,  452,  452,  452,  452,  454,
+      454,  454,  454,  454,  454,  454,  454,  454,  763,  862,
+      997,  454,  747,  454,  862, 1003,  454,  454,  454,  454,
+      454,  454,  724,  724,  724,  724,  724,  724,  724,  728,
+      728,  728,  728,  728,  728,  728,  748,  764,  454,  464,
+      464,  464,  464,  464,  464,  464,  464,  464, 1558, 1010,
+      748,  464, 1562,  883,  764,  751,  464,  464,  464,  464,
 
-      451,  451,  451,  451,  451,  451, 1066, 1270, 1269,  451,
-     1265,  451,  973,  973, 1066,  451,  451,  451,  451,  451,
-      451,  664,  664,  664,  664,  664,  664,  664,  724,  724,
-      724,  724,  724,  724,  724,  753,  768,  451,  457,  457,
-      457,  457,  457,  457,  457,  457,  457, 1264, 1261,  753,
-      457, 1008, 1257, 1015,  768,  886,  457,  457,  457,  457,
-      457,  457,  459,  459,  459,  459,  459,  459,  459,  459,
-      459,  768, 1256,  886,  459,  753,  459, 1008,  886, 1015,
-      459,  459,  459,  459,  459,  459,  729,  729,  729,  729,
-      729,  729,  729,  733,  733,  733,  733,  733,  733,  733,
+      464,  464,  465,  465,  465,  465,  465,  465,  465,  751,
+      883,  764, 1566,  465, 1010,  748,  792,  792,  465,  465,
+      465,  465,  465,  465,  516,  752,  516,  516,  516,  516,
+      516,  516,  516,  792,  751, 1586, 1022,  516, 1595,  752,
+      974,  863,  516,  516,  516,  516,  516,  516,  517,  517,
+      517,  517,  517,  517,  517,  517, 1266,  974,  863,  974,
+      517, 1022,  517,  863,  752,  517,  517,  517,  517,  517,
+      517,  733,  733,  733,  733,  733,  733,  733,  735,  735,
+      735,  735,  735,  735,  735,  766,  772,  517,  519,  519,
+      519,  519,  519,  519,  519,  519,  854, 1265, 1264, 1025,
 
-      756,  769,  459,  469,  469,  469,  469,  469,  469,  469,
-      469,  469, 1255, 1027,  756,  469, 1251,  975, 1250,  769,
-      757,  469,  469,  469,  469,  469,  469,  470,  470,  470,
-      470,  470,  470,  470,  757,  975,  769, 1247,  470, 1027,
-      756,  785,  975,  876,  470,  470,  470,  470,  470,  470,
-      521,  819,  521,  521,  521,  521,  521,  521,  521,  785,
-      757,  876, 1244,  521,  876,  819,  972,  967,  785,  521,
-      521,  521,  521,  521,  521,  522,  522,  522,  522,  522,
-      522,  522,  522, 1243,  972,  967, 1242,  522,  967,  522,
-     1238,  819,  972,  522,  522,  522,  522,  522,  522,  738,
-
-      738,  738,  738,  738,  738,  738,  740,  740,  740,  740,
-      740,  740,  740,  771,  777,  522,  524,  524,  524,  524,
-      524,  524,  524,  524, 1030, 1124, 1237, 1042,  524, 1046,
-     1058,  771,  777, 1124,  524,  524,  524,  524,  524,  524,
-      528,  528,  528,  528,  528,  528,  528,  528,  771, 1135,
-     1030,  777,  528, 1042, 1114, 1046, 1058, 1135,  528,  528,
+      519, 1037,  766,  772,  854,  519,  519,  519,  519,  519,
+      519,  523,  523,  523,  523,  523,  523,  523,  523,  766,
+     1260, 1259,  772,  523, 1025, 1041, 1037, 1053,  523,  523,
+      523,  523,  523,  523,  524,  524,  524,  524,  524,  524,
+      524,  524,  525,  525,  525,  525,  525,  525,  525,  912,
+     1041, 1256, 1053,  525, 1109, 1162, 1174,  912,  525,  525,
+      525,  525,  525,  525,  526,  526,  526,  526,  526,  526,
+      526,  526,  528,  528,  528,  528,  528,  528,  528, 1109,
+     1162, 1174, 1203,  528, 1252, 1251,  864,  866,  528,  528,
       528,  528,  528,  528,  529,  529,  529,  529,  529,  529,
-      529,  529,  530,  530,  530,  530,  530,  530,  530, 1147,
-     1114, 1234, 1233,  530, 1167, 1179, 1208, 1147, 1232,  530,
-      530,  530,  530,  530,  530,  531,  531,  531,  531,  531,
 
-      531,  531,  531,  533,  533,  533,  533,  533,  533,  533,
-     1167, 1179, 1208, 1211,  533, 1228, 1226,  970,  974,  977,
-      533,  533,  533,  533,  533,  533,  534,  534,  534,  534,
-      534,  534,  534,  534,  534,  970,  974,  977,  534, 1211,
-      970,  974,  977,  820,  534,  534,  534,  534,  534,  534,
-      535,  535,  535,  535,  535,  535,  535,  820, 1159, 1225,
-     1214,  535, 1222,  976,  978, 1221, 1159,  535,  535,  535,
-      535,  535,  535,  539,  539,  539,  539,  539,  539,  539,
-      539,  976,  978,  820,  539,  978, 1214,  979,  981,  976,
-      539,  539,  539,  539,  539,  539,  541,  541,  541,  541,
+      529,  529,  529,  864,  866, 1250,  529, 1203,  864,  866,
+      814,  529,  529,  529,  529,  529,  529,  530,  530,  530,
+      530,  530,  530,  530,  814, 1246, 1206, 1245,  530, 1242,
+      868,  869, 1239,  530,  530,  530,  530,  530,  530,  534,
+      534,  534,  534,  534,  534,  534,  534,  868,  869,  814,
+      534, 1206,  868,  869,  871,  534,  534,  534,  534,  534,
+      534,  536,  536,  536,  536,  536,  536,  536,  536,  536,
+     1238,  871, 1209,  536,  871,  874, 1237,  881,  536,  536,
+      536,  536,  536,  536,  537,  537,  537,  537,  537,  537,
+      537,  537,  874,  874,  881,  537, 1233, 1209,  875,  881,
 
-      541,  541,  541,  541,  541,  979,  981,  979,  541, 1218,
-      983,  981,  984, 1215,  541,  541,  541,  541,  541,  541,
-      542,  542,  542,  542,  542,  542,  542,  542,  983, 1212,
-      984,  542, 1209, 1205,  985,  989, 1076,  542,  542,  542,
-      542,  542,  542,  550,  550,  550,  550,  550,  550,  550,
-      550,  550,  985,  989, 1076,  550, 1181, 1079, 1082, 1083,
-     1180,  550,  550,  550,  550,  550,  550,  551,  551,  551,
-      551,  551,  551,  551,  551, 1079, 1082, 1083,  551, 1079,
-     1082, 1084, 1083, 1087,  551,  551,  551,  551,  551,  551,
-      560,  560,  560,  560,  560,  560,  560,  560,  560, 1084,
+      537,  537,  537,  537,  537,  537,  545,  545,  545,  545,
+      545,  545,  545,  545,  545,  875, 1232, 1229,  545, 1212,
+      965,  962,  875,  545,  545,  545,  545,  545,  545,  546,
+      546,  546,  546,  546,  546,  546,  546,  965,  962, 1215,
+      546,  962,  965,  968, 1212,  546,  546,  546,  546,  546,
+      546,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      968,  968, 1240,  555, 1215, 1228,  970,  969,  555,  555,
+      555,  555,  555,  555,  557,  557,  557,  557,  557,  557,
+      557,  557,  557,  970,  969, 1227,  557, 1240,  557,  969,
+      970,  557,  557,  557,  557,  557,  557,  739,  739,  739,
 
-     1177, 1087,  560, 1217, 1220, 1088, 1087, 1173,  560,  560,
-      560,  560,  560,  560,  562,  562,  562,  562,  562,  562,
-      562,  562,  562, 1088, 1172, 1088,  562, 1169,  562, 1217,
-     1220, 1164,  562,  562,  562,  562,  562,  562,  744,  744,
-      744,  744,  744,  744,  744,  750,  750,  750,  750,  750,
-      750,  750,  872,  778,  562,  613,  613,  613,  613,  613,
-      613,  613, 1245, 1163, 1259, 1273,  613, 1319, 1092, 1160,
-      872,  778,  613,  613,  613,  613,  613,  613,  615,  615,
-      615,  615,  615,  615,  615,  778, 1092,  872, 1245,  615,
-     1259, 1273, 1092, 1319, 1152,  615,  615,  615,  615,  615,
+      739,  739,  739,  739,  745,  745,  745,  745,  745,  745,
+      745,  867,  773,  557,  608,  608,  608,  608,  608,  608,
+      608, 1254, 1223, 1268, 1221,  608, 1314,  972,  867,  773,
+      608,  608,  608,  608,  608,  608,  610,  610,  610,  610,
+      610,  610,  610,  773,  972,  867, 1254,  610, 1268,  972,
+     1377, 1314,  610,  610,  610,  610,  610,  610,  611,  611,
+      611,  611,  611,  611,  611,  611,  613,  613,  613,  613,
+      613,  613,  613,  923, 1427, 1377, 1436,  613, 1445,  878,
+      976,  923,  613,  613,  613,  613,  613,  613,  615,  615,
+      615,  615,  615,  615,  615,  615,  878,  976, 1220, 1427,
 
-      615,  616,  616,  616,  616,  616,  616,  616,  616,  618,
-      618,  618,  618,  618,  618,  618, 1291, 1151, 1148, 1382,
-      618, 1432,  882, 1090, 1291, 1093,  618,  618,  618,  618,
-      618,  618,  620,  620,  620,  620,  620,  620,  620,  620,
-      882, 1090, 1090, 1093,  620, 1382, 1093, 1432, 1441,  882,
-      620,  620,  620,  620,  620,  620,  621,  621,  621,  621,
-      621,  621,  621,  621,  622,  622,  622,  622,  622,  622,
-      622, 1347, 1354, 1140, 1441,  622, 1139, 1136, 1129, 1347,
-     1354,  622,  622,  622,  622,  622,  622,  623,  623,  623,
-      623,  623,  623,  623,  623,  626,  626,  626,  626,  626,
+      615, 1436,  976, 1445,  878,  615,  615,  615,  615,  615,
+      615,  616,  616,  616,  616,  616,  616,  616,  616,  617,
+      617,  617,  617,  617,  617,  617,  935, 1217, 1216, 1213,
+      617, 1210, 1207, 1204,  935,  617,  617,  617,  617,  617,
+      617,  618,  618,  618,  618,  618,  618,  618,  618,  621,
+      621,  621,  621,  621,  621,  621,  621,  621,  765,  775,
+      776,  621,  777,  621,  973,  978,  621,  621,  621,  621,
+      621,  621, 1061, 1200, 1176,  765,  775,  776, 1175,  777,
+     1061,  973,  978,  770,  973,  775,  776,  765,  621,  624,
+      624,  624,  624,  624,  624,  624,  624,  624,  777,  780,
 
-      626,  626,  626,  626,  770,  884,  827,  626,  782,  626,
-      786, 1182, 1186,  626,  626,  626,  626,  626,  626, 1362,
-      827, 1128,  770,  884, 1125, 1120,  782, 1362,  786, 1182,
-     1186,  775,  884,  792,  770,  626,  629,  629,  629,  629,
-      629,  629,  629,  629,  629,  782,  827,  786,  629,  775,
-      629,  792, 1370, 1182,  629,  629,  629,  629,  629,  629,
-     1370,  775, 1119, 1116,  792,  799,  799,  799,  799,  799,
-      799,  799,  793,  828,  831, 1450,  629,  635,  635,  635,
-      635,  635,  635,  635,  635,  635, 1183,  828,  831,  635,
-      793,  635,  832,  842,  843,  635,  635,  635,  635,  635,
+      770,  624,  781,  624,  979, 1119,  624,  624,  624,  624,
+      624,  624,  770, 1119, 1172, 1130,  780, 1454, 1168,  781,
+     1167,  979,  787, 1130, 1164,  780,  815,  788,  624,  630,
+      630,  630,  630,  630,  630,  630,  630,  630,  781,  787,
+      815,  630, 1454,  630,  788, 1142,  630,  630,  630,  630,
+      630,  630,  787, 1142, 1521, 1159,  788,  794,  794,  794,
+      794,  794,  794,  794,  822,  815,  823,  873,  630,  635,
+      635,  635,  635,  635,  635,  635,  635,  635,  822, 1521,
+      823,  635, 1158, 1548,  873, 1155,  635,  635,  635,  635,
+      635,  635,  637,  637,  637,  637,  637,  637,  637,  637,
 
-      635, 1450,  793, 1378, 1183, 1459,  832,  842,  843, 1184,
-     1115, 1378, 1112,  828,  831,  846, 1111,  635,  640,  640,
-      640,  640,  640,  640,  640,  640,  640, 1184, 1183,  846,
-      640, 1459,  832,  842,  843, 1189,  640,  640,  640,  640,
-      640,  640,  642,  642,  642,  642,  642,  642,  642,  642,
-      642, 1184, 1108, 1189,  642,  846,  642, 1105, 1189,  847,
-      642,  642,  642,  642,  642,  642,  840,  840,  840,  840,
-      840,  840,  840,  847,  855,  855,  855,  855,  855,  855,
-      855, 1102,  642,  652,  652,  652,  652,  652,  652,  652,
-      652,  652, 1423, 1098, 1526,  652, 1553, 1557, 1185,  847,
+      637,  873,  826,  822,  637,  823,  637,  827, 1548,  637,
+      637,  637,  637,  637,  637, 1147,  826, 1552, 1146, 1143,
+     1556,  827,  835,  835,  835,  835,  835,  835,  835,  837,
+      980,  637,  647,  647,  647,  647,  647,  647,  647,  647,
+      647,  826, 1552,  837,  647, 1556,  827,  980, 1135,  647,
+      647,  647,  647,  647,  647,  649,  649,  649,  649,  649,
+      649,  649,  649,  649,  876,  838,  841,  649,  837,  649,
+      842, 1134,  649,  649,  649,  649,  649,  649, 1131,  838,
+      841,  876, 1124, 1560,  842,  850,  850,  850,  850,  850,
+      850,  850,  876,  865,  649,  660,  660,  660,  660,  660,
 
-     1423,  652,  652,  652,  652,  652,  652,  654,  654,  654,
-      654,  654,  654,  654,  654,  654, 1185, 1071, 1185,  654,
-     1526,  654, 1553, 1557, 1067,  654,  654,  654,  654,  654,
-      654,  857,  857,  857,  857,  857,  857,  857,  861,  861,
-      861,  861,  861,  861,  861,  878,  870,  654,  665,  665,
-      665,  665,  665,  665,  665,  665,  665, 1472, 1060, 1059,
-      665, 1056, 1561,  878,  870, 1472,  665,  665,  665,  665,
-      665,  665,  666,  666,  666,  666,  666,  666,  666,  870,
-      878, 1052, 1051,  666,  887,  875,  877,  885, 1561,  666,
-      666,  666,  666,  666,  666,  669,  669,  669,  669,  669,
+      660,  660,  660,  660,  838,  841, 1123,  660, 1560,  842,
+      865,  882,  660,  660,  660,  660,  660,  660,  661,  661,
+      661,  661,  661,  661,  661,  865, 1120, 1115,  882,  661,
+     1114,  984, 1071, 1079,  661,  661,  661,  661,  661,  661,
+      664,  664,  664,  664,  664,  664,  664,  882,  984, 1071,
+     1079,  664,  870,  872,  958,  880,  664,  664,  664,  664,
+      664,  664,  852,  852,  852,  852,  852,  852,  852,  870,
+      872,  958,  880,  946,  664,  699,  947,  699,  699,  699,
+      699,  699,  699,  699,  870,  872,  958,  946,  699,  880,
+      947, 1083, 1074,  699,  699,  699,  699,  699,  699,  700,
 
-      669,  669,  887,  875,  877,  885,  669,  966, 1078,  951,
-      963,  881,  669,  669,  669,  669,  669,  669,  875,  877,
-     1565,  887,  885,  951, 1532,  966, 1078,  952,  963,  881,
-      669,  704, 1532,  704,  704,  704,  704,  704,  704,  704,
-      881,  952,  966,  963,  704, 1078, 1565,  964, 1048,  951,
-      704,  704,  704,  704,  704,  704,  910,  910,  910,  910,
-      910,  910,  910,  955,  956,  964,  968,  952,  704,  705,
-      705,  705,  705,  705,  705,  705,  705,  955,  956, 1044,
-      964,  705, 1190, 1298,  968,  968, 1043,  705,  705,  705,
-      705,  705,  705,  915,  915,  915,  915,  915,  915,  915,
+      700,  700,  700,  700,  700,  700,  700, 1111, 1083, 1074,
+     1083,  700,  946, 1074, 1110,  947,  700,  700,  700,  700,
+      700,  700,  701,  701,  701,  701,  701,  701,  701,  856,
+      856,  856,  856,  856,  856,  856,  961,  959,  877,  905,
+      905,  905,  905,  905,  905,  905,  910,  910,  910,  910,
+      910,  910,  910,  961,  959,  877,  701,  702,  702,  702,
+      702,  702,  702,  702,  877, 1107, 1106, 1103,  702,  959,
+      961, 1564, 1584,  702,  702,  702,  702,  702,  702,  704,
+      704,  704,  704,  704,  704,  704,  704,  706,  706,  706,
+      706,  706,  706,  706,  706, 1154, 1564, 1584, 1100,  706,
 
-     1190, 1298,  968,  955,  956,  705,  706,  706,  706,  706,
-      706,  706,  706,  919,  919,  919,  919,  919,  919,  919,
-      924,  924,  924,  924,  924,  924,  924,  926,  926,  926,
-      926,  926,  926,  926,  930,  930,  930,  930,  930,  930,
-      930,  706,  707,  707,  707,  707,  707,  707,  707, 1040,
-     1036, 1035, 1032,  707, 1029, 1569, 1589, 1598, 1028,  707,
-      707,  707,  707,  707,  707,  709,  709,  709,  709,  709,
-      709,  709,  709,  711,  711,  711,  711,  711,  711,  711,
-      711, 1569, 1589, 1598, 1025,  711, 1021, 1020, 1017, 1016,
-     1013,  711,  711,  711,  711,  711,  711,  712,  712,  712,
+     1593, 1097, 1093, 1154,  706,  706,  706,  706,  706,  706,
+      707,  707,  707,  707,  707,  707,  707,  707,  709,  709,
+      709,  709,  709,  709,  709, 1593, 1066, 1062, 1055,  709,
+     1054, 1051, 1077, 1078,  709,  709,  709,  709,  709,  709,
+      710,  710,  710,  710,  710,  710,  710,  710,  710, 1077,
+     1078, 1047,  710, 1077, 1082, 1078,  950,  710,  710,  710,
+      710,  710,  710,  711,  711,  711,  711,  711,  711,  711,
+      950, 1082, 1046, 1043,  711, 1039, 1082, 1087, 1038,  711,
+      711,  711,  711,  711,  711,  713,  713,  713,  713,  713,
+      713,  713,  713,  713, 1087,  950, 1035,  713, 1031, 1085,
 
-      712,  712,  712,  712,  712,  714,  714,  714,  714,  714,
-      714,  714, 1009, 1005, 1004, 1003,  714, 1000,  997, 1201,
-     1202, 1187,  714,  714,  714,  714,  714,  714,  715,  715,
-      715,  715,  715,  715,  715,  715,  715, 1201, 1202, 1187,
-      715, 1201,  994, 1202, 1299, 1010,  715,  715,  715,  715,
-      715,  715,  716,  716,  716,  716,  716,  716,  716, 1010,
-     1187,  991, 1299,  716,  990,  962, 1300,  961, 1301,  716,
-      716,  716,  716,  716,  716,  718,  718,  718,  718,  718,
-      718,  718,  718,  718, 1300, 1010, 1301,  718,  958, 1192,
-     1302, 1310, 1011,  718,  718,  718,  718,  718,  718,  719,
+     1087,  951,  713,  713,  713,  713,  713,  713,  714,  714,
+      714,  714,  714,  714,  714,  951, 1085, 1085, 1030,  714,
+     1027, 1177, 1088, 1024,  714,  714,  714,  714,  714,  714,
+      718,  718,  718,  718,  718,  718,  718,  718, 1177, 1088,
+      951,  718, 1088, 1023, 1178, 1020,  718,  718,  718,  718,
+      718,  718,  720,  720,  720,  720,  720,  720,  720,  720,
+      720, 1178, 1177, 1016,  720, 1015, 1179, 1181, 1012,  720,
+      720,  720,  720,  720,  720,  721,  721,  721,  721,  721,
+      721,  721,  721, 1179, 1181, 1178,  721, 1011, 1008, 1180,
+     1004,  721,  721,  721,  721,  721,  721,  729,  729,  729,
 
-      719,  719,  719,  719,  719,  719, 1011, 1192, 1302, 1310,
-      719,  954, 1307, 1302, 1310, 1192,  719,  719,  719,  719,
-      719,  719,  723,  723,  723,  723,  723,  723,  723,  723,
-     1307,  953, 1011,  723,  950,  945,  941, 1314, 1315,  723,
-      723,  723,  723,  723,  723,  725,  725,  725,  725,  725,
-      725,  725,  725,  725, 1307, 1314, 1315,  725,  933,  929,
-     1396, 1397,  922,  725,  725,  725,  725,  725,  725,  726,
-      726,  726,  726,  726,  726,  726,  726, 1315, 1396, 1397,
-      726, 1396, 1397, 1398, 1399, 1401,  726,  726,  726,  726,
-      726,  726,  734,  734,  734,  734,  734,  734,  734,  734,
+      729,  729,  729,  729,  729,  729, 1180, 1179, 1180,  729,
+     1000, 1184, 1185, 1182,  729,  729,  729,  729,  729,  729,
+      730,  730,  730,  730,  730,  730,  730,  730, 1184, 1185,
+     1182,  730,  999, 1184,  998, 1196,  730,  730,  730,  730,
+      730,  730,  740,  740,  740,  740,  740,  740,  740,  740,
+      740, 1182, 1196,  995,  740,  992, 1196, 1197, 1293,  740,
+      740,  740,  740,  740,  740,  741,  741,  741,  741,  741,
+      741,  741,  741,  989, 1197, 1293,  741,  986,  985, 1197,
+     1294,  741,  741,  741,  741,  741,  741,  753,  753,  753,
+      753,  753,  753,  753,  753,  753,  957, 1294,  956,  753,
 
-      734, 1398, 1399, 1401,  734,  918, 1399,  913, 1402,  908,
-      734,  734,  734,  734,  734,  734,  735,  735,  735,  735,
-      735,  735,  735,  735,  907, 1398, 1402,  735,  906,  903,
-     1402, 1403, 1404,  735,  735,  735,  735,  735,  735,  745,
-      745,  745,  745,  745,  745,  745,  745,  745,  900, 1403,
-     1404,  745,  896, 1403, 1406, 1409, 1404,  745,  745,  745,
-      745,  745,  745,  746,  746,  746,  746,  746,  746,  746,
-      746,  864, 1406, 1409,  746,  860, 1406, 1477, 1409, 1478,
-      746,  746,  746,  746,  746,  746,  758,  758,  758,  758,
-      758,  758,  758,  758,  758, 1477,  853, 1478,  758,  852,
+      953,  949,  948,  975,  753,  753,  753,  753,  753,  753,
+      755,  755,  755,  755,  755,  755,  755,  755,  755,  879,
+      975, 1005,  755,  945,  755,  940,  936,  755,  755,  755,
+      755,  755,  755,  975,  967, 1005,  879,  914,  914,  914,
+      914,  914,  914,  914, 1076,  879,  928,  963, 1006,  755,
+      789,  967,  789,  789,  789,  789,  789,  789,  789,  967,
+     1005, 1076, 1006,  789,  963,  963, 1295,  789,  789,  789,
+      789,  789,  789,  789,  791,  791,  791,  791,  791,  791,
+      791, 1076,  963, 1295,  924,  791,  971, 1006, 1296, 1309,
+      791,  791,  791,  791,  791,  791,  793,  793,  793,  793,
 
-      849, 1488,  845, 1477,  758,  758,  758,  758,  758,  758,
-      760,  760,  760,  760,  760,  760,  760,  760,  760, 1488,
-     1488,  844,  760,  841,  760,  838,  837,  834,  760,  760,
-      760,  760,  760,  760,  936,  936,  936,  936,  936,  936,
-      936,  938,  938,  938,  938,  938,  938,  938, 1018,  969,
-      760,  794, 1019,  794,  794,  794,  794,  794,  794,  794,
-      830,  829, 1018,  826,  794,  825, 1019,  969, 1081,  794,
-      794,  794,  794,  794,  794,  794,  796,  796,  796,  796,
-      796,  796,  796,  969,  822,  818, 1081,  796, 1018, 1534,
-     1491, 1536, 1019,  796,  796,  796,  796,  796,  796,  798,
+      793,  793,  793,  971,  917, 1296, 1309,  793,  913, 1187,
+     1297,  971,  793,  793,  793,  793,  793,  793,  795,  795,
+      795,  795,  795,  795,  795,  795, 1187, 1297,  908,  903,
+      795,  902, 1297,  901, 1187,  795,  795,  795,  795,  795,
+      795,  796,  796,  796,  796,  796,  796,  796,  796,  799,
+      799,  799,  799,  799,  799,  799,  799,  799,  898,  895,
+      891,  799,  859,  799,  855,  848,  799,  799,  799,  799,
+      799,  799,  919,  919,  919,  919,  919,  919,  919,  921,
+      921,  921,  921,  921,  921,  921,  847, 1396,  799,  802,
+      802,  802,  802,  802,  802,  802,  802,  802,  844,  840,
 
-      798,  798,  798,  798,  798,  798, 1081, 1534, 1491, 1536,
-      798, 1491, 1303, 1537, 1544, 1548,  798,  798,  798,  798,
-      798,  798,  800,  800,  800,  800,  800,  800,  800,  800,
-     1303, 1537, 1544, 1548,  800,  815, 1537, 1544,  814, 1303,
-      800,  800,  800,  800,  800,  800,  801,  801,  801,  801,
-      801,  801,  801,  801,  804,  804,  804,  804,  804,  804,
-      804,  804,  804,  813,  812,  809,  804,  806,  804,  803,
-      802,  763,  804,  804,  804,  804,  804,  804,  942,  942,
-      942,  942,  942,  942,  942,  949,  949,  949,  949,  949,
-      949,  949,  965,  971,  804,  807,  807,  807,  807,  807,
+      839,  802,  836,  802, 1396,  833,  802,  802,  802,  802,
+      802,  802,  925,  925,  925,  925,  925,  925,  925,  931,
+      931,  931,  931,  931,  931,  931,  832, 1473,  802,  805,
+      805,  805,  805,  805,  805,  805,  805,  805,  829,  825,
+      824,  805,  821,  805, 1473,  820,  805,  805,  805,  805,
+      805,  805,  933,  933,  933,  933,  933,  933,  933,  937,
+      937,  937,  937,  937,  937,  937, 1013,  960,  805,  811,
+      811,  811,  811,  811,  811,  811,  811,  811,  817,  813,
+     1013,  811,  810,  811,  960,  964,  811,  811,  811,  811,
+      811,  811,  944,  944,  944,  944,  944,  944,  944,  960,
 
-      807,  807,  807,  807, 1073, 1074, 1022,  807,  762,  807,
-      965,  971, 1479,  807,  807,  807,  807,  807,  807,  759,
-     1022,  755, 1073, 1074,  754,  965,  965,  982,  971,  980,
-     1479, 1077,  751, 1073, 1074,  807,  810,  810,  810,  810,
-      810,  810,  810,  810,  810,  982, 1022,  980,  810, 1077,
-      810, 1479, 1023,  747,  810,  810,  810,  810,  810,  810,
-      980, 1033,  982, 1077,  743,  736, 1023, 1031, 1031, 1031,
-     1031, 1031, 1031, 1031, 1034, 1033,  810,  816,  816,  816,
-      816,  816,  816,  816,  816,  816, 1576, 1075, 1034,  816,
-      732,  816, 1023, 1037, 1038,  816,  816,  816,  816,  816,
+      960,  809,  964,  808,  807, 1013, 1014,  966,  811,  816,
+      816,  816,  816,  816,  816,  816,  816,  816,  964,  804,
+     1014,  816,  801,  798,  966,  977,  816,  816,  816,  816,
+      816,  816,  818,  818,  818,  818,  818,  818,  818,  818,
+      818,  966,  977, 1017,  818, 1014,  818, 1018, 1286,  818,
+      818,  818,  818,  818,  818,  797, 1286, 1017,  758,  977,
+      757, 1018, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1028,
+      754,  818,  828,  828,  828,  828,  828,  828,  828,  828,
+      828,  750, 1017, 1028,  828,  749, 1018, 1072,  746,  828,
+      828,  828,  828,  828,  828,  830,  830,  830,  830,  830,
 
-      816, 1033,  727,  722, 1576, 1075,  721, 1037, 1038,  720,
-     1541,  717,  713, 1049, 1034, 1050, 1075,  816,  821,  821,
-      821,  821,  821,  821,  821,  821,  821, 1049, 1541, 1050,
-      821,  703,  702, 1037, 1038,  698,  821,  821,  821,  821,
-      821,  821,  823,  823,  823,  823,  823,  823,  823,  823,
-      823, 1541,  697, 1049,  823, 1050,  823, 1085, 1196, 1053,
-      823,  823,  823,  823,  823,  823, 1047, 1047, 1047, 1047,
-     1047, 1047, 1047, 1053,  695, 1085, 1196,  694, 1054, 1410,
-     1197,  677,  823,  833,  833,  833,  833,  833,  833,  833,
-      833,  833, 1054, 1196, 1085,  833,  667, 1410, 1197, 1053,
+      830,  830,  830,  830, 1072, 1029, 1032,  830, 1028,  830,
+     1033,  742,  830,  830,  830,  830,  830,  830, 1072, 1029,
+     1032,  738,  731,  727, 1033, 1042, 1042, 1042, 1042, 1042,
+     1042, 1042, 1044, 1302,  830,  843,  843,  843,  843,  843,
+      843,  843,  843,  843, 1029, 1032, 1044,  843,  722, 1033,
+     1302,  717,  843,  843,  843,  843,  843,  843,  845,  845,
+      845,  845,  845,  845,  845,  845,  845, 1068, 1045, 1048,
+      845, 1044,  845, 1049, 1302,  845,  845,  845,  845,  845,
+      845,  716, 1045, 1048, 1068,  715,  712, 1049, 1057, 1057,
+     1057, 1057, 1057, 1057, 1057, 1068,  708,  845,  857,  857,
 
-      663,  833,  833,  833,  833,  833,  833,  835,  835,  835,
-      835,  835,  835,  835,  835,  835, 1197, 1410, 1054,  835,
-      657,  835,  656,  653,  649,  835,  835,  835,  835,  835,
-      835, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1064, 1064,
-     1064, 1064, 1064, 1064, 1064, 1170, 1094,  835,  848,  848,
-      848,  848,  848,  848,  848,  848,  848,  648,  645, 1170,
-      848,  644,  641,  637, 1094, 1094,  848,  848,  848,  848,
-      848,  848,  850,  850,  850,  850,  850,  850,  850,  850,
-      850, 1094, 1094,  634,  850, 1170,  850, 1587, 1486, 1086,
-      850,  850,  850,  850,  850,  850, 1068, 1068, 1068, 1068,
+      857,  857,  857,  857,  857,  857,  857, 1045, 1048,  698,
+      857,  697, 1049, 1075, 1165,  857,  857,  857,  857,  857,
+      857,  858,  858,  858,  858,  858,  858,  858, 1165,  693,
+     1075,  692,  858,  690,  689, 1305,  672,  858,  858,  858,
+      858,  858,  858,  884, 1075,  884,  884,  884,  884,  884,
+      884,  884, 1305, 1165,  662,  658,  884, 1305, 1393, 1310,
+      884,  884,  884,  884,  884,  884,  884,  885,  885,  885,
+      885,  885,  885,  885, 1342, 1393, 1310,  652,  885,  651,
+      648, 1394, 1342,  885,  885,  885,  885,  885,  885,  886,
+      886,  886,  886,  886,  886,  886,  886, 1310, 1394, 1393,
 
-     1068, 1068, 1068,  633,  632, 1587, 1486, 1086, 1200, 1171,
-     1174,  631,  850,  862,  862,  862,  862,  862,  862,  862,
-      862,  862, 1086, 1171, 1174,  862, 1200, 1486, 1612, 1080,
-     1175,  862,  862,  862,  862,  862,  862,  863,  863,  863,
-      863,  863,  863,  863, 1175, 1200, 1612, 1080,  863, 1171,
-     1174, 1578,  628, 1579,  863,  863,  863,  863,  863,  863,
-      889, 1080,  889,  889,  889,  889,  889,  889,  889, 1578,
-     1175, 1579, 1578,  889, 1579, 1620, 1580, 1628,  889,  889,
-      889,  889,  889,  889,  889,  890,  890,  890,  890,  890,
-      890,  890,  625, 1620, 1580, 1628,  890, 1580, 1411, 1089,
+      644,  886, 1394,  886,  643,  640,  886,  886,  886,  886,
+      886,  886, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1063,
+     1063, 1063, 1063, 1063, 1063, 1063, 1073, 1081,  886,  888,
+      888,  888,  888,  888,  888,  888,  639,  636,  632,  629,
+      888,  628,  627, 1073, 1081,  888,  888,  888,  888,  888,
+      888,  889,  889,  889,  889,  889,  889,  889,  889, 1081,
+      626,  623, 1073,  889,  620,  619,  612,  609,  889,  889,
+      889,  889,  889,  889,  890,  890,  890,  890,  890,  890,
+      890,  890,  892,  892,  892,  892,  892,  892,  892, 1349,
+      607,  603,  597,  892,  596,  595, 1397, 1349,  892,  892,
 
-     1585, 1091,  890,  890,  890,  890,  890,  890,  891,  891,
-      891,  891,  891,  891,  891,  891, 1411, 1089, 1585, 1091,
-      891, 1585,  891,  624,  617, 1411,  891,  891,  891,  891,
-      891,  891, 1089, 1091, 1117, 1117, 1117, 1117, 1117, 1117,
-     1117, 1122, 1122, 1122, 1122, 1122, 1122, 1122,  891,  893,
-      893,  893,  893,  893,  893,  893,  614,  612,  608,  602,
-      893,  601, 1476, 1605, 1607, 1608,  893,  893,  893,  893,
-      893,  893,  894,  894,  894,  894,  894,  894,  894,  894,
-     1476, 1605, 1607, 1608,  894, 1605,  600, 1607, 1608, 1476,
-      894,  894,  894,  894,  894,  894,  895,  895,  895,  895,
+      892,  892,  892,  892,  893,  893,  893,  893,  893,  893,
+      893,  893,  893, 1397,  594,  590,  893, 1397, 1404, 1391,
+     1166,  893,  893,  893,  893,  893,  893,  894,  894,  894,
+      894,  894,  894,  894, 1166, 1404, 1391,  589,  894, 1391,
+     1404, 1398,  587,  894,  894,  894,  894,  894,  894,  896,
+      896,  896,  896,  896,  896,  896,  896,  896, 1398, 1166,
+      586,  896, 1398, 1399, 1392, 1169,  896,  896,  896,  896,
+      896,  896,  897,  897,  897,  897,  897,  897,  897, 1169,
+     1399, 1392,  585,  897, 1392,  584, 1399,  580,  897,  897,
+      897,  897,  897,  897,  899,  899,  899,  899,  899,  899,
 
-      895,  895,  895,  895,  897,  897,  897,  897,  897,  897,
-      897,  599,  595,  594,  592,  897,  591,  590, 1633, 1634,
-     1622,  897,  897,  897,  897,  897,  897,  898,  898,  898,
-      898,  898,  898,  898,  898,  898, 1633, 1634, 1622,  898,
-      589,  585, 1634, 1635, 1229,  898,  898,  898,  898,  898,
-      898,  899,  899,  899,  899,  899,  899,  899, 1229, 1622,
-      584, 1635,  899,  583,  582, 1636, 1635, 1623,  899,  899,
-      899,  899,  899,  899,  901,  901,  901,  901,  901,  901,
-      901,  901,  901, 1636, 1229, 1623,  901,  581, 1636, 1638,
-     1640, 1230,  901,  901,  901,  901,  901,  901,  902,  902,
+      899,  899,  899,  579, 1169,  578,  899,  577, 1401, 1474,
+     1170,  899,  899,  899,  899,  899,  899,  900,  900,  900,
+      900,  900,  900,  900, 1170, 1401, 1474,  576,  900, 1401,
+      575, 1486,  574,  900,  900,  900,  900,  900,  900,  904,
+      904,  904,  904,  904,  904,  904,  904, 1474, 1486, 1170,
+      904, 1486,  573, 1529, 1481,  904,  904,  904,  904,  904,
+      904,  906,  906,  906,  906,  906,  906,  906,  906,  906,
+     1529, 1481,  572,  906,  571,  570, 1483,  569,  906,  906,
+      906,  906,  906,  906,  907,  907,  907,  907,  907,  907,
+      907,  907, 1481, 1483, 1483,  907,  568,  567, 1531, 1532,
 
-      902,  902,  902,  902,  902, 1230, 1623, 1638, 1640,  902,
-      580,  579, 1638,  578, 1624,  902,  902,  902,  902,  902,
-      902,  904,  904,  904,  904,  904,  904,  904,  904,  904,
-      577, 1230, 1624,  904,  576,  575, 1645, 1647, 1235,  904,
-      904,  904,  904,  904,  904,  905,  905,  905,  905,  905,
-      905,  905, 1235, 1624, 1645, 1647,  905, 1645, 1649, 1647,
-      574,  573,  905,  905,  905,  905,  905,  905,  909,  909,
-      909,  909,  909,  909,  909,  909, 1649,  572, 1235,  909,
-      569, 1649, 1651, 1652, 1657,  909,  909,  909,  909,  909,
-      909,  911,  911,  911,  911,  911,  911,  911,  911,  911,
+      907,  907,  907,  907,  907,  907,  915,  915,  915,  915,
+      915,  915,  915,  915,  915, 1531, 1532,  564,  915,  563,
+     1536, 1532, 1539,  915,  915,  915,  915,  915,  915,  916,
+      916,  916,  916,  916,  916,  916,  916, 1536,  562, 1539,
+      916,  560,  559,  556, 1539,  916,  916,  916,  916,  916,
+      916,  926,  926,  926,  926,  926,  926,  926,  926,  926,
+     1536,  551,  547,  926,  543, 1543, 1571, 1573,  926,  926,
+      926,  926,  926,  926,  927,  927,  927,  927,  927,  927,
+      927,  927, 1543, 1571, 1573,  927,  538, 1573, 1582, 1574,
+      927,  927,  927,  927,  927,  927,  938,  938,  938,  938,
 
-     1651, 1652, 1657,  911,  568, 1651, 1653,  567,  565,  911,
-      911,  911,  911,  911,  911,  912,  912,  912,  912,  912,
-      912,  912,  912, 1657, 1653, 1652,  912,  564,  561, 1660,
-      556, 1664,  912,  912,  912,  912,  912,  912,  920,  920,
-      920,  920,  920,  920,  920,  920,  920, 1660, 1653, 1664,
-      920,  552, 1660, 1668, 1669,  548,  920,  920,  920,  920,
-      920,  920,  921,  921,  921,  921,  921,  921,  921,  921,
-      543, 1668, 1669,  921,  538,  537, 1668, 1669, 1674,  921,
-      921,  921,  921,  921,  921,  931,  931,  931,  931,  931,
-      931,  931,  931,  931,  536,  532, 1674,  931,  526, 1675,
+      938,  938,  938,  938,  938, 1582, 1574,  533,  938, 1574,
+     1607, 1575, 1580,  938,  938,  938,  938,  938,  938,  939,
+      939,  939,  939,  939,  939,  939,  939, 1607, 1575, 1580,
+      939, 1575, 1580, 1600, 1602,  939,  939,  939,  939,  939,
+      939,  952,  952,  952,  952,  952,  952,  952,  952,  952,
+     1600, 1602,  532,  952, 1600,  531, 1602,  527,  952,  952,
+      952,  952,  952,  952,  954,  954,  954,  954,  954,  954,
+      954,  954,  954, 1069, 1070,  521,  954, 1080,  954, 1224,
+     1089,  954,  954,  954,  954,  954,  954, 1357, 1365,  520,
+     1069, 1070, 1373, 1224, 1080, 1357, 1365, 1089, 1089, 1615,
 
-     1677, 1674,  525,  931,  931,  931,  931,  931,  931,  932,
-      932,  932,  932,  932,  932,  932,  932, 1675, 1677,  520,
-      932, 1675,  519, 1679, 1682, 1683,  932,  932,  932,  932,
-      932,  932,  943,  943,  943,  943,  943,  943,  943,  943,
-      943, 1679, 1682, 1683,  943, 1682, 1679, 1684, 1689,  518,
-      943,  943,  943,  943,  943,  943,  944,  944,  944,  944,
-      944,  944,  944,  944,  517, 1684, 1689,  944,  516,  515,
-     1694, 1689, 1698,  944,  944,  944,  944,  944,  944,  957,
-      957,  957,  957,  957,  957,  957,  957,  957, 1694, 1684,
-     1698,  957,  514,  513, 1700, 1698, 1703,  957,  957,  957,
+     1373, 1069, 1070,  954,  981,  981,  981,  981,  981,  981,
+      981,  981,  981, 1080, 1089, 1089, 1615,  981, 1224,  515,
+      514,  981,  981,  981,  981,  981,  981,  981,  982,  982,
+      982,  982,  982,  982,  982,  982,  983,  983,  983,  983,
+      983,  983,  983,  983,  983,  513, 1084, 1189, 1086,  512,
+     1623,  511, 1195,  983,  987,  987,  987,  987,  987,  987,
+      987,  987,  987, 1084, 1189, 1086,  987, 1623,  987, 1195,
+     1191,  987,  987,  987,  987,  987,  987, 1189, 1084, 1086,
+     1112, 1112, 1112, 1112, 1112, 1112, 1112, 1191, 1195,  510,
+     1628,  509, 1635,  987,  990,  990,  990,  990,  990,  990,
 
-      957,  957,  957,  959,  959,  959,  959,  959,  959,  959,
-      959,  959, 1700,  512, 1703,  959,  511,  959,  510,  509,
-      508,  959,  959,  959,  959,  959,  959, 1126, 1126, 1126,
-     1126, 1126, 1126, 1126, 1131, 1131, 1131, 1131, 1131, 1131,
-     1131, 1710, 1712,  959,  986,  986,  986,  986,  986,  986,
-      986,  986,  986,  506,  503,  502,  501,  986,  500, 1710,
-     1712,  499,  986,  986,  986,  986,  986,  986,  986,  987,
-      987,  987,  987,  987,  987,  987,  987,  988,  988,  988,
-      988,  988,  988,  988,  988,  988, 1133, 1133, 1133, 1133,
-     1133, 1133, 1133, 1701, 1714,  988,  992,  992,  992,  992,
+      990,  990,  990,  508, 1191,  507,  990, 1628,  990, 1635,
+      506,  990,  990,  990,  990,  990,  990, 1117, 1117, 1117,
+     1117, 1117, 1117, 1117, 1121, 1121, 1121, 1121, 1121, 1121,
+     1121,  505, 1659,  990,  993,  993,  993,  993,  993,  993,
+      993,  993,  993,  504,  503,  501,  993,  498,  993, 1659,
+      497,  993,  993,  993,  993,  993,  993, 1126, 1126, 1126,
+     1126, 1126, 1126, 1126, 1128, 1128, 1128, 1128, 1128, 1128,
+     1128,  496, 1672,  993,  996,  996,  996,  996,  996,  996,
+      996,  996,  996,  495,  494,  493,  996,  492,  996, 1672,
+      490,  996,  996,  996,  996,  996,  996, 1132, 1132, 1132,
 
-      992,  992,  992,  992,  992,  498,  497,  495,  992,  494,
-      992, 1701, 1714,  493,  992,  992,  992,  992,  992,  992,
-     1137, 1137, 1137, 1137, 1137, 1137, 1137, 1143, 1143, 1143,
-     1143, 1143, 1143, 1143, 1706, 1701,  992,  995,  995,  995,
-      995,  995,  995,  995,  995,  995,  492,  491,  489,  995,
-      487,  995, 1706,  485,  484,  995,  995,  995,  995,  995,
-      995, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1149, 1149,
-     1149, 1149, 1149, 1149, 1149, 1719, 1706,  995,  998,  998,
-      998,  998,  998,  998,  998,  998,  998,  483,  482,  481,
-      998,  479,  998, 1719,  478,  476,  998,  998,  998,  998,
+     1132, 1132, 1132, 1132, 1138, 1138, 1138, 1138, 1138, 1138,
+     1138, 1192, 1225,  996, 1001, 1001, 1001, 1001, 1001, 1001,
+     1001, 1001,  489,  488,  487, 1001, 1225,  486, 1192,  484,
+     1001, 1001, 1001, 1001, 1001, 1001, 1002, 1002, 1002, 1002,
+     1002, 1002, 1002, 1002, 1002,  482, 1192,  480, 1002,  479,
+     1002, 1225,  478, 1002, 1002, 1002, 1002, 1002, 1002, 1140,
+     1140, 1140, 1140, 1140, 1140, 1140, 1144, 1144, 1144, 1144,
+     1144, 1144, 1144, 1230, 1193, 1002, 1007, 1007, 1007, 1007,
+     1007, 1007, 1007, 1007, 1007,  477,  476, 1230, 1007,  474,
+      473, 1193, 1603, 1007, 1007, 1007, 1007, 1007, 1007, 1009,
 
-      998,  998, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1157,
-     1157, 1157, 1157, 1157, 1157, 1157, 1721, 1724,  998, 1001,
-     1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001,  475,  474,
-      471, 1001,  467, 1001, 1721, 1724,  463, 1001, 1001, 1001,
-     1001, 1001, 1001, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
-     1168, 1168, 1168, 1168, 1168, 1168, 1168,  462,  461, 1001,
-     1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006,  458,  454,
-      453, 1006,  450,  449,  448, 1191, 1194, 1006, 1006, 1006,
-     1006, 1006, 1006, 1007, 1007, 1007, 1007, 1007, 1007, 1007,
-     1007, 1007, 1188, 1191, 1194, 1007, 1543, 1007, 1198, 1236,
+     1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1193, 1603,
+      471, 1009, 1230, 1009, 1603,  470, 1009, 1009, 1009, 1009,
+     1009, 1009, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1152,
+     1152, 1152, 1152, 1152, 1152, 1152, 1231, 1301, 1009, 1019,
+     1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019,  469,  466,
+     1231, 1019,  462,  458, 1301, 1301, 1019, 1019, 1019, 1019,
+     1019, 1019, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021,
+     1021,  457, 1301,  456, 1021, 1231, 1021,  453,  449, 1021,
+     1021, 1021, 1021, 1021, 1021, 1156, 1156, 1156, 1156, 1156,
+     1156, 1156, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1234,
 
-     1308, 1007, 1007, 1007, 1007, 1007, 1007, 1194, 1191,  447,
-     1188,  444,  443, 1236, 1543,  434, 1198, 1709, 1308,  431,
-      429, 1188,  428, 1007, 1012, 1012, 1012, 1012, 1012, 1012,
-     1012, 1012, 1012, 1198, 1543, 1709, 1012, 1308, 1709, 1236,
-     1195, 1199, 1012, 1012, 1012, 1012, 1012, 1012, 1014, 1014,
-     1014, 1014, 1014, 1014, 1014, 1014, 1014, 1193, 1195, 1199,
-     1014,  427, 1014,  426,  425, 1309, 1014, 1014, 1014, 1014,
-     1014, 1014, 1195, 1199,  424, 1193, 1223, 1223, 1223, 1223,
-     1223, 1223, 1223, 1309, 1239, 1311, 1193,  423, 1014, 1024,
-     1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1239,  422,
+     1303, 1021, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034,
+     1034,  448,  445, 1234, 1034,  444,  443, 1303, 1186, 1034,
+     1034, 1034, 1034, 1034, 1034, 1036, 1036, 1036, 1036, 1036,
+     1036, 1036, 1036, 1036, 1183, 1186, 1303, 1036, 1234, 1036,
+     1418, 1467, 1036, 1036, 1036, 1036, 1036, 1036, 1418, 1467,
+     1186, 1183, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1640,
+     1235, 1678, 1183, 1617, 1036, 1050, 1050, 1050, 1050, 1050,
+     1050, 1050, 1050, 1050, 1235,  442, 1640, 1050, 1678, 1640,
+     1617, 1190, 1050, 1050, 1050, 1050, 1050, 1050, 1052, 1052,
+     1052, 1052, 1052, 1052, 1052, 1052, 1052, 1188, 1190, 1235,
 
-     1309, 1024,  421, 1311,  420, 1203,  419, 1024, 1024, 1024,
-     1024, 1024, 1024, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
-     1026, 1026, 1311, 1203, 1239, 1026,  418, 1026, 1240,  417,
-      416, 1026, 1026, 1026, 1026, 1026, 1026, 1203,  414,  412,
-      411,  409, 1240, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
-      408, 1248, 1313, 1026, 1039, 1039, 1039, 1039, 1039, 1039,
-     1039, 1039, 1039,  405,  404, 1248, 1039,  402, 1240,  400,
-     1313,  399, 1039, 1039, 1039, 1039, 1039, 1039, 1041, 1041,
-     1041, 1041, 1041, 1041, 1041, 1041, 1041, 1313, 1249, 1252,
-     1041, 1248, 1041, 1253,  398,  393, 1041, 1041, 1041, 1041,
+     1052, 1617, 1052, 1527,  439, 1052, 1052, 1052, 1052, 1052,
+     1052, 1527, 1190,  438, 1188, 1241, 1241, 1241, 1241, 1241,
+     1241, 1241, 1405,  429, 1243, 1188, 1304, 1052, 1064, 1064,
+     1064, 1064, 1064, 1064, 1064, 1064, 1064,  426, 1243, 1405,
+     1064,  424,  423, 1304, 1244, 1064, 1064, 1064, 1064, 1064,
+     1064, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1244, 1405,
+     1304,  422, 1065, 1243,  421, 1629,  420, 1065, 1065, 1065,
+     1065, 1065, 1065, 1090, 1090, 1090, 1090, 1090, 1090, 1090,
+     1090, 1090, 1629, 1244,  419,  418, 1090, 1629,  417,  416,
+     1090, 1090, 1090, 1090, 1090, 1090, 1090, 1091, 1091, 1091,
 
-     1041, 1041, 1249, 1252,  392,  391,  389, 1253, 1260, 1260,
-     1260, 1260, 1260, 1260, 1260,  388, 1262, 1395, 1041, 1055,
-     1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1249, 1252,
-     1262, 1055,  387, 1253,  386, 1395,  384, 1055, 1055, 1055,
-     1055, 1055, 1055, 1057, 1057, 1057, 1057, 1057, 1057, 1057,
-     1057, 1057, 1395, 1263, 1266, 1057, 1262, 1057, 1267,  379,
-      378, 1057, 1057, 1057, 1057, 1057, 1057, 1263, 1266,  377,
-      374,  370, 1267, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
-      368, 1276, 1489, 1057, 1069, 1069, 1069, 1069, 1069, 1069,
-     1069, 1069, 1069, 1263, 1266, 1276, 1069,  363, 1267,  362,
+     1091, 1091, 1091, 1091, 1091, 1092, 1092, 1092, 1092, 1092,
+     1092, 1092, 1092, 1092,  415, 1642, 1247, 1248,  414, 1257,
+     1308, 1258, 1092, 1094, 1094, 1094, 1094, 1094, 1094, 1094,
+     1247, 1248, 1642, 1257, 1094, 1258, 1642, 1308,  413, 1094,
+     1094, 1094, 1094, 1094, 1094, 1095, 1095, 1095, 1095, 1095,
+     1095, 1095, 1095, 1095, 1308, 1247, 1248, 1095, 1257, 1630,
+     1258, 1261, 1095, 1095, 1095, 1095, 1095, 1095, 1096, 1096,
+     1096, 1096, 1096, 1096, 1096, 1261, 1630,  412,  411, 1096,
+      409, 1630, 1631,  407, 1096, 1096, 1096, 1096, 1096, 1096,
+     1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1631,
 
-     1489, 1277, 1069, 1069, 1069, 1069, 1069, 1069, 1070, 1070,
-     1070, 1070, 1070, 1070, 1070, 1277,  359, 1489,  354, 1070,
-      353, 1276, 1707,  345, 1713, 1070, 1070, 1070, 1070, 1070,
-     1070, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
-     1707, 1277, 1713,  343, 1095, 1707,  342, 1713,  337, 1095,
-     1095, 1095, 1095, 1095, 1095, 1095, 1096, 1096, 1096, 1096,
-     1096, 1096, 1096, 1096, 1097, 1097, 1097, 1097, 1097, 1097,
-     1097, 1097, 1097,  335, 1725, 1726, 1280, 1281, 1727, 1306,
-      333, 1337, 1097, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
-     1280, 1281, 1725, 1726, 1099, 1337, 1727, 1306, 1306,  332,
+     1261,  406, 1098,  404, 1631, 1633, 1262, 1098, 1098, 1098,
+     1098, 1098, 1098, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
+     1262,  403, 1633,  400, 1099,  399,  397, 1633,  395, 1099,
+     1099, 1099, 1099, 1099, 1099, 1101, 1101, 1101, 1101, 1101,
+     1101, 1101, 1101, 1101,  394, 1262,  393, 1101,  388, 1644,
+     1647, 1271, 1101, 1101, 1101, 1101, 1101, 1101, 1102, 1102,
+     1102, 1102, 1102, 1102, 1102, 1271, 1644, 1647,  387, 1102,
+      386, 1644, 1618,  384, 1102, 1102, 1102, 1102, 1102, 1102,
+     1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1618,
+     1271, 1647, 1104,  383, 1646, 1648, 1689, 1104, 1104, 1104,
 
-     1099, 1099, 1099, 1099, 1099, 1099, 1100, 1100, 1100, 1100,
-     1100, 1100, 1100, 1100, 1100, 1306, 1280, 1281, 1100,  331,
-      330, 1337,  329, 1338, 1100, 1100, 1100, 1100, 1100, 1100,
-     1101, 1101, 1101, 1101, 1101, 1101, 1101, 1338,  328,  327,
-      325, 1101,  324,  323,  318,  315, 1687, 1101, 1101, 1101,
-     1101, 1101, 1101, 1103, 1103, 1103, 1103, 1103, 1103, 1103,
-     1103, 1103,  314, 1338, 1687, 1103,  313,  310,  303,  302,
-     1385, 1103, 1103, 1103, 1103, 1103, 1103, 1104, 1104, 1104,
-     1104, 1104, 1104, 1104, 1385, 1687,  300,  299, 1104,  298,
-      296,  294,  293, 1718, 1104, 1104, 1104, 1104, 1104, 1104,
+     1104, 1104, 1104, 1105, 1105, 1105, 1105, 1105, 1105, 1105,
+     1618, 1646, 1648, 1689, 1105,  382, 1646, 1194, 1198, 1105,
+     1105, 1105, 1105, 1105, 1105, 1108, 1108, 1108, 1108, 1108,
+     1108, 1108, 1108, 1108, 1194, 1198, 1648, 1108,  381, 1108,
+      379,  374, 1108, 1108, 1108, 1108, 1108, 1108, 1194, 1198,
+     1255, 1255, 1255, 1255, 1255, 1255, 1255, 1269, 1269, 1269,
+     1269, 1269, 1269, 1269, 1108, 1113, 1113, 1113, 1113, 1113,
+     1113, 1113, 1113, 1113,  373,  372,  369, 1113,  365,  363,
+     1655, 1663, 1113, 1113, 1113, 1113, 1113, 1113, 1122, 1122,
+     1122, 1122, 1122, 1122, 1122, 1122, 1122, 1655, 1663,  358,
 
-     1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106,  292,
-     1385, 1718, 1106,  290,  286,  285,  283, 1386, 1106, 1106,
-     1106, 1106, 1106, 1106, 1107, 1107, 1107, 1107, 1107, 1107,
-     1107, 1386, 1718,  280,  276, 1107,  275,  272,  271,  269,
-      264, 1107, 1107, 1107, 1107, 1107, 1107, 1109, 1109, 1109,
-     1109, 1109, 1109, 1109, 1109, 1109,  261, 1386,  259, 1109,
-      258,  256,  253,  249, 1389, 1109, 1109, 1109, 1109, 1109,
-     1109, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1389,  245,
-      243,  241, 1110,  240,  238,  237,  236,  235, 1110, 1110,
-     1110, 1110, 1110, 1110, 1113, 1113, 1113, 1113, 1113, 1113,
+     1122,  357, 1655, 1663, 1664, 1122, 1122, 1122, 1122, 1122,
+     1122, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133,
+      354, 1664,  349, 1133,  348,  340, 1664, 1669, 1133, 1133,
+     1133, 1133, 1133, 1133, 1145, 1145, 1145, 1145, 1145, 1145,
+     1145, 1145, 1145,  338, 1669,  337, 1145,  332,  330, 1669,
+     1670, 1145, 1145, 1145, 1145, 1145, 1145, 1157, 1157, 1157,
+     1157, 1157, 1157, 1157, 1157, 1157,  328, 1670,  327, 1157,
+      326, 1670, 1674, 1677, 1157, 1157, 1157, 1157, 1157, 1157,
+     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1674,
+     1677,  325, 1171, 1677, 1674,  324,  323, 1171, 1171, 1171,
 
-     1113, 1113, 1113,  234, 1389,  233, 1113,  232, 1113,  230,
-      228,  226, 1113, 1113, 1113, 1113, 1113, 1113, 1287, 1287,
-     1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1289, 1289,
-     1289, 1289, 1312,  225, 1113, 1118, 1118, 1118, 1118, 1118,
-     1118, 1118, 1118, 1118,  223,  221,  220, 1118,  218,  215,
-     1312, 1312,  214, 1118, 1118, 1118, 1118, 1118, 1118, 1127,
-     1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1312,  213,
-      211, 1127,  209,  208,  205,  204,  202, 1127, 1127, 1127,
-     1127, 1127, 1127, 1138, 1138, 1138, 1138, 1138, 1138, 1138,
-     1138, 1138,  201,  200,  199, 1138,  198,  197,  196,  195,
+     1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173, 1173, 1173,
+     1173, 1173, 1298, 1272, 1275, 1173, 1276, 1173,  322,  320,
+     1173, 1173, 1173, 1173, 1173, 1173,  319, 1272, 1275, 1298,
+     1276, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1298, 1299,
+     1306, 1311, 1173, 1199, 1199, 1199, 1199, 1199, 1199, 1199,
+     1199, 1199, 1272, 1275,  318, 1276, 1299, 1306, 1311, 1332,
+     1199, 1201, 1201, 1201, 1201, 1201, 1201, 1201, 1201, 1299,
+      313, 1311, 1201, 1332,  310, 1695, 1306, 1201, 1201, 1201,
+     1201, 1201, 1201, 1202, 1202, 1202, 1202, 1202, 1202, 1202,
+     1202, 1202, 1695,  309,  308, 1202,  305, 1202, 1332,  298,
 
-      194, 1138, 1138, 1138, 1138, 1138, 1138, 1150, 1150, 1150,
-     1150, 1150, 1150, 1150, 1150, 1150,  193,  192,  191, 1150,
-      190,  189,  188,  187,  186, 1150, 1150, 1150, 1150, 1150,
-     1150, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
-      185,  183,  182, 1162,  179,  178,  177,  176,  175, 1162,
-     1162, 1162, 1162, 1162, 1162, 1176, 1176, 1176, 1176, 1176,
-     1176, 1176, 1176, 1176,  174,  173,  172, 1176,  170,  167,
-      166,  165,  164, 1176, 1176, 1176, 1176, 1176, 1176, 1178,
-     1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178,  161,  159,
-      150, 1178,  149, 1178, 1475, 1535, 1390, 1178, 1178, 1178,
+     1202, 1202, 1202, 1202, 1202, 1202, 1284, 1284, 1284, 1284,
+     1284, 1284, 1284, 1288, 1288, 1288, 1288, 1288, 1288, 1288,
+     1333, 1300, 1202, 1205, 1205, 1205, 1205, 1205, 1205, 1205,
+     1205, 1205,  297, 1312, 1333, 1205, 1470, 1205, 1300, 1307,
+     1205, 1205, 1205, 1205, 1205, 1205,  295,  294,  293, 1300,
+     1312,  291,  289, 1470,  288,  287, 1307, 1307,  285, 1333,
+      281, 1312, 1205, 1208, 1208, 1208, 1208, 1208, 1208, 1208,
+     1208, 1208, 1470,  280, 1307, 1208,  278, 1208,  275,  271,
+     1208, 1208, 1208, 1208, 1208, 1208, 1340, 1340, 1340, 1340,
+     1340, 1340, 1340, 1345, 1345, 1345, 1345, 1345, 1345, 1345,
 
-     1178, 1178, 1178, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
-     1390, 1650, 1475, 1535,  148, 1546, 1304, 1316,  147, 1178,
-     1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1650,
-      146, 1475, 1535, 1546, 1304, 1316, 1390, 1427, 1204, 1206,
-     1206, 1206, 1206, 1206, 1206, 1206, 1206, 1304, 1316, 1650,
-     1206, 1427, 1546,  145,  144, 1400, 1206, 1206, 1206, 1206,
-     1206, 1206, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207,
-     1207, 1305, 1317, 1400, 1207,  142, 1207, 1427,  140,  139,
-     1207, 1207, 1207, 1207, 1207, 1207,  137, 1400,  135, 1305,
-     1317, 1345, 1345, 1345, 1345, 1345, 1345, 1345,  133,  132,
+      270, 1698, 1208, 1211, 1211, 1211, 1211, 1211, 1211, 1211,
+     1211, 1211,  267,  266,  264, 1211,  259, 1211, 1698,  256,
+     1211, 1211, 1211, 1211, 1211, 1211, 1347, 1347, 1347, 1347,
+     1347, 1347, 1347, 1353, 1353, 1353, 1353, 1353, 1353, 1353,
+      254, 1705, 1211, 1214, 1214, 1214, 1214, 1214, 1214, 1214,
+     1214, 1214,  253,  251,  248, 1214,  244, 1214, 1705,  240,
+     1214, 1214, 1214, 1214, 1214, 1214, 1355, 1355, 1355, 1355,
+     1355, 1355, 1355, 1361, 1361, 1361, 1361, 1361, 1361, 1361,
+     1380, 1390, 1214, 1219, 1219, 1219, 1219, 1219, 1219, 1219,
+     1219, 1219,  238,  236, 1380, 1219,  235,  233, 1390, 1679,
 
-     1305, 1317, 1207, 1210, 1210, 1210, 1210, 1210, 1210, 1210,
-     1210, 1210,  131,  130,  128, 1210,  127, 1210,  126,  125,
-      124, 1210, 1210, 1210, 1210, 1210, 1210, 1350, 1350, 1350,
-     1350, 1350, 1350, 1350, 1352, 1352, 1352, 1352, 1352, 1352,
-     1352,  123,  121, 1210, 1213, 1213, 1213, 1213, 1213, 1213,
-     1213, 1213, 1213,  119,  118,  117, 1213,  116, 1213,  115,
-      114,  113, 1213, 1213, 1213, 1213, 1213, 1213, 1358, 1358,
-     1358, 1358, 1358, 1358, 1358, 1360, 1360, 1360, 1360, 1360,
-     1360, 1360,  112,  111, 1213, 1216, 1216, 1216, 1216, 1216,
-     1216, 1216, 1216, 1216,  109,  108,  101, 1216,  100, 1216,
+     1219, 1219, 1219, 1219, 1219, 1219, 1226, 1226, 1226, 1226,
+     1226, 1226, 1226, 1226, 1226, 1390, 1679,  232, 1226, 1380,
+      231, 1684, 1693, 1226, 1226, 1226, 1226, 1226, 1226, 1236,
+     1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1684, 1693,
+     1679, 1236,  230, 1684, 1693, 1696, 1236, 1236, 1236, 1236,
+     1236, 1236, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249,
+     1249,  229, 1696,  228, 1249,  227,  225, 1701, 1702, 1249,
+     1249, 1249, 1249, 1249, 1249, 1263, 1263, 1263, 1263, 1263,
+     1263, 1263, 1263, 1263, 1701, 1702, 1696, 1263,  223,  221,
+     1702,  220, 1263, 1263, 1263, 1263, 1263, 1263, 1277, 1277,
 
-       99,   97,   96, 1216, 1216, 1216, 1216, 1216, 1216, 1366,
-     1366, 1366, 1366, 1366, 1366, 1366, 1368, 1368, 1368, 1368,
-     1368, 1368, 1368,   93,   92, 1216, 1219, 1219, 1219, 1219,
-     1219, 1219, 1219, 1219, 1219,   91,   90,   89, 1219,   88,
-     1219,   87,   86,   85, 1219, 1219, 1219, 1219, 1219, 1219,
-     1374, 1374, 1374, 1374, 1374, 1374, 1374, 1376, 1376, 1376,
-     1376, 1376, 1376, 1376, 1428, 1539, 1219, 1224, 1224, 1224,
-     1224, 1224, 1224, 1224, 1224, 1224,   84,   82, 1428, 1224,
-       81,   80,   79, 1539,   78, 1224, 1224, 1224, 1224, 1224,
-     1224, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231,
+     1277, 1277, 1277, 1277, 1277, 1277, 1277,  218, 1701,  216,
+     1277,  215,  213, 1707, 1704, 1277, 1277, 1277, 1277, 1277,
+     1277, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289,
+     1707, 1704,  210, 1289, 1704,  209, 1709, 1708, 1289, 1289,
+     1289, 1289, 1289, 1289, 1313, 1313, 1313, 1313, 1313, 1313,
+     1313, 1313, 1313, 1709, 1708,  208, 1313,  206, 1313, 1708,
+      204, 1313, 1313, 1313, 1313, 1313, 1313, 1363, 1363, 1363,
+     1363, 1363, 1363, 1363, 1369, 1369, 1369, 1369, 1369, 1369,
+     1369, 1381, 1484, 1313, 1317, 1317, 1317, 1317, 1317, 1317,
+     1317, 1317, 1317,  203,  200, 1381, 1317,  199,  197, 1484,
 
-       77, 1539,   76, 1231, 1428,   75,   74,   73,   72, 1231,
-     1231, 1231, 1231, 1231, 1231, 1241, 1241, 1241, 1241, 1241,
-     1241, 1241, 1241, 1241,   71,   70,   69, 1241,   67,   66,
-       65,   51,   43, 1241, 1241, 1241, 1241, 1241, 1241, 1254,
-     1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,   42,   40,
-       18, 1254,   11,    8,    3,    0,    0, 1254, 1254, 1254,
-     1254, 1254, 1254, 1268, 1268, 1268, 1268, 1268, 1268, 1268,
-     1268, 1268,    0,    0,    0, 1268,    0,    0,    0,    0,
-        0, 1268, 1268, 1268, 1268, 1268, 1268, 1282, 1282, 1282,
-     1282, 1282, 1282, 1282, 1282, 1282,    0,    0,    0, 1282,
+     1714, 1317, 1317, 1317, 1317, 1317, 1317, 1320, 1320, 1320,
+     1320, 1320, 1320, 1320, 1320, 1320, 1484, 1714,  196, 1320,
+     1381,  195, 1716, 1719, 1320, 1320, 1320, 1320, 1320, 1320,
+     1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1323, 1716,
+     1719,  194, 1323,  193,  192, 1720, 1721, 1323, 1323, 1323,
+     1323, 1323, 1323, 1326, 1326, 1326, 1326, 1326, 1326, 1326,
+     1326, 1326, 1720, 1721,  191, 1326,  190,  189, 1722,  188,
+     1326, 1326, 1326, 1326, 1326, 1326, 1329, 1329, 1329, 1329,
+     1329, 1329, 1329, 1329, 1329, 1722,  187,  186, 1329,  185,
+      184,  183,  182, 1329, 1329, 1329, 1329, 1329, 1329, 1334,
 
-        0,    0,    0,    0,    0, 1282, 1282, 1282, 1282, 1282,
-     1282, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
-        0,    0,    0, 1294,    0,    0,    0,    0,    0, 1294,
-     1294, 1294, 1294, 1294, 1294, 1318, 1318, 1318, 1318, 1318,
-     1318, 1318, 1318, 1318,    0,    0,    0, 1318,    0, 1318,
-        0,    0,    0, 1318, 1318, 1318, 1318, 1318, 1318, 1383,
-     1383, 1383, 1383, 1383, 1383, 1383, 1421, 1421, 1421, 1421,
-     1421, 1421, 1421, 1435, 1540, 1318, 1322, 1322, 1322, 1322,
-     1322, 1322, 1322, 1322, 1322,    0,    0, 1435, 1322,    0,
-        0,    0, 1540,    0, 1322, 1322, 1322, 1322, 1322, 1322,
+     1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334,  181,  180,
+      178, 1334,  177,  174,  173,  172, 1334, 1334, 1334, 1334,
+     1334, 1334, 1371, 1371, 1371, 1371, 1371, 1371, 1371, 1378,
+     1378, 1378, 1378, 1378, 1378, 1378, 1384, 1385, 1395, 1400,
+     1402, 1403, 1406, 1416, 1416, 1416, 1416, 1416, 1416, 1416,
+     1384, 1385, 1422,  171,  170, 1395, 1400, 1402, 1403, 1406,
+      169,  168,  167,  165,  162,  161, 1422, 1400, 1406, 1395,
+     1403, 1402, 1423, 1400, 1430, 1384, 1385, 1386, 1386, 1386,
+     1386, 1386, 1386, 1386, 1386, 1386, 1423,  160, 1430, 1386,
+      159, 1422,  156,  154, 1386, 1386, 1386, 1386, 1386, 1386,
 
-     1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325,    0,
-     1540,    0, 1325, 1435,    0,    0,    0,    0, 1325, 1325,
-     1325, 1325, 1325, 1325, 1328, 1328, 1328, 1328, 1328, 1328,
-     1328, 1328, 1328,    0,    0,    0, 1328,    0,    0,    0,
-        0,    0, 1328, 1328, 1328, 1328, 1328, 1328, 1331, 1331,
-     1331, 1331, 1331, 1331, 1331, 1331, 1331,    0,    0,    0,
-     1331,    0,    0,    0,    0,    0, 1331, 1331, 1331, 1331,
-     1331, 1331, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334,
-     1334,    0,    0,    0, 1334,    0,    0,    0,    0,    0,
-     1334, 1334, 1334, 1334, 1334, 1334, 1339, 1339, 1339, 1339,
+     1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407,  145,
+      144, 1423, 1407, 1430,  143,  142, 1431, 1407, 1407, 1407,
+     1407, 1407, 1407, 1428, 1428, 1428, 1428, 1428, 1428, 1428,
+     1431, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1439, 1440,
+     1446, 1446, 1446, 1446, 1446, 1446, 1446, 1448, 1449,  141,
+      140,  139, 1439, 1440,  137, 1431, 1457, 1458,  135,  134,
+      132, 1448, 1449, 1455, 1455, 1455, 1455, 1455, 1455, 1455,
+     1457, 1458,  130,  128,  127,  126,  125, 1439, 1440, 1463,
+     1463, 1463, 1463, 1463, 1463, 1463, 1448, 1449, 1465, 1465,
+     1465, 1465, 1465, 1465, 1465, 1457, 1458, 1471, 1475, 1472,
 
-     1339, 1339, 1339, 1339, 1339,    0,    0,    0, 1339,    0,
-        0,    0, 1407,    0, 1339, 1339, 1339, 1339, 1339, 1339,
-     1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1405,
-     1407, 1408, 1391,    0, 1436,    0,    0,    0, 1391, 1391,
-     1391, 1391, 1391, 1391, 1407, 1490,    0, 1405, 1436, 1408,
-     1433, 1433, 1433, 1433, 1433, 1433, 1433,    0, 1405,    0,
-        0, 1408, 1444, 1490, 1405, 1412, 1412, 1412, 1412, 1412,
-     1412, 1412, 1412, 1412, 1436, 1490, 1444, 1412,    0,    0,
-        0,    0, 1445, 1412, 1412, 1412, 1412, 1412, 1412, 1442,
-     1442, 1442, 1442, 1442, 1442, 1442, 1445, 1453, 1454,    0,
+     1480, 1476, 1477, 1478, 1479, 1482,  123,  122, 1485,  121,
+      120,  119,  118,  116, 1471, 1475, 1472, 1480, 1476, 1477,
+     1478, 1479, 1482, 1471, 1472, 1485, 1475, 1476, 1477, 1478,
+     1479, 1480, 1495, 1482, 1496,  114,  113, 1485, 1501, 1501,
+     1501, 1501, 1501, 1501, 1501,  112, 1495,  111, 1496, 1505,
+     1505, 1505, 1505, 1505, 1505, 1505, 1509, 1509, 1509, 1509,
+     1509, 1509, 1509, 1513, 1513, 1513, 1513, 1513, 1513, 1513,
+      110, 1495,  109, 1496, 1517, 1517, 1517, 1517, 1517, 1517,
+     1517, 1522, 1522, 1522, 1522, 1522, 1522, 1522, 1524, 1525,
+     1530, 1533, 1540, 1544, 1534, 1535, 1537, 1538, 1572, 1541,
 
-        0,    0, 1444, 1451, 1451, 1451, 1451, 1451, 1451, 1451,
-     1462, 1453, 1454, 1460, 1460, 1460, 1460, 1460, 1460, 1460,
-     1463,    0, 1445,    0, 1462, 1468, 1468, 1468, 1468, 1468,
-     1468, 1468,    0, 1480, 1463, 1485, 1481, 1453, 1454, 1470,
-     1470, 1470, 1470, 1470, 1470, 1470, 1482, 1483, 1484,    0,
-     1462, 1480, 1487, 1485, 1481, 1500,    0, 1501, 1542, 1547,
-     1463, 1603, 1480, 1481, 1482, 1483, 1484, 1485,    0, 1500,
-     1487, 1501,    0, 1482, 1483, 1484, 1542, 1547,    0, 1603,
-        0, 1487, 1506, 1506, 1506, 1506, 1506, 1506, 1506,    0,
-        0,    0,    0, 1603, 1542, 1500, 1547, 1501, 1510, 1510,
+      108,  107, 1524, 1525, 1542, 1579, 1598, 1530, 1533, 1540,
+     1544, 1534, 1535, 1537, 1538, 1572, 1541, 1533, 1540, 1544,
+      106, 1542, 1579, 1598,  104,  103, 1530, 1524, 1525, 1534,
+     1535, 1537, 1572,   96, 1538, 1541,   95, 1598,   94, 1579,
+     1542, 1546, 1546, 1546, 1546, 1546, 1546, 1546, 1549, 1549,
+     1549, 1549, 1549, 1549, 1549, 1553, 1553, 1553, 1553, 1553,
+     1553, 1553, 1557, 1557, 1557, 1557, 1557, 1557, 1557, 1561,
+     1561, 1561, 1561, 1561, 1561, 1561, 1565, 1565, 1565, 1565,
+     1565, 1565, 1565, 1568, 1568, 1568, 1568, 1568, 1568, 1568,
+     1576,   92, 1577, 1578, 1581, 1583, 1585, 1585, 1585, 1585,
 
-     1510, 1510, 1510, 1510, 1510, 1514, 1514, 1514, 1514, 1514,
-     1514, 1514, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1522,
-     1522, 1522, 1522, 1522, 1522, 1522, 1527, 1527, 1527, 1527,
-     1527, 1527, 1527, 1529, 1530, 1538, 1545, 1549, 1551, 1551,
-     1551, 1551, 1551, 1551, 1551,    0,    0, 1529, 1530,    0,
-        0,    0,    0, 1538, 1545, 1549,    0,    0,    0,    0,
-        0,    0, 1538, 1545, 1549, 1554, 1554, 1554, 1554, 1554,
-     1554, 1554,    0, 1529, 1530, 1558, 1558, 1558, 1558, 1558,
-     1558, 1558, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1566,
-     1566, 1566, 1566, 1566, 1566, 1566, 1570, 1570, 1570, 1570,
+     1585, 1585, 1585,   91, 1596, 1599, 1597, 1576, 1576, 1577,
+     1578, 1581, 1583, 1594, 1594, 1594, 1594, 1594, 1594, 1594,
+     1581, 1596, 1599, 1597, 1601, 1576, 1604, 1605, 1577, 1578,
+     1606, 1583, 1597, 1616, 1619, 1620, 1599, 1621,   88, 1622,
+     1596, 1601, 1624, 1604, 1605,   87,   86, 1606, 1632, 1625,
+     1616, 1619, 1620, 1605, 1621, 1601, 1622,   85, 1634, 1624,
+     1643, 1606, 1604, 1620, 1636, 1632, 1625, 1621, 1637, 1616,
+     1638, 1639, 1619, 1622, 1632, 1634, 1634, 1643, 1624, 1625,
+       84, 1636, 1641, 1645, 1650, 1637, 1649, 1638, 1639, 1652,
+     1651, 1643, 1654, 1634, 1634, 1656,   83, 1636, 1636, 1641,
 
-     1570, 1570, 1570, 1573, 1573, 1573, 1573, 1573, 1573, 1573,
-     1577, 1581,    0, 1582, 1583, 1586, 1588, 1584, 1590, 1590,
-     1590, 1590, 1590, 1590, 1590, 1601, 1609,    0, 1577, 1581,
-     1581, 1582, 1583, 1586, 1588, 1584,    0,    0,    0,    0,
-        0,    0, 1586, 1601, 1609, 1577, 1602, 1581, 1604, 1606,
-     1582, 1583, 1584, 1588, 1599, 1599, 1599, 1599, 1599, 1599,
-     1599, 1610, 1601, 1609, 1602, 1611, 1604, 1606, 1621, 1625,
-        0, 1626, 1627, 1602, 1629, 1630, 1637, 1639,    0, 1610,
-     1604, 1606, 1641, 1611,    0,    0, 1621, 1625, 1610, 1626,
-     1627, 1642, 1629, 1630, 1637, 1639, 1639, 1611, 1625,    0,
+     1645, 1650, 1637, 1649, 1638, 1639, 1652, 1651, 1653, 1654,
+     1650, 1651, 1656,   82, 1657, 1658, 1641, 1660, 1661,   81,
+     1645, 1662, 1649, 1651, 1651, 1653, 1654, 1652, 1665, 1667,
+     1656, 1657, 1658, 1658, 1660, 1661, 1653,   80, 1662, 1666,
+     1668,   79, 1671, 1675, 1673, 1665, 1667, 1676, 1657, 1661,
+     1658,   77, 1680, 1660, 1665,   76, 1666, 1668, 1662, 1671,
+     1675, 1673, 1681, 1667, 1676, 1682,   75, 1685, 1666, 1680,
+     1683, 1686, 1668, 1671, 1673, 1675, 1687,   74,   73, 1681,
+     1688, 1676, 1682, 1680, 1685,   72,   71, 1683, 1686,   70,
+     1690, 1691, 1692, 1687, 1681, 1681, 1694, 1688, 1683, 1697,
 
-     1641, 1643, 1626, 1637, 1644, 1621, 1630, 1627,    0, 1642,
-     1646, 1629, 1648, 1639, 1639, 1654, 1641, 1641,    0, 1643,
-     1655,    0, 1644, 1665, 1656, 1658, 1642,    0, 1646,    0,
-     1648, 1659, 1661, 1654,    0, 1662, 1643, 1663, 1655, 1644,
-        0, 1665, 1656, 1658, 1648, 1646, 1656, 1655,    0, 1659,
-     1661, 1666, 1654, 1662, 1658, 1663, 1663, 1667, 1656, 1656,
-     1665, 1670, 1671, 1672, 1673,    0, 1659, 1676, 1661, 1666,
-     1662, 1678, 1680, 1663,    0, 1667, 1681,    0, 1685, 1670,
-     1671, 1672, 1673, 1666,    0, 1676, 1686,    0, 1670, 1678,
-     1680, 1690, 1671,    0, 1681, 1667, 1685, 1673, 1672, 1676,
+     1699, 1685, 1686, 1682, 1700,   69, 1688, 1690, 1691, 1692,
+     1703, 1706, 1687, 1694, 1710, 1711, 1697, 1699, 1713, 1691,
+     1690, 1700, 1694, 1715, 1712, 1717,   68, 1703, 1706, 1692,
+       67, 1710, 1711, 1697,   66, 1713, 1699,   65,   64, 1700,
+     1715, 1712, 1717,   62, 1703,   61,   60, 1706,   47, 1710,
+     1712, 1711,   40,   39, 1718,   37, 1713, 1718, 1718, 1715,
+       15, 1717,   13,   10,    7,    3,    0,    0,    0,    0,
+        0, 1718, 1724,    0, 1724, 1725,    0, 1725, 1725, 1725,
+     1725, 1725, 1725, 1726,    0, 1726, 1727, 1727, 1727, 1728,
+     1728, 1728, 1729, 1729, 1729, 1730, 1730, 1730, 1731, 1731,
 
-     1688,    0, 1678, 1691, 1686, 1680, 1692, 1693,    0, 1690,
-     1685, 1681, 1696, 1695, 1697, 1699,    0,    0, 1688, 1686,
-     1686, 1691, 1702,    0, 1692, 1693, 1690, 1704, 1708, 1688,
-     1696, 1695, 1697, 1699, 1693, 1691, 1705, 1711, 1716,    0,
-     1702, 1696, 1699, 1692, 1695, 1704, 1708, 1715, 1720, 1717,
-     1722,    0, 1697,    0, 1705, 1711, 1716, 1702,    0,    0,
-        0,    0,    0, 1708, 1704, 1715, 1720, 1717, 1722,    0,
-        0,    0, 1705,    0, 1711, 1716, 1717, 1723,    0,    0,
-     1723, 1723,    0, 1715,    0, 1720,    0, 1722,    0,    0,
-        0,    0,    0,    0,    0, 1723, 1729,    0,    0,    0,
+     1731, 1732, 1732, 1732, 1733, 1733, 1733, 1734, 1734, 1734,
+     1735, 1735, 1735, 1736,    0, 1736, 1737, 1737, 1737, 1738,
+     1738, 1738, 1739, 1739, 1739, 1740, 1740, 1740, 1741,    0,
+     1741, 1742, 1742, 1742, 1743, 1743,    0,    0, 1743, 1744,
+     1744, 1744, 1745, 1745, 1745, 1746, 1746, 1746, 1747, 1747,
+     1747, 1748, 1748, 1748, 1749, 1749, 1749, 1750, 1750, 1750,
+     1751, 1751, 1751, 1752, 1752, 1752, 1753, 1753,    0,    0,
+     1753, 1754, 1754, 1754, 1755, 1755, 1755, 1756,    0, 1756,
+     1757, 1757, 1757, 1758, 1758, 1758, 1759,    0, 1759, 1760,
+     1760, 1760, 1761, 1761, 1761, 1762, 1762, 1762, 1763, 1763,
 
-        0, 1729, 1729, 1729, 1730,    0, 1730, 1730, 1730, 1730,
-     1730, 1730, 1730, 1731,    0, 1731, 1732, 1732, 1732, 1733,
-     1733, 1733, 1734, 1734, 1734, 1735, 1735, 1735, 1736, 1736,
-     1736, 1737, 1737, 1737, 1738, 1738, 1738, 1739, 1739, 1739,
-     1740, 1740, 1740, 1741,    0, 1741, 1742, 1742, 1742, 1743,
-     1743, 1743, 1744, 1744, 1744, 1745, 1745, 1745, 1746,    0,
-     1746, 1747, 1747, 1747, 1748, 1748,    0,    0, 1748, 1749,
-     1749, 1749, 1750, 1750, 1750, 1751, 1751, 1751, 1752, 1752,
-     1752, 1753, 1753, 1753, 1754, 1754, 1754, 1755, 1755, 1755,
-     1756, 1756, 1756, 1757, 1757, 1757, 1758, 1758,    0,    0,
+     1763, 1764, 1764, 1764, 1765,    0, 1765, 1766,    0, 1766,
+     1767, 1767, 1767, 1768, 1768, 1768, 1769,    0, 1769, 1770,
+     1770,    0,    0, 1770, 1771, 1771,    0,    0, 1771, 1772,
+     1772, 1772, 1773, 1773, 1773, 1774, 1774,    0, 1774, 1775,
+     1775, 1775, 1776, 1776, 1776, 1777, 1777, 1777, 1778, 1778,
+     1778, 1779, 1779, 1779, 1780, 1780, 1780, 1781, 1781, 1781,
+     1782, 1782,    0,    0, 1782, 1783, 1783, 1783, 1784, 1784,
+     1784, 1785, 1785,    0, 1785, 1786, 1786,    0,    0, 1786,
+     1787, 1787,    0, 1787, 1788, 1788, 1789, 1789,    0,    0,
+     1789, 1790, 1790, 1790, 1791, 1791, 1791, 1792, 1792,    0,
 
-     1758, 1759, 1759, 1759, 1760, 1760, 1760, 1761,    0, 1761,
-     1762, 1762, 1762, 1763, 1763, 1763, 1764,    0, 1764, 1765,
-     1765, 1765, 1766, 1766, 1766, 1767, 1767, 1767, 1768, 1768,
-     1768, 1769, 1769, 1769, 1770,    0, 1770, 1771,    0, 1771,
-     1772, 1772, 1772, 1773, 1773, 1773, 1774,    0, 1774, 1775,
-     1775,    0,    0, 1775, 1776, 1776,    0,    0, 1776, 1777,
-     1777, 1777, 1778, 1778, 1778, 1779, 1779,    0, 1779, 1780,
-     1780, 1780, 1781, 1781, 1781, 1782, 1782, 1782, 1783, 1783,
-     1783, 1784, 1784, 1784, 1785, 1785, 1785, 1786, 1786, 1786,
-     1787, 1787,    0,    0, 1787, 1788, 1788, 1788, 1789, 1789,
+     1792, 1793,    0, 1793, 1794,    0, 1794, 1795, 1795, 1795,
+     1796, 1796, 1796, 1797,    0, 1797, 1798, 1798, 1798, 1799,
+     1799, 1799, 1800, 1800, 1800, 1801, 1801, 1801, 1802, 1802,
+     1802, 1803, 1803, 1803, 1804,    0, 1804, 1805,    0, 1805,
+     1806, 1806, 1806, 1807, 1807, 1807, 1808,    0, 1808, 1809,
+        0, 1809, 1810,    0, 1810, 1811, 1811, 1811, 1812, 1812,
+     1812, 1813,    0, 1813, 1814,    0,    0, 1814, 1815, 1815,
+        0, 1815, 1816, 1816,    0,    0, 1816, 1817, 1817,    0,
+     1817, 1818, 1818, 1819, 1819,    0,    0, 1819, 1820, 1820,
+     1820, 1821, 1821, 1821, 1822, 1822,    0, 1822, 1823, 1823,
 
-     1789, 1790, 1790,    0, 1790, 1791, 1791,    0,    0, 1791,
-     1792, 1792,    0, 1792, 1793, 1793, 1794, 1794,    0,    0,
-     1794, 1795, 1795, 1795, 1796, 1796, 1796, 1797, 1797,    0,
-     1797, 1798,    0, 1798, 1799,    0, 1799, 1800, 1800, 1800,
-     1801, 1801, 1801, 1802,    0, 1802, 1803, 1803, 1803, 1804,
-     1804, 1804, 1805, 1805, 1805, 1806, 1806, 1806, 1807, 1807,
-     1807, 1808, 1808, 1808, 1809,    0, 1809, 1810,    0, 1810,
-     1811, 1811, 1811, 1812, 1812, 1812, 1813,    0, 1813, 1814,
-        0, 1814, 1815,    0, 1815, 1816, 1816, 1816, 1817, 1817,
-     1817, 1818,    0, 1818, 1819,    0,    0, 1819, 1820, 1820,
+     1823,    0, 1823, 1823, 1824, 1824, 1824, 1825, 1825, 1825,
+     1826, 1826, 1826, 1827, 1827, 1827, 1828, 1828, 1828, 1829,
+     1829, 1829, 1830, 1830, 1830, 1831, 1831, 1831, 1832, 1832,
+        0,    0, 1832, 1833, 1833, 1833, 1834, 1834, 1834, 1835,
+     1835,    0, 1835, 1836, 1836,    0,    0, 1836, 1837, 1837,
+        0, 1837, 1838, 1838, 1839, 1839,    0,    0, 1839, 1840,
+     1840, 1840, 1841, 1841, 1841, 1842, 1842,    0, 1842, 1843,
+        0,    0, 1843, 1844, 1844,    0, 1844, 1845, 1845,    0,
+        0, 1845, 1846, 1846,    0, 1846, 1847, 1847, 1848, 1848,
+        0,    0, 1848, 1849, 1849, 1849, 1850, 1850, 1850, 1851,
 
-        0, 1820, 1821, 1821,    0,    0, 1821, 1822, 1822,    0,
-     1822, 1823, 1823, 1824, 1824,    0,    0, 1824, 1825, 1825,
-     1825, 1826, 1826, 1826, 1827, 1827,    0, 1827, 1828, 1828,
-     1828,    0, 1828, 1828, 1829, 1829, 1829, 1830, 1830, 1830,
-     1831, 1831, 1831, 1832, 1832, 1832, 1833, 1833, 1833, 1834,
-     1834, 1834, 1835, 1835, 1835, 1836, 1836, 1836, 1837, 1837,
-        0,    0, 1837, 1838, 1838, 1838, 1839, 1839, 1839, 1840,
-     1840,    0, 1840, 1841, 1841,    0,    0, 1841, 1842, 1842,
-        0, 1842, 1843, 1843, 1844, 1844,    0,    0, 1844, 1845,
-     1845, 1845, 1846, 1846, 1846, 1847, 1847,    0, 1847, 1848,
+     1851,    0, 1851, 1852,    0, 1852, 1853,    0, 1853, 1854,
+        0, 1854, 1855, 1855, 1855, 1856, 1856, 1856, 1857,    0,
+     1857, 1858, 1858, 1858,    0, 1858, 1858, 1859, 1859, 1859,
+     1860, 1860, 1860, 1861, 1861, 1861, 1862, 1862, 1862, 1863,
+     1863, 1863, 1864, 1864, 1864, 1865, 1865, 1865, 1866,    0,
+     1866, 1867,    0, 1867, 1868, 1868, 1868, 1869, 1869, 1869,
+     1870,    0, 1870, 1871,    0, 1871, 1872,    0, 1872, 1873,
+     1873, 1873, 1874, 1874, 1874, 1875,    0, 1875, 1876,    0,
+     1876, 1877,    0, 1877, 1878,    0, 1878, 1879, 1879, 1879,
+     1880, 1880, 1880, 1881,    0, 1881, 1882,    0, 1882, 1883,
 
-        0,    0, 1848, 1849, 1849,    0, 1849, 1850, 1850,    0,
-        0, 1850, 1851, 1851,    0, 1851, 1852, 1852, 1853, 1853,
-        0,    0, 1853, 1854, 1854, 1854, 1855, 1855, 1855, 1856,
-     1856,    0, 1856, 1857,    0, 1857, 1858,    0, 1858, 1859,
-        0, 1859, 1860, 1860, 1860, 1861, 1861, 1861, 1862,    0,
-     1862, 1863, 1863, 1863,    0, 1863, 1863, 1864, 1864, 1864,
-     1865, 1865, 1865, 1866, 1866, 1866, 1867, 1867, 1867, 1868,
-     1868, 1868, 1869, 1869, 1869, 1870, 1870, 1870, 1871,    0,
-     1871, 1872,    0, 1872, 1873, 1873, 1873, 1874, 1874, 1874,
-     1875,    0, 1875, 1876,    0, 1876, 1877,    0, 1877, 1878,
+        0,    0, 1883, 1884, 1884,    0, 1884, 1885, 1885,    0,
+        0, 1885, 1886, 1886,    0, 1886, 1887, 1887, 1888, 1888,
+        0,    0, 1888, 1889, 1889, 1889, 1890, 1890, 1890, 1891,
+     1891,    0, 1891, 1892, 1892, 1892,    0, 1892, 1892, 1893,
+     1893, 1893, 1894, 1894, 1894, 1895, 1895, 1895, 1896, 1896,
+     1896, 1897, 1897, 1897, 1898, 1898, 1898, 1899, 1899, 1899,
+     1900, 1900, 1900, 1901, 1901,    0,    0, 1901, 1902, 1902,
+     1902, 1903, 1903, 1903, 1904, 1904,    0, 1904, 1905, 1905,
+        0,    0, 1905, 1906, 1906,    0, 1906, 1907, 1907, 1908,
+     1908,    0,    0, 1908, 1909, 1909, 1909, 1910, 1910, 1910,
 
-     1878, 1878, 1879, 1879, 1879, 1880,    0, 1880, 1881,    0,
-     1881, 1882,    0, 1882, 1883,    0, 1883, 1884, 1884, 1884,
-     1885, 1885, 1885, 1886,    0, 1886, 1887,    0, 1887, 1888,
-        0,    0, 1888, 1889, 1889,    0, 1889, 1890, 1890,    0,
-        0, 1890, 1891, 1891,    0, 1891, 1892, 1892, 1893, 1893,
-        0,    0, 1893, 1894, 1894, 1894, 1895, 1895, 1895, 1896,
-     1896,    0, 1896, 1897, 1897, 1897,    0, 1897, 1897, 1898,
-     1898, 1898, 1899, 1899, 1899, 1900, 1900, 1900, 1901, 1901,
-     1901, 1902, 1902, 1902, 1903, 1903, 1903, 1904, 1904, 1904,
-     1905, 1905, 1905, 1906, 1906,    0,    0, 1906, 1907, 1907,
+     1911, 1911,    0, 1911, 1912,    0,    0, 1912, 1913, 1913,
+        0, 1913, 1914, 1914,    0,    0, 1914, 1915, 1915,    0,
+     1915, 1916, 1916, 1917, 1917,    0,    0, 1917, 1918, 1918,
+     1918, 1919, 1919, 1919, 1920, 1920,    0, 1920, 1921,    0,
+     1921, 1922,    0,    0, 1922, 1923, 1923,    0, 1923, 1924,
+     1924,    0,    0, 1924, 1925, 1925,    0, 1925, 1926, 1926,
+     1927, 1927,    0,    0, 1927, 1928, 1928, 1928, 1929, 1929,
+     1929, 1930, 1930,    0, 1930, 1931,    0, 1931, 1932,    0,
+     1932, 1933,    0, 1933, 1934, 1934, 1934, 1935, 1935, 1935,
+     1936,    0, 1936, 1937, 1937, 1937,    0, 1937, 1937, 1938,
 
-     1907, 1908, 1908, 1908, 1909, 1909,    0, 1909, 1910, 1910,
-        0,    0, 1910, 1911, 1911,    0, 1911, 1912, 1912, 1913,
-     1913,    0,    0, 1913, 1914, 1914, 1914, 1915, 1915, 1915,
-     1916, 1916,    0, 1916, 1917,    0,    0, 1917, 1918, 1918,
-        0, 1918, 1919, 1919,    0,    0, 1919, 1920, 1920,    0,
-     1920, 1921, 1921, 1922, 1922,    0,    0, 1922, 1923, 1923,
-     1923, 1924, 1924, 1924, 1925, 1925,    0, 1925, 1926,    0,
-     1926, 1927,    0,    0, 1927, 1928, 1928,    0, 1928, 1929,
-     1929,    0,    0, 1929, 1930, 1930,    0, 1930, 1931, 1931,
-     1932, 1932,    0,    0, 1932, 1933, 1933, 1933, 1934, 1934,
+     1938, 1938, 1939, 1939, 1939, 1940, 1940, 1940, 1941, 1941,
+     1941, 1942, 1942, 1942, 1943, 1943, 1943, 1944, 1944, 1944,
+     1945, 1945, 1945, 1946, 1946, 1946, 1947, 1947, 1947, 1948,
+        0, 1948, 1949,    0, 1949, 1950, 1950, 1950, 1951, 1951,
+     1951, 1952, 1952, 1952, 1953,    0, 1953, 1954,    0, 1954,
+     1955,    0, 1955, 1956, 1956, 1956, 1957, 1957, 1957, 1958,
+     1958, 1958, 1959,    0, 1959, 1960,    0, 1960, 1961,    0,
+     1961, 1962,    0, 1962, 1963, 1963, 1963, 1964, 1964, 1964,
+     1965, 1965, 1965, 1966,    0, 1966, 1967,    0, 1967, 1968,
+        0, 1968, 1969,    0, 1969, 1970, 1970, 1970, 1971, 1971,
 
-     1934, 1935, 1935,    0, 1935, 1936,    0, 1936, 1937,    0,
-     1937, 1938,    0, 1938, 1939, 1939, 1939, 1940, 1940, 1940,
-     1941,    0, 1941, 1942, 1942, 1942,    0, 1942, 1942, 1943,
-     1943, 1943, 1944, 1944, 1944, 1945, 1945, 1945, 1946, 1946,
-     1946, 1947, 1947, 1947, 1948, 1948, 1948, 1949, 1949, 1949,
-     1950, 1950, 1950, 1951, 1951, 1951, 1952, 1952, 1952, 1953,
-        0, 1953, 1954,    0, 1954, 1955, 1955, 1955, 1956, 1956,
-     1956, 1957, 1957, 1957, 1958,    0, 1958, 1959,    0, 1959,
-     1960,    0, 1960, 1961, 1961, 1961, 1962, 1962, 1962, 1963,
-     1963, 1963, 1964,    0, 1964, 1965,    0, 1965, 1966,    0,
+     1971, 1972, 1972, 1972, 1973,    0, 1973, 1974,    0, 1974,
+     1975,    0,    0, 1975, 1976, 1976,    0, 1976, 1977, 1977,
+        0,    0, 1977, 1978, 1978,    0, 1978, 1979, 1979, 1980,
+     1980,    0,    0, 1980, 1981, 1981, 1981, 1982, 1982, 1982,
+     1983, 1983,    0, 1983, 1984, 1984, 1984,    0, 1984, 1984,
+     1985, 1985, 1985, 1986, 1986, 1986, 1987, 1987, 1987, 1988,
+     1988, 1988, 1989, 1989, 1989, 1990, 1990, 1990, 1991, 1991,
+     1991, 1992, 1992, 1992, 1993,    0, 1993, 1994, 1994, 1994,
+     1995, 1995,    0,    0, 1995, 1996, 1996, 1996, 1997, 1997,
+     1997, 1998, 1998,    0, 1998, 1999, 1999,    0,    0, 1999,
 
-     1966, 1967,    0, 1967, 1968, 1968, 1968, 1969, 1969, 1969,
-     1970, 1970, 1970, 1971,    0, 1971, 1972,    0, 1972, 1973,
-        0, 1973, 1974,    0, 1974, 1975, 1975, 1975, 1976, 1976,
-     1976, 1977, 1977, 1977, 1978,    0, 1978, 1979,    0, 1979,
-     1980,    0,    0, 1980, 1981, 1981,    0, 1981, 1982, 1982,
-        0,    0, 1982, 1983, 1983,    0, 1983, 1984, 1984, 1985,
-     1985,    0,    0, 1985, 1986, 1986, 1986, 1987, 1987, 1987,
-     1988, 1988,    0, 1988, 1989, 1989, 1989,    0, 1989, 1989,
-     1990, 1990, 1990, 1991, 1991, 1991, 1992, 1992, 1992, 1993,
-     1993, 1993, 1994, 1994, 1994, 1995, 1995, 1995, 1996, 1996,
+     2000, 2000,    0, 2000, 2001, 2001, 2002, 2002,    0,    0,
+     2002, 2003, 2003, 2003, 2004, 2004, 2004, 2005, 2005,    0,
+     2005, 2006,    0,    0, 2006, 2007, 2007,    0, 2007, 2008,
+     2008,    0,    0, 2008, 2009, 2009,    0, 2009, 2010, 2010,
+     2011, 2011,    0,    0, 2011, 2012, 2012, 2012, 2013, 2013,
+     2013, 2014, 2014,    0, 2014, 2015,    0, 2015, 2016,    0,
+        0, 2016, 2017, 2017,    0, 2017, 2018, 2018,    0,    0,
+     2018, 2019, 2019,    0, 2019, 2020, 2020, 2021, 2021,    0,
+        0, 2021, 2022, 2022, 2022, 2023, 2023, 2023, 2024, 2024,
+        0, 2024, 2025,    0, 2025, 2026,    0,    0, 2026, 2027,
 
-     1996, 1997, 1997, 1997, 1998,    0, 1998, 1999, 1999, 1999,
-     2000, 2000,    0,    0, 2000, 2001, 2001, 2001, 2002, 2002,
-     2002, 2003, 2003,    0, 2003, 2004, 2004,    0,    0, 2004,
-     2005, 2005,    0, 2005, 2006, 2006, 2007, 2007,    0,    0,
-     2007, 2008, 2008, 2008, 2009, 2009, 2009, 2010, 2010,    0,
-     2010, 2011,    0,    0, 2011, 2012, 2012,    0, 2012, 2013,
-     2013,    0,    0, 2013, 2014, 2014,    0, 2014, 2015, 2015,
-     2016, 2016,    0,    0, 2016, 2017, 2017, 2017, 2018, 2018,
-     2018, 2019, 2019,    0, 2019, 2020,    0, 2020, 2021,    0,
-        0, 2021, 2022, 2022,    0, 2022, 2023, 2023,    0,    0,
+     2027,    0, 2027, 2028, 2028,    0,    0, 2028, 2029, 2029,
+        0, 2029, 2030, 2030, 2031, 2031,    0,    0, 2031, 2032,
+     2032, 2032, 2033, 2033, 2033, 2034, 2034,    0, 2034, 2035,
+        0, 2035, 2036,    0, 2036, 2037,    0, 2037, 2038, 2038,
+     2038, 2039,    0, 2039, 2040, 2040, 2040, 2041,    0, 2041,
+     2042, 2042, 2042,    0, 2042, 2042, 2043,    0, 2043, 2044,
+     2044, 2044, 2045,    0, 2045, 2046, 2046, 2046, 2047,    0,
+     2047, 2048, 2048, 2048, 2049,    0, 2049, 2050, 2050, 2050,
+     2051,    0, 2051, 2052, 2052, 2052, 2053,    0, 2053, 2054,
+     2054, 2054, 2055, 2055,    0,    0, 2055, 2056, 2056, 2056,
 
-     2023, 2024, 2024,    0, 2024, 2025, 2025, 2026, 2026,    0,
-        0, 2026, 2027, 2027, 2027, 2028, 2028, 2028, 2029, 2029,
-        0, 2029, 2030,    0, 2030, 2031,    0,    0, 2031, 2032,
-     2032,    0, 2032, 2033, 2033,    0,    0, 2033, 2034, 2034,
-        0, 2034, 2035, 2035, 2036, 2036,    0,    0, 2036, 2037,
-     2037, 2037, 2038, 2038, 2038, 2039, 2039,    0, 2039, 2040,
-        0, 2040, 2041,    0, 2041, 2042,    0, 2042, 2043, 2043,
-     2043, 2044,    0, 2044, 2045, 2045, 2045, 2046,    0, 2046,
-     2047, 2047, 2047,    0, 2047, 2047, 2048,    0, 2048, 2049,
-     2049, 2049, 2050,    0, 2050, 2051, 2051, 2051, 2052,    0,
+     2057, 2057, 2057, 2058, 2058, 2058, 2059, 2059,    0, 2059,
+     2060, 2060, 2060, 2061,    0, 2061, 2062, 2062, 2062, 2063,
+     2063, 2063, 2064,    0, 2064, 2065,    0, 2065, 2066, 2066,
+     2066, 2067, 2067, 2067, 2068,    0, 2068, 2069,    0, 2069,
+     2070,    0, 2070, 2071, 2071, 2071, 2072, 2072, 2072, 2073,
+        0, 2073, 2074,    0, 2074, 2075,    0, 2075, 2076, 2076,
+     2076, 2077, 2077, 2077, 2078,    0, 2078, 2079,    0, 2079,
+     2080,    0, 2080, 2081, 2081, 2081, 2082, 2082, 2082, 2083,
+        0, 2083, 2084,    0,    0, 2084, 2085, 2085,    0, 2085,
+     2086, 2086,    0,    0, 2086, 2087, 2087,    0, 2087, 2088,
 
-     2052, 2053, 2053, 2053, 2054,    0, 2054, 2055, 2055, 2055,
-     2056,    0, 2056, 2057, 2057, 2057, 2058,    0, 2058, 2059,
-     2059, 2059, 2060, 2060,    0,    0, 2060, 2061, 2061, 2061,
-     2062, 2062, 2062, 2063, 2063, 2063, 2064, 2064,    0, 2064,
-     2065, 2065, 2065, 2066,    0, 2066, 2067, 2067, 2067, 2068,
-     2068, 2068, 2069,    0, 2069, 2070,    0, 2070, 2071, 2071,
-     2071, 2072, 2072, 2072, 2073,    0, 2073, 2074,    0, 2074,
-     2075,    0, 2075, 2076, 2076, 2076, 2077, 2077, 2077, 2078,
-        0, 2078, 2079,    0, 2079, 2080,    0, 2080, 2081, 2081,
-     2081, 2082, 2082, 2082, 2083,    0, 2083, 2084,    0, 2084,
+     2088, 2089, 2089,    0,    0, 2089, 2090, 2090, 2090, 2091,
+        0, 2091, 2092, 2092,    0, 2092, 2093, 2093, 2093,    0,
+     2093, 2093, 2094, 2094, 2094, 2095, 2095, 2095, 2096,    0,
+     2096, 2097,    0, 2097, 2098,    0, 2098, 2099,    0, 2099,
+     2100,    0, 2100, 2101,    0, 2101, 2102,    0, 2102, 2103,
+     2103, 2103, 2104, 2104, 2104, 2105,    0, 2105, 2106, 2106,
+        0,    0, 2106, 2107, 2107,    0, 2107, 2108, 2108, 2109,
+        0, 2109, 2110,    0,    0, 2110, 2111, 2111,    0, 2111,
+     2112, 2112,    0,    0, 2112, 2113, 2113,    0, 2113, 2114,
+     2114, 2115,    0, 2115, 2116,    0, 2116, 2117,    0,    0,
 
-     2085,    0, 2085, 2086, 2086, 2086, 2087, 2087, 2087, 2088,
-        0, 2088, 2089,    0,    0, 2089, 2090, 2090,    0, 2090,
-     2091, 2091,    0,    0, 2091, 2092, 2092,    0, 2092, 2093,
-     2093, 2094, 2094,    0,    0, 2094, 2095, 2095, 2095, 2096,
-        0, 2096, 2097, 2097,    0, 2097, 2098, 2098, 2098,    0,
-     2098, 2098, 2099, 2099, 2099, 2100, 2100, 2100, 2101,    0,
-     2101, 2102,    0, 2102, 2103,    0, 2103, 2104,    0, 2104,
-     2105,    0, 2105, 2106,    0, 2106, 2107,    0, 2107, 2108,
-     2108, 2108, 2109, 2109, 2109, 2110,    0, 2110, 2111, 2111,
-        0,    0, 2111, 2112, 2112,    0, 2112, 2113, 2113, 2114,
+     2117, 2118, 2118,    0, 2118, 2119, 2119,    0,    0, 2119,
+     2120, 2120,    0, 2120, 2121, 2121, 2122,    0, 2122, 2123,
+        0, 2123, 2124,    0,    0, 2124, 2125, 2125,    0, 2125,
+     2126, 2126,    0,    0, 2126, 2127, 2127,    0, 2127, 2128,
+     2128, 2129,    0, 2129, 2130,    0, 2130, 2131,    0,    0,
+     2131, 2132, 2132,    0, 2132, 2133, 2133,    0,    0, 2133,
+     2134, 2134,    0, 2134, 2135, 2135, 2136,    0, 2136, 2137,
+        0, 2137, 2138,    0, 2138, 2139,    0, 2139, 2140, 2140,
+     2140, 2141,    0, 2141, 2142, 2142, 2142,    0, 2142, 2142,
+     2143,    0, 2143, 2144,    0, 2144, 2145,    0, 2145, 2146,
 
-        0, 2114, 2115,    0,    0, 2115, 2116, 2116,    0, 2116,
-     2117, 2117,    0,    0, 2117, 2118, 2118,    0, 2118, 2119,
-     2119, 2120,    0, 2120, 2121,    0, 2121, 2122,    0,    0,
-     2122, 2123, 2123,    0, 2123, 2124, 2124,    0,    0, 2124,
-     2125, 2125,    0, 2125, 2126, 2126, 2127,    0, 2127, 2128,
-        0, 2128, 2129,    0,    0, 2129, 2130, 2130,    0, 2130,
-     2131, 2131,    0,    0, 2131, 2132, 2132,    0, 2132, 2133,
-     2133, 2134,    0, 2134, 2135,    0, 2135, 2136,    0,    0,
-     2136, 2137, 2137,    0, 2137, 2138, 2138,    0,    0, 2138,
-     2139, 2139,    0, 2139, 2140, 2140, 2141,    0, 2141, 2142,
+        0, 2146, 2147,    0, 2147, 2148,    0, 2148, 2149,    0,
+     2149, 2150, 2150,    0,    0, 2150, 2151, 2151,    0, 2151,
+     2152, 2152, 2153,    0, 2153, 2154,    0, 2154, 2155,    0,
+     2155, 2156,    0, 2156, 2157,    0, 2157, 2158,    0, 2158,
+     2159,    0, 2159, 2160,    0, 2160, 2161,    0, 2161, 2162,
+        0, 2162, 2163,    0,    0, 2163, 2164, 2164,    0,    0,
+     2164, 2165,    0, 2165, 2166,    0, 2166, 2167,    0, 2167,
+     2168,    0,    0, 2168, 2169,    0,    0, 2169, 2170,    0,
+        0, 2170, 2171,    0,    0, 2171, 2172,    0,    0, 2172,
+     2173,    0, 2173, 2174,    0, 2174, 2175,    0,    0, 2175,
 
-        0, 2142, 2143,    0, 2143, 2144,    0, 2144, 2145, 2145,
-     2145, 2146,    0, 2146, 2147, 2147, 2147,    0, 2147, 2147,
-     2148,    0, 2148, 2149,    0, 2149, 2150,    0, 2150, 2151,
-        0, 2151, 2152,    0, 2152, 2153,    0, 2153, 2154,    0,
-     2154, 2155, 2155,    0,    0, 2155, 2156, 2156,    0, 2156,
-     2157, 2157, 2158,    0, 2158, 2159,    0, 2159, 2160,    0,
-     2160, 2161,    0, 2161, 2162,    0, 2162, 2163,    0, 2163,
-     2164,    0, 2164, 2165,    0, 2165, 2166,    0, 2166, 2167,
-        0, 2167, 2168,    0,    0, 2168, 2169, 2169,    0,    0,
-     2169, 2170,    0, 2170, 2171,    0, 2171, 2172,    0, 2172,
-
-     2173,    0,    0, 2173, 2174,    0,    0, 2174, 2175,    0,
-        0, 2175, 2176,    0,    0, 2176, 2177,    0,    0, 2177,
-     2178,    0, 2178, 2179,    0, 2179, 2180,    0,    0, 2180,
-     2181,    0, 2181, 2182,    0, 2182, 2183,    0, 2183, 2184,
-        0, 2184, 2185,    0, 2185, 2186,    0,    0, 2186, 2187,
-        0, 2187, 2188,    0, 2188, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
-
-     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
+     2176,    0, 2176, 2177,    0, 2177, 2178,    0, 2178, 2179,
+        0, 2179, 2180,    0, 2180, 2181,    0,    0, 2181, 2182,
+        0, 2182, 2183,    0, 2183, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723,
+     1723, 1723, 1723, 1723, 1723, 1723, 1723, 1723
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -2978,7 +3140,8 @@
  */
 DIAG_OFF_FLEX
 
-#line 2982 "scanner.c"
+#line 3144 "scanner.c"
+#line 3145 "scanner.c"
 
 #define INITIAL 0
 
@@ -3028,52 +3191,52 @@
 
     }; /* end struct yyguts_t */
 
-static int yy_init_globals (yyscan_t yyscanner );
+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 yylex_init (yyscan_t* scanner);
 
-int pcap_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_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 yylex_destroy ( yyscan_t yyscanner );
 
-int pcap_get_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
 
-void pcap_set_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
 
-YY_EXTRA_TYPE pcap_get_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
 
-void pcap_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
 
-FILE *pcap_get_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
 
-void pcap_set_in  (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in  ( FILE * _in_str , yyscan_t yyscanner );
 
-FILE *pcap_get_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
 
-void pcap_set_out  (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out  ( FILE * _out_str , yyscan_t yyscanner );
 
-			int pcap_get_leng (yyscan_t yyscanner );
+			int yyget_leng ( yyscan_t yyscanner );
 
-char *pcap_get_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
 
-int pcap_get_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
 
-void pcap_set_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
 
-int pcap_get_column  (yyscan_t yyscanner );
+int yyget_column  ( yyscan_t yyscanner );
 
-void pcap_set_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
 
-YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
+YYSTYPE * yyget_lval ( yyscan_t yyscanner );
 
-void pcap_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -3081,9 +3244,9 @@
 
 #ifndef YY_SKIP_YYWRAP
 #ifdef __cplusplus
-extern "C" int pcap_wrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
 #else
-extern int pcap_wrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
 #endif
 #endif
 
@@ -3092,19 +3255,18 @@
 #endif
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
 #endif
 
 #ifndef YY_NO_INPUT
-
 #ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
 #else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
 #endif
 
 #endif
@@ -3135,7 +3297,7 @@
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		int n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -3148,7 +3310,7 @@
 	else \
 		{ \
 		errno=0; \
-		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
 			{ \
 			if( errno != EINTR) \
 				{ \
@@ -3189,10 +3351,10 @@
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int pcap_lex \
-               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+extern int yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner);
 
-#define YY_DECL int pcap_lex \
+#define YY_DECL int yylex \
                (YYSTYPE * yylval_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
@@ -3240,18 +3402,18 @@
 			yyout = stdout;
 
 		if ( ! YY_CURRENT_BUFFER ) {
-			pcap_ensure_buffer_stack (yyscanner);
+			yyensure_buffer_stack (yyscanner);
 			YY_CURRENT_BUFFER_LVALUE =
-				pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+				yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
 		}
 
-		pcap__load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 		}
 
 	{
 #line 254 "scanner.l"
 
-#line 3255 "scanner.c"
+#line 3417 "scanner.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -3278,13 +3440,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 1729 )
-					yy_c = yy_meta[(unsigned int) yy_c];
+				if ( yy_current_state >= 1724 )
+					yy_c = yy_meta[yy_c];
 				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 1728 );
+		while ( yy_current_state != 1723 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -3557,705 +3719,690 @@
 case 51:
 YY_RULE_SETUP
 #line 314 "scanner.l"
-{
-#ifdef NO_PROTOCHAIN
-		  bpf_error(yyextra, "%s not supported", yytext);
-#else
-		  return PROTOCHAIN;
-#endif
-		}
+return PROTOCHAIN;
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 322 "scanner.l"
+#line 316 "scanner.l"
 return GATEWAY;
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 324 "scanner.l"
+#line 318 "scanner.l"
 return TYPE;
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 325 "scanner.l"
+#line 319 "scanner.l"
 return SUBTYPE;
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 326 "scanner.l"
+#line 320 "scanner.l"
 return DIR;
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 327 "scanner.l"
+#line 321 "scanner.l"
 return ADDR1;
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 328 "scanner.l"
+#line 322 "scanner.l"
 return ADDR2;
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 329 "scanner.l"
+#line 323 "scanner.l"
 return ADDR3;
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 330 "scanner.l"
+#line 324 "scanner.l"
 return ADDR4;
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 331 "scanner.l"
+#line 325 "scanner.l"
 return RA;
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 332 "scanner.l"
+#line 326 "scanner.l"
 return TA;
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 334 "scanner.l"
+#line 328 "scanner.l"
 return LESS;
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 335 "scanner.l"
+#line 329 "scanner.l"
 return GREATER;
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 336 "scanner.l"
+#line 330 "scanner.l"
 return CBYTE;
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 337 "scanner.l"
+#line 331 "scanner.l"
 return TK_BROADCAST;
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 338 "scanner.l"
+#line 332 "scanner.l"
 return TK_MULTICAST;
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 340 "scanner.l"
+#line 334 "scanner.l"
 return AND;
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 341 "scanner.l"
+#line 335 "scanner.l"
 return OR;
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 342 "scanner.l"
+#line 336 "scanner.l"
 return '!';
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 344 "scanner.l"
+#line 338 "scanner.l"
 return LEN;
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 345 "scanner.l"
+#line 339 "scanner.l"
 return INBOUND;
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 346 "scanner.l"
+#line 340 "scanner.l"
 return OUTBOUND;
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 348 "scanner.l"
+#line 342 "scanner.l"
 return VLAN;
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 349 "scanner.l"
+#line 343 "scanner.l"
 return MPLS;
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 350 "scanner.l"
+#line 344 "scanner.l"
 return PPPOED;
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 351 "scanner.l"
+#line 345 "scanner.l"
 return PPPOES;
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 352 "scanner.l"
+#line 346 "scanner.l"
 return GENEVE;
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 354 "scanner.l"
+#line 348 "scanner.l"
 return LANE;
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 355 "scanner.l"
+#line 349 "scanner.l"
 return LLC;
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 356 "scanner.l"
+#line 350 "scanner.l"
 return METAC;
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 357 "scanner.l"
+#line 351 "scanner.l"
 return BCC;
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 358 "scanner.l"
+#line 352 "scanner.l"
 return OAM;
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 359 "scanner.l"
+#line 353 "scanner.l"
 return OAMF4;
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 360 "scanner.l"
+#line 354 "scanner.l"
 return OAMF4EC;
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 361 "scanner.l"
+#line 355 "scanner.l"
 return OAMF4SC;
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 362 "scanner.l"
+#line 356 "scanner.l"
 return SC;
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 363 "scanner.l"
+#line 357 "scanner.l"
 return ILMIC;
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 364 "scanner.l"
+#line 358 "scanner.l"
 return VPI;
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 365 "scanner.l"
+#line 359 "scanner.l"
 return VCI;
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 366 "scanner.l"
+#line 360 "scanner.l"
 return CONNECTMSG;
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 367 "scanner.l"
+#line 361 "scanner.l"
 return METACONNECT;
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 369 "scanner.l"
+#line 363 "scanner.l"
 return PF_IFNAME;
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 370 "scanner.l"
+#line 364 "scanner.l"
 return PF_RSET;
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 371 "scanner.l"
+#line 365 "scanner.l"
 return PF_RNR;
 	YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 372 "scanner.l"
+#line 366 "scanner.l"
 return PF_SRNR;
 	YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 373 "scanner.l"
+#line 367 "scanner.l"
 return PF_REASON;
 	YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 374 "scanner.l"
+#line 368 "scanner.l"
 return PF_ACTION;
 	YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 376 "scanner.l"
+#line 370 "scanner.l"
 return FISU;
 	YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 377 "scanner.l"
+#line 371 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 378 "scanner.l"
+#line 372 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 379 "scanner.l"
+#line 373 "scanner.l"
 return MSU;
 	YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 380 "scanner.l"
+#line 374 "scanner.l"
 return HFISU;
 	YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 381 "scanner.l"
+#line 375 "scanner.l"
 return HLSSU;
 	YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 382 "scanner.l"
+#line 376 "scanner.l"
 return HMSU;
 	YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 383 "scanner.l"
+#line 377 "scanner.l"
 return SIO;
 	YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 384 "scanner.l"
+#line 378 "scanner.l"
 return OPC;
 	YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 385 "scanner.l"
+#line 379 "scanner.l"
 return DPC;
 	YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 386 "scanner.l"
+#line 380 "scanner.l"
 return SLS;
 	YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 387 "scanner.l"
+#line 381 "scanner.l"
 return HSIO;
 	YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 388 "scanner.l"
+#line 382 "scanner.l"
 return HOPC;
 	YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 389 "scanner.l"
+#line 383 "scanner.l"
 return HDPC;
 	YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 390 "scanner.l"
+#line 384 "scanner.l"
 return HSLS;
 	YY_BREAK
 case 113:
 /* rule 113 can match eol */
 YY_RULE_SETUP
-#line 392 "scanner.l"
+#line 386 "scanner.l"
 ;
 	YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 393 "scanner.l"
+#line 387 "scanner.l"
 return yytext[0];
 	YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 394 "scanner.l"
+#line 388 "scanner.l"
 return GEQ;
 	YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 395 "scanner.l"
+#line 389 "scanner.l"
 return LEQ;
 	YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 396 "scanner.l"
+#line 390 "scanner.l"
 return NEQ;
 	YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 397 "scanner.l"
+#line 391 "scanner.l"
 return '=';
 	YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 398 "scanner.l"
+#line 392 "scanner.l"
 return LSH;
 	YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 399 "scanner.l"
+#line 393 "scanner.l"
 return RSH;
 	YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 400 "scanner.l"
-{ yylval->e = pcap_ether_aton(((char *)yytext)+1);
-			  if (yylval->e == NULL)
-				bpf_error(yyextra, "malloc");
-			  return AID; }
+#line 394 "scanner.l"
+{ yylval->s = sdup(yyextra, yytext); return AID; }
 	YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 404 "scanner.l"
-{ yylval->e = pcap_ether_aton((char *)yytext);
-			  if (yylval->e == NULL)
-				bpf_error(yyextra, "malloc");
-			  return EID; }
+#line 395 "scanner.l"
+{ yylval->s = sdup(yyextra, yytext); return EID; }
 	YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 408 "scanner.l"
+#line 396 "scanner.l"
 { yylval->i = stoi((char *)yytext); return NUM; }
 	YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 409 "scanner.l"
+#line 397 "scanner.l"
 {
 			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 	YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 411 "scanner.l"
+#line 399 "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(yytext, NULL, &hints, &res))
-				bpf_error(yyextra, "bogus IPv6 address %s", yytext);
-			  else {
+			  if (getaddrinfo(yytext, NULL, &hints, &res)) {
+				bpf_set_error(yyextra, "bogus IPv6 address %s", yytext);
+				yylval->s = NULL;
+			  } else {
 				freeaddrinfo(res);
-				yylval->s = sdup(yyextra, (char *)yytext); return HID6;
+				yylval->s = sdup(yyextra, (char *)yytext);
 			  }
 #else
-			  bpf_error(yyextra, "IPv6 address %s not supported", yytext);
+			  bpf_set_error(yyextra, "IPv6 address %s not supported", yytext);
+			  yylval->s = NULL;
 #endif /*INET6*/
+			  return HID6;
 			}
 	YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 427 "scanner.l"
-{ bpf_error(yyextra, "bogus ethernet address %s", yytext); }
+#line 418 "scanner.l"
+{ bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; }
 	YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 428 "scanner.l"
+#line 419 "scanner.l"
 { yylval->i = 0; return NUM; }
 	YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 429 "scanner.l"
+#line 420 "scanner.l"
 { yylval->i = 1; return NUM; }
 	YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 430 "scanner.l"
+#line 421 "scanner.l"
 { yylval->i = 0; return NUM; }
 	YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 431 "scanner.l"
+#line 422 "scanner.l"
 { yylval->i = 3; return NUM; }
 	YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 432 "scanner.l"
+#line 423 "scanner.l"
 { yylval->i = 4; return NUM; }
 	YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 433 "scanner.l"
+#line 424 "scanner.l"
 { yylval->i = 5; return NUM; }
 	YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 434 "scanner.l"
+#line 425 "scanner.l"
 { yylval->i = 8; return NUM; }
 	YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 435 "scanner.l"
+#line 426 "scanner.l"
 { yylval->i = 9; return NUM; }
 	YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 436 "scanner.l"
+#line 427 "scanner.l"
 { yylval->i = 10; return NUM; }
 	YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 437 "scanner.l"
+#line 428 "scanner.l"
 { yylval->i = 11; return NUM; }
 	YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 438 "scanner.l"
+#line 429 "scanner.l"
 { yylval->i = 12; return NUM; }
 	YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 439 "scanner.l"
+#line 430 "scanner.l"
 { yylval->i = 13; return NUM; }
 	YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 440 "scanner.l"
+#line 431 "scanner.l"
 { yylval->i = 14; return NUM; }
 	YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 441 "scanner.l"
+#line 432 "scanner.l"
 { yylval->i = 15; return NUM; }
 	YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 442 "scanner.l"
+#line 433 "scanner.l"
 { yylval->i = 16; return NUM; }
 	YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 443 "scanner.l"
+#line 434 "scanner.l"
 { yylval->i = 17; return NUM; }
 	YY_BREAK
 case 143:
 YY_RULE_SETUP
-#line 444 "scanner.l"
+#line 435 "scanner.l"
 { yylval->i = 18; return NUM; }
 	YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 446 "scanner.l"
+#line 437 "scanner.l"
 { yylval->i = 0; return NUM; }
 	YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 447 "scanner.l"
+#line 438 "scanner.l"
 { yylval->i = 1; return NUM; }
 	YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 449 "scanner.l"
+#line 440 "scanner.l"
 { yylval->i = 128; return NUM; }
 	YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 450 "scanner.l"
+#line 441 "scanner.l"
 { yylval->i = 129; return NUM; }
 	YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 451 "scanner.l"
+#line 442 "scanner.l"
 { yylval->i = 130; return NUM; }
 	YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 452 "scanner.l"
+#line 443 "scanner.l"
 { yylval->i = 131; return NUM; }
 	YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 453 "scanner.l"
+#line 444 "scanner.l"
 { yylval->i = 132; return NUM; }
 	YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 454 "scanner.l"
+#line 445 "scanner.l"
 { yylval->i = 133; return NUM; }
 	YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 455 "scanner.l"
+#line 446 "scanner.l"
 { yylval->i = 134; return NUM; }
 	YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 456 "scanner.l"
+#line 447 "scanner.l"
 { yylval->i = 135; return NUM; }
 	YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 457 "scanner.l"
+#line 448 "scanner.l"
 { yylval->i = 136; return NUM; }
 	YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 458 "scanner.l"
+#line 449 "scanner.l"
 { yylval->i = 137; return NUM; }
 	YY_BREAK
 case 156:
 YY_RULE_SETUP
-#line 459 "scanner.l"
+#line 450 "scanner.l"
 { yylval->i = 138; return NUM; }
 	YY_BREAK
 case 157:
 YY_RULE_SETUP
-#line 460 "scanner.l"
+#line 451 "scanner.l"
 { yylval->i = 139; return NUM; }
 	YY_BREAK
 case 158:
 YY_RULE_SETUP
-#line 461 "scanner.l"
+#line 452 "scanner.l"
 { yylval->i = 140; return NUM; }
 	YY_BREAK
 case 159:
 YY_RULE_SETUP
-#line 462 "scanner.l"
+#line 453 "scanner.l"
 { yylval->i = 141; return NUM; }
 	YY_BREAK
 case 160:
 YY_RULE_SETUP
-#line 463 "scanner.l"
+#line 454 "scanner.l"
 { yylval->i = 142; return NUM; }
 	YY_BREAK
 case 161:
 YY_RULE_SETUP
-#line 464 "scanner.l"
+#line 455 "scanner.l"
 { yylval->i = 143; return NUM; }
 	YY_BREAK
 case 162:
 YY_RULE_SETUP
-#line 465 "scanner.l"
+#line 456 "scanner.l"
 { yylval->i = 144; return NUM; }
 	YY_BREAK
 case 163:
 YY_RULE_SETUP
-#line 466 "scanner.l"
+#line 457 "scanner.l"
 { yylval->i = 145; return NUM; }
 	YY_BREAK
 case 164:
 YY_RULE_SETUP
-#line 467 "scanner.l"
+#line 458 "scanner.l"
 { yylval->i = 146; return NUM; }
 	YY_BREAK
 case 165:
 YY_RULE_SETUP
-#line 468 "scanner.l"
+#line 459 "scanner.l"
 { yylval->i = 147; return NUM; }
 	YY_BREAK
 case 166:
 YY_RULE_SETUP
-#line 469 "scanner.l"
+#line 460 "scanner.l"
 { yylval->i = 148; return NUM; }
 	YY_BREAK
 case 167:
 YY_RULE_SETUP
-#line 470 "scanner.l"
+#line 461 "scanner.l"
 { yylval->i = 149; return NUM; }
 	YY_BREAK
 case 168:
 YY_RULE_SETUP
-#line 471 "scanner.l"
+#line 462 "scanner.l"
 { yylval->i = 151; return NUM; }
 	YY_BREAK
 case 169:
 YY_RULE_SETUP
-#line 472 "scanner.l"
+#line 463 "scanner.l"
 { yylval->i = 152; return NUM; }
 	YY_BREAK
 case 170:
 YY_RULE_SETUP
-#line 473 "scanner.l"
+#line 464 "scanner.l"
 { yylval->i = 153; return NUM; }
 	YY_BREAK
 case 171:
 YY_RULE_SETUP
-#line 475 "scanner.l"
+#line 466 "scanner.l"
 { yylval->i = 13; return NUM; }
 	YY_BREAK
 case 172:
 YY_RULE_SETUP
-#line 476 "scanner.l"
+#line 467 "scanner.l"
 { yylval->i = 0x01; return NUM; }
 	YY_BREAK
 case 173:
 YY_RULE_SETUP
-#line 477 "scanner.l"
+#line 468 "scanner.l"
 { yylval->i = 0x02; return NUM; }
 	YY_BREAK
 case 174:
 YY_RULE_SETUP
-#line 478 "scanner.l"
+#line 469 "scanner.l"
 { yylval->i = 0x04; return NUM; }
 	YY_BREAK
 case 175:
 YY_RULE_SETUP
-#line 479 "scanner.l"
+#line 470 "scanner.l"
 { yylval->i = 0x08; return NUM; }
 	YY_BREAK
 case 176:
 YY_RULE_SETUP
-#line 480 "scanner.l"
+#line 471 "scanner.l"
 { yylval->i = 0x10; return NUM; }
 	YY_BREAK
 case 177:
 YY_RULE_SETUP
-#line 481 "scanner.l"
+#line 472 "scanner.l"
 { yylval->i = 0x20; return NUM; }
 	YY_BREAK
 case 178:
 YY_RULE_SETUP
-#line 482 "scanner.l"
+#line 473 "scanner.l"
 { yylval->i = 0x40; return NUM; }
 	YY_BREAK
 case 179:
 YY_RULE_SETUP
-#line 483 "scanner.l"
+#line 474 "scanner.l"
 { yylval->i = 0x80; return NUM; }
 	YY_BREAK
 case 180:
 YY_RULE_SETUP
-#line 484 "scanner.l"
+#line 475 "scanner.l"
 {
 			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
 	YY_BREAK
 case 181:
 YY_RULE_SETUP
-#line 486 "scanner.l"
+#line 477 "scanner.l"
 { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
 	YY_BREAK
 case 182:
 YY_RULE_SETUP
-#line 487 "scanner.l"
-{
-			bpf_error(yyextra, "illegal token: %s", yytext); }
+#line 478 "scanner.l"
+{ return LEX_ERROR; }
 	YY_BREAK
 case 183:
 YY_RULE_SETUP
-#line 489 "scanner.l"
-{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
-	YY_BREAK
-case 184:
-YY_RULE_SETUP
-#line 490 "scanner.l"
+#line 479 "scanner.l"
 ECHO;
 	YY_BREAK
-#line 4259 "scanner.c"
+#line 4406 "scanner.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -4273,7 +4420,7 @@
 			/* We're scanning a new file or input source.  It's
 			 * possible that this happened because the user
 			 * just pointed yyin at a new source and called
-			 * pcap_lex().  If so, then we have to assure
+			 * yylex().  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
@@ -4334,7 +4481,7 @@
 				{
 				yyg->yy_did_buffer_switch_on_eof = 0;
 
-				if ( pcap_wrap(yyscanner ) )
+				if ( yywrap( yyscanner ) )
 					{
 					/* Note: because we've taken care in
 					 * yy_get_next_buffer() to have set up
@@ -4388,7 +4535,7 @@
 	} /* end of action switch */
 		} /* end of scanning one token */
 	} /* end of user's declarations */
-} /* end of pcap_lex */
+} /* end of yylex */
 
 /* yy_get_next_buffer - try to read in a new buffer
  *
@@ -4467,7 +4614,8 @@
 
 				b->yy_ch_buf = (char *)
 					/* Include room in for 2 EOB chars. */
-					pcap_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+					yyrealloc( (void *) b->yy_ch_buf,
+							 (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
 				}
 			else
 				/* Can't grow it, we don't own it. */
@@ -4499,7 +4647,7 @@
 		if ( number_to_move == YY_MORE_ADJ )
 			{
 			ret_val = EOB_ACT_END_OF_FILE;
-			pcap_restart(yyin  ,yyscanner);
+			yyrestart( yyin  , yyscanner);
 			}
 
 		else
@@ -4516,9 +4664,12 @@
 	if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
 		/* Extend the array by 50%, plus the number we really need. */
 		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pcap_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+		/* "- 2" to take care of EOB's */
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
 	}
 
 	yyg->yy_n_chars += number_to_move;
@@ -4551,10 +4702,10 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 1729 )
-				yy_c = yy_meta[(unsigned int) yy_c];
+			if ( yy_current_state >= 1724 )
+				yy_c = yy_meta[yy_c];
 			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 		}
 
 	return yy_current_state;
@@ -4580,11 +4731,11 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 1729 )
-			yy_c = yy_meta[(unsigned int) yy_c];
+		if ( yy_current_state >= 1724 )
+			yy_c = yy_meta[yy_c];
 		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-	yy_is_jam = (yy_current_state == 1728);
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	yy_is_jam = (yy_current_state == 1723);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
@@ -4619,7 +4770,7 @@
 
 		else
 			{ /* need more input */
-			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
 			++yyg->yy_c_buf_p;
 
 			switch ( yy_get_next_buffer( yyscanner ) )
@@ -4636,13 +4787,13 @@
 					 */
 
 					/* Reset buffer status. */
-					pcap_restart(yyin ,yyscanner);
+					yyrestart( yyin , yyscanner);
 
 					/*FALLTHROUGH*/
 
 				case EOB_ACT_END_OF_FILE:
 					{
-					if ( pcap_wrap(yyscanner ) )
+					if ( yywrap( yyscanner ) )
 						return 0;
 
 					if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -4674,34 +4825,34 @@
  * @param yyscanner The scanner object.
  * @note This function does not reset the start condition to @c INITIAL .
  */
-    void pcap_restart  (FILE * input_file , yyscan_t yyscanner)
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	if ( ! YY_CURRENT_BUFFER ){
-        pcap_ensure_buffer_stack (yyscanner);
+        yyensure_buffer_stack (yyscanner);
 		YY_CURRENT_BUFFER_LVALUE =
-            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
 	}
 
-	pcap__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	pcap__load_buffer_state(yyscanner );
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+	yy_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 , yyscan_t yyscanner)
+    void yy_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);
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
      */
-	pcap_ensure_buffer_stack (yyscanner);
+	yyensure_buffer_stack (yyscanner);
 	if ( YY_CURRENT_BUFFER == new_buffer )
 		return;
 
@@ -4714,17 +4865,17 @@
 		}
 
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	pcap__load_buffer_state(yyscanner );
+	yy_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
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
 	 * to go ahead and always set it.
 	 */
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
-static void pcap__load_buffer_state  (yyscan_t yyscanner)
+static void yy_load_buffer_state  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -4739,35 +4890,35 @@
  * @param yyscanner The scanner object.
  * @return the allocated buffer state.
  */
-    YY_BUFFER_STATE pcap__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
-	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
 	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
-	b->yy_buf_size = (yy_size_t)size;
+	b->yy_buf_size = size;
 
 	/* yy_ch_buf has to be 2 characters longer than the size given because
 	 * we need to put in 2 end-of-buffer characters.
 	 */
-	b->yy_ch_buf = (char *) pcap_alloc(b->yy_buf_size + 2 ,yyscanner );
+	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
 	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
 	b->yy_is_our_buffer = 1;
 
-	pcap__init_buffer(b,file ,yyscanner);
+	yy_init_buffer( b, file , yyscanner);
 
 	return b;
 }
 
 /** Destroy the buffer.
- * @param b a buffer created with pcap__create_buffer()
+ * @param b a buffer created with yy_create_buffer()
  * @param yyscanner The scanner object.
  */
-    void pcap__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -4778,28 +4929,28 @@
 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
 
 	if ( b->yy_is_our_buffer )
-		pcap_free((void *) b->yy_ch_buf ,yyscanner );
+		yyfree( (void *) b->yy_ch_buf , yyscanner );
 
-	pcap_free((void *) b ,yyscanner );
+	yyfree( (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.
+ * such as during a yyrestart() or at EOF.
  */
-    static void pcap__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
 
 {
 	int oerrno = errno;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-	pcap__flush_buffer(b ,yyscanner);
+	yy_flush_buffer( b , yyscanner);
 
 	b->yy_input_file = file;
 	b->yy_fill_buffer = 1;
 
-    /* If b is the current buffer, then pcap__init_buffer was _probably_
-     * called from pcap_restart() or through yy_get_next_buffer.
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
      * In that case, we don't want to reset the lineno or column.
      */
     if (b != YY_CURRENT_BUFFER){
@@ -4816,7 +4967,7 @@
  * @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 , yyscan_t yyscanner)
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if ( ! b )
@@ -4837,7 +4988,7 @@
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
 	if ( b == YY_CURRENT_BUFFER )
-		pcap__load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 }
 
 /** Pushes the new state onto the stack. The new state becomes
@@ -4846,15 +4997,15 @@
  *  @param new_buffer The new state.
  *  @param yyscanner The scanner object.
  */
-void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if (new_buffer == NULL)
 		return;
 
-	pcap_ensure_buffer_stack(yyscanner);
+	yyensure_buffer_stack(yyscanner);
 
-	/* This block is copied from pcap__switch_to_buffer. */
+	/* This block is copied from yy_switch_to_buffer. */
 	if ( YY_CURRENT_BUFFER )
 		{
 		/* Flush out information for old buffer. */
@@ -4868,8 +5019,8 @@
 		yyg->yy_buffer_stack_top++;
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
-	/* copied from pcap__switch_to_buffer. */
-	pcap__load_buffer_state(yyscanner );
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( yyscanner );
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
@@ -4877,19 +5028,19 @@
  *  The next element becomes the new top.
  *  @param yyscanner The scanner object.
  */
-void pcap_pop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if (!YY_CURRENT_BUFFER)
 		return;
 
-	pcap__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
 	YY_CURRENT_BUFFER_LVALUE = NULL;
 	if (yyg->yy_buffer_stack_top > 0)
 		--yyg->yy_buffer_stack_top;
 
 	if (YY_CURRENT_BUFFER) {
-		pcap__load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 		yyg->yy_did_buffer_switch_on_eof = 1;
 	}
 }
@@ -4897,9 +5048,9 @@
 /* Allocates the stack if it does not exist.
  *  Guarantees space for at least one push.
  */
-static void pcap_ensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
 {
-	int num_to_alloc;
+	yy_size_t num_to_alloc;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	if (!yyg->yy_buffer_stack) {
@@ -4909,11 +5060,11 @@
 		 * immediate realloc on the next call.
          */
       num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_alloc
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in pcap_ensure_buffer_stack()" );
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
 		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 
@@ -4928,12 +5079,12 @@
 		yy_size_t grow_size = 8 /* arbitrary grow size */;
 
 		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_realloc
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
 								(yyg->yy_buffer_stack,
 								num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in pcap_ensure_buffer_stack()" );
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
 		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -4947,7 +5098,7 @@
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE pcap__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
@@ -4957,11 +5108,11 @@
 		/* They forgot to leave room for the EOB's. */
 		return NULL;
 
-	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
 	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
 
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */
 	b->yy_buf_pos = b->yy_ch_buf = base;
 	b->yy_is_our_buffer = 0;
 	b->yy_input_file = NULL;
@@ -4971,33 +5122,33 @@
 	b->yy_fill_buffer = 0;
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
-	pcap__switch_to_buffer(b ,yyscanner );
+	yy_switch_to_buffer( b , yyscanner );
 
 	return b;
 }
 
-/** Setup the input buffer state to scan a string. The next call to pcap_lex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() 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_scan_bytes() instead.
  */
-YY_BUFFER_STATE pcap__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
 {
     
-	return pcap__scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+	return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
 }
 
-/** Setup the input buffer state to scan the given bytes. The next call to pcap_lex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() 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, int  _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
 	char *buf;
@@ -5006,18 +5157,18 @@
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = (yy_size_t) (_yybytes_len + 2);
-	buf = (char *) pcap_alloc(n ,yyscanner );
+	buf = (char *) yyalloc( n , yyscanner );
 	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_bytes()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
 
 	for ( i = 0; i < _yybytes_len; ++i )
 		buf[i] = yybytes[i];
 
 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
-	b = pcap__scan_buffer(buf,n ,yyscanner);
+	b = yy_scan_buffer( buf, n , yyscanner);
 	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in pcap__scan_bytes()" );
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
 
 	/* It's okay to grow etc. this buffer, and we should throw it
 	 * away when we're done.
@@ -5031,11 +5182,11 @@
 #define YY_EXIT_FAILURE 2
 #endif
 
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
-	(void) fprintf( stderr, "%s\n", msg );
+	fprintf( stderr, "%s\n", msg );
 	exit( YY_EXIT_FAILURE );
 }
 
@@ -5061,7 +5212,7 @@
 /** Get the user-defined data for this scanner.
  * @param yyscanner The scanner object.
  */
-YY_EXTRA_TYPE pcap_get_extra  (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyextra;
@@ -5070,7 +5221,7 @@
 /** Get the current line number.
  * @param yyscanner The scanner object.
  */
-int pcap_get_lineno  (yyscan_t yyscanner)
+int yyget_lineno  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -5083,7 +5234,7 @@
 /** Get the current column number.
  * @param yyscanner The scanner object.
  */
-int pcap_get_column  (yyscan_t yyscanner)
+int yyget_column  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -5096,7 +5247,7 @@
 /** Get the input stream.
  * @param yyscanner The scanner object.
  */
-FILE *pcap_get_in  (yyscan_t yyscanner)
+FILE *yyget_in  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyin;
@@ -5105,7 +5256,7 @@
 /** Get the output stream.
  * @param yyscanner The scanner object.
  */
-FILE *pcap_get_out  (yyscan_t yyscanner)
+FILE *yyget_out  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyout;
@@ -5114,7 +5265,7 @@
 /** Get the length of the current token.
  * @param yyscanner The scanner object.
  */
-int pcap_get_leng  (yyscan_t yyscanner)
+int yyget_leng  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyleng;
@@ -5124,7 +5275,7 @@
  * @param yyscanner The scanner object.
  */
 
-char *pcap_get_text  (yyscan_t yyscanner)
+char *yyget_text  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yytext;
@@ -5134,7 +5285,7 @@
  * @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)
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yyextra = user_defined ;
@@ -5144,13 +5295,13 @@
  * @param _line_number line number
  * @param yyscanner The scanner object.
  */
-void pcap_set_lineno (int  _line_number , yyscan_t yyscanner)
+void yyset_lineno (int  _line_number , yyscan_t yyscanner)
 {
     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" );
+           YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
     
     yylineno = _line_number;
 }
@@ -5159,13 +5310,13 @@
  * @param _column_no column number
  * @param yyscanner The scanner object.
  */
-void pcap_set_column (int  _column_no , yyscan_t yyscanner)
+void yyset_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" );
+           YY_FATAL_ERROR( "yyset_column called with no buffer" );
     
     yycolumn = _column_no;
 }
@@ -5174,27 +5325,27 @@
  * input buffer.
  * @param _in_str A readable stream.
  * @param yyscanner The scanner object.
- * @see pcap__switch_to_buffer
+ * @see yy_switch_to_buffer
  */
-void pcap_set_in (FILE *  _in_str , yyscan_t yyscanner)
+void yyset_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)
+void yyset_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)
+int yyget_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)
+void yyset_debug (int  _bdebug , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yy_flex_debug = _bdebug ;
@@ -5202,13 +5353,13 @@
 
 /* Accessor methods for yylval and yylloc */
 
-YYSTYPE * pcap_get_lval  (yyscan_t yyscanner)
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yylval;
 }
 
-void pcap_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yylval = yylval_param;
@@ -5216,20 +5367,18 @@
 
 /* User-visible API */
 
-/* pcap_lex_init is special because it creates the scanner itself, so it is
+/* yylex_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)
-
+int yylex_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 );
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
 
     if (*ptr_yy_globals == NULL){
         errno = ENOMEM;
@@ -5242,27 +5391,25 @@
     return yy_init_globals ( *ptr_yy_globals );
 }
 
-/* pcap_lex_init_extra has the same functionality as pcap_lex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_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 user defined value in the first argument will be available to yyalloc in
  * the yyextra field.
  */
-
-int pcap_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_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);
+    yyset_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 );
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
 
     if (*ptr_yy_globals == NULL){
         errno = ENOMEM;
@@ -5273,7 +5420,7 @@
     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);
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
 
     return yy_init_globals ( *ptr_yy_globals );
 }
@@ -5282,7 +5429,7 @@
 {
     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.
+     * This function is called from yylex_destroy(), so don't allocate here.
      */
 
     yyg->yy_buffer_stack = NULL;
@@ -5306,37 +5453,37 @@
 #endif
 
     /* For future reference: Set errno on error, since we are called by
-     * pcap_lex_init()
+     * yylex_init()
      */
     return 0;
 }
 
-/* pcap_lex_destroy is for both reentrant and non-reentrant scanners. */
-int pcap_lex_destroy  (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_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 ,yyscanner );
+		yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
 		YY_CURRENT_BUFFER_LVALUE = NULL;
-		pcap_pop_buffer_state(yyscanner);
+		yypop_buffer_state(yyscanner);
 	}
 
 	/* Destroy the stack itself. */
-	pcap_free(yyg->yy_buffer_stack ,yyscanner);
+	yyfree(yyg->yy_buffer_stack , yyscanner);
 	yyg->yy_buffer_stack = NULL;
 
     /* Destroy the start condition stack. */
-        pcap_free(yyg->yy_start_stack ,yyscanner );
+        yyfree( 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. */
+     * yylex() is called, initialization will occur. */
     yy_init_globals( yyscanner);
 
     /* Destroy the main struct (reentrant only). */
-    pcap_free ( yyscanner , yyscanner );
+    yyfree ( yyscanner , yyscanner );
     yyscanner = NULL;
     return 0;
 }
@@ -5346,7 +5493,7 @@
  */
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
@@ -5358,7 +5505,7 @@
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
 {
 	int n;
 	for ( n = 0; s[n]; ++n )
@@ -5368,14 +5515,14 @@
 }
 #endif
 
-void *pcap_alloc (yy_size_t  size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
 	return malloc(size);
 }
 
-void *pcap_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
@@ -5390,17 +5537,16 @@
 	return realloc(ptr, size);
 }
 
-void pcap_free (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
-	free( (char *) ptr );	/* see pcap_realloc() for (char *) cast */
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
 }
 
 #define YYTABLES_NAME "yytables"
 
-#line 490 "scanner.l"
-
+#line 479 "scanner.l"
 
 
 /*
diff --git a/scanner.h b/scanner.h
index dc464bd..8efc470 100644
--- a/scanner.h
+++ b/scanner.h
@@ -39,11 +39,233 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
 
+#ifdef yy_create_buffer
+#define pcap__create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer pcap__create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define pcap__delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer pcap__delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define pcap__scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer pcap__scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define pcap__scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string pcap__scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define pcap__scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes pcap__scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define pcap__init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer pcap__init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define pcap__flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer pcap__flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define pcap__load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state pcap__load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define pcap__switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer pcap__switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define pcap_push_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state pcap_push_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define pcap_pop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state pcap_pop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define pcap_ensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack pcap_ensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define pcap_lex_ALREADY_DEFINED
+#else
+#define yylex pcap_lex
+#endif
+
+#ifdef yyrestart
+#define pcap_restart_ALREADY_DEFINED
+#else
+#define yyrestart pcap_restart
+#endif
+
+#ifdef yylex_init
+#define pcap_lex_init_ALREADY_DEFINED
+#else
+#define yylex_init pcap_lex_init
+#endif
+
+#ifdef yylex_init_extra
+#define pcap_lex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra pcap_lex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define pcap_lex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy pcap_lex_destroy
+#endif
+
+#ifdef yyget_debug
+#define pcap_get_debug_ALREADY_DEFINED
+#else
+#define yyget_debug pcap_get_debug
+#endif
+
+#ifdef yyset_debug
+#define pcap_set_debug_ALREADY_DEFINED
+#else
+#define yyset_debug pcap_set_debug
+#endif
+
+#ifdef yyget_extra
+#define pcap_get_extra_ALREADY_DEFINED
+#else
+#define yyget_extra pcap_get_extra
+#endif
+
+#ifdef yyset_extra
+#define pcap_set_extra_ALREADY_DEFINED
+#else
+#define yyset_extra pcap_set_extra
+#endif
+
+#ifdef yyget_in
+#define pcap_get_in_ALREADY_DEFINED
+#else
+#define yyget_in pcap_get_in
+#endif
+
+#ifdef yyset_in
+#define pcap_set_in_ALREADY_DEFINED
+#else
+#define yyset_in pcap_set_in
+#endif
+
+#ifdef yyget_out
+#define pcap_get_out_ALREADY_DEFINED
+#else
+#define yyget_out pcap_get_out
+#endif
+
+#ifdef yyset_out
+#define pcap_set_out_ALREADY_DEFINED
+#else
+#define yyset_out pcap_set_out
+#endif
+
+#ifdef yyget_leng
+#define pcap_get_leng_ALREADY_DEFINED
+#else
+#define yyget_leng pcap_get_leng
+#endif
+
+#ifdef yyget_text
+#define pcap_get_text_ALREADY_DEFINED
+#else
+#define yyget_text pcap_get_text
+#endif
+
+#ifdef yyget_lineno
+#define pcap_get_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno pcap_get_lineno
+#endif
+
+#ifdef yyset_lineno
+#define pcap_set_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno pcap_set_lineno
+#endif
+
+#ifdef yyget_column
+#define pcap_get_column_ALREADY_DEFINED
+#else
+#define yyget_column pcap_get_column
+#endif
+
+#ifdef yyset_column
+#define pcap_set_column_ALREADY_DEFINED
+#else
+#define yyset_column pcap_set_column
+#endif
+
+#ifdef yywrap
+#define pcap_wrap_ALREADY_DEFINED
+#else
+#define yywrap pcap_wrap
+#endif
+
+#ifdef yyget_lval
+#define pcap_get_lval_ALREADY_DEFINED
+#else
+#define yyget_lval pcap_get_lval
+#endif
+
+#ifdef yyset_lval
+#define pcap_set_lval_ALREADY_DEFINED
+#else
+#define yyset_lval pcap_set_lval
+#endif
+
+#ifdef yyalloc
+#define pcap_alloc_ALREADY_DEFINED
+#else
+#define yyalloc pcap_alloc
+#endif
+
+#ifdef yyrealloc
+#define pcap_realloc_ALREADY_DEFINED
+#else
+#define yyrealloc pcap_realloc
+#endif
+
+#ifdef yyfree
+#define pcap_free_ALREADY_DEFINED
+#else
+#define yyfree pcap_free
+#endif
+
 /* First, we deal with  platform-specific or compiler-specific issues. */
 
 /* begin standard C headers. */
@@ -114,10 +336,16 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
 #endif /* ! C99 */
 
 #endif /* ! FLEXINT_H */
 
+/* begin standard C++ headers. */
+
 /* TODO: this is always defined, so inline it */
 #define yyconst const
 
@@ -218,21 +446,21 @@
 	};
 #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 );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_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,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
 
-void *pcap_alloc (yy_size_t ,yyscan_t yyscanner );
-void *pcap_realloc (void *,yy_size_t ,yyscan_t yyscanner );
-void pcap_free (void * ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
 
 /* Begin user sect3 */
 
@@ -256,46 +484,46 @@
 
 #define YY_EXTRA_TYPE compiler_state_t *
 
-int pcap_lex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
 
-int pcap_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_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 yylex_destroy ( yyscan_t yyscanner );
 
-int pcap_get_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
 
-void pcap_set_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
 
-YY_EXTRA_TYPE pcap_get_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
 
-void pcap_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
 
-FILE *pcap_get_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
 
-void pcap_set_in  (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in  ( FILE * _in_str , yyscan_t yyscanner );
 
-FILE *pcap_get_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
 
-void pcap_set_out  (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out  ( FILE * _out_str , yyscan_t yyscanner );
 
-			int pcap_get_leng (yyscan_t yyscanner );
+			int yyget_leng ( yyscan_t yyscanner );
 
-char *pcap_get_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
 
-int pcap_get_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
 
-void pcap_set_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
 
-int pcap_get_column  (yyscan_t yyscanner );
+int yyget_column  ( yyscan_t yyscanner );
 
-void pcap_set_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
 
-YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
+YYSTYPE * yyget_lval ( yyscan_t yyscanner );
 
-void pcap_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -303,18 +531,18 @@
 
 #ifndef YY_SKIP_YYWRAP
 #ifdef __cplusplus
-extern "C" int pcap_wrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
 #else
-extern int pcap_wrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
 #endif
 #endif
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
 #endif
 
 #ifndef YY_NO_INPUT
@@ -342,10 +570,10 @@
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int pcap_lex \
-               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+extern int yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner);
 
-#define YY_DECL int pcap_lex \
+#define YY_DECL int yylex \
                (YYSTYPE * yylval_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
@@ -363,9 +591,154 @@
 #undef YY_DECL
 #endif
 
-#line 490 "scanner.l"
+#ifndef pcap__create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef pcap__delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef pcap__scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef pcap__scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef pcap__scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef pcap__init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef pcap__flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef pcap__load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef pcap__switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef pcap_push_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef pcap_pop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef pcap_ensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef pcap_lex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef pcap_restart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef pcap_lex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef pcap_lex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef pcap_lex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef pcap_get_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef pcap_set_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef pcap_get_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef pcap_set_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef pcap_get_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef pcap_set_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef pcap_get_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef pcap_set_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef pcap_get_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef pcap_get_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef pcap_get_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef pcap_set_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef pcap_get_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef pcap_set_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef pcap_wrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef pcap_get_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef pcap_set_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef pcap_get_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef pcap_set_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef pcap_alloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef pcap_realloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef pcap_free_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef pcap_text_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef pcap_leng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef pcap_in_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef pcap_out_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef pcap__flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef pcap_lineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef pcap_tables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef pcap_tables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef pcap_TABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
+
+#line 479 "scanner.l"
 
 
-#line 370 "scanner.h"
+#line 743 "scanner.h"
 #undef pcap_IN_HEADER
 #endif /* pcap_HEADER_H */
diff --git a/scanner.l b/scanner.l
index e0890b4..06b9acc 100644
--- a/scanner.l
+++ b/scanner.l
@@ -85,7 +85,6 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#include <ctype.h>
 #include <string.h>
 
 #include "pcap-int.h"
@@ -147,8 +146,7 @@
 #include "os-proto.h"
 #endif
 
-static int stoi(char *);
-static inline int xdtoi(int);
+static int stou(char *, YYSTYPE *, compiler_state_t *);
 
 /*
  * Disable diagnostics in the code generated by Flex.
@@ -311,13 +309,7 @@
 port		return PORT;
 portrange	return PORTRANGE;
 proto		return PROTO;
-protochain	{
-#ifdef NO_PROTOCHAIN
-		  bpf_error(yyextra, "%s not supported", yytext);
-#else
-		  return PROTOCHAIN;
-#endif
-		}
+protochain	return PROTOCHAIN;
 
 gateway		return GATEWAY;
 
@@ -345,6 +337,8 @@
 inbound		return INBOUND;
 outbound	return OUTBOUND;
 
+ifindex		return IFINDEX;
+
 vlan		return VLAN;
 mpls		return MPLS;
 pppoed		return PPPOED;
@@ -397,15 +391,9 @@
 "=="			return '=';
 "<<"			return LSH;
 ">>"			return RSH;
-${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(yyextra, "malloc");
-			  return EID; }
-{N}			{ yylval->i = stoi((char *)yytext); return NUM; }
+${B}			{ yylval->s = sdup(yyextra, yytext); return AID; }
+{MAC}			{ yylval->s = sdup(yyextra, yytext); return EID; }
+{N}			{ return stou(yytext, yylval, yyextra); }
 ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})	{
 			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 {V6}			{
@@ -414,79 +402,84 @@
 			  memset(&hints, 0, sizeof(hints));
 			  hints.ai_family = AF_INET6;
 			  hints.ai_flags = AI_NUMERICHOST;
-			  if (getaddrinfo(yytext, NULL, &hints, &res))
-				bpf_error(yyextra, "bogus IPv6 address %s", yytext);
-			  else {
+			  if (getaddrinfo(yytext, NULL, &hints, &res)) {
+				bpf_set_error(yyextra, "bogus IPv6 address %s", yytext);
+				yylval->s = NULL;
+			  } else {
 				freeaddrinfo(res);
-				yylval->s = sdup(yyextra, (char *)yytext); return HID6;
+				yylval->s = sdup(yyextra, (char *)yytext);
 			  }
 #else
-			  bpf_error(yyextra, "IPv6 address %s not supported", yytext);
+			  bpf_set_error(yyextra, "IPv6 address %s not supported", yytext);
+			  yylval->s = NULL;
 #endif /*INET6*/
+			  return HID6;
 			}
-{B}:+({B}:+)+		{ bpf_error(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; }
+{B}:+({B}:+)+		{ bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; }
+icmptype		{ yylval->h = 0; return NUM; }
+icmpcode		{ yylval->h = 1; return NUM; }
+icmp-echoreply		{ yylval->h = 0; return NUM; }
+icmp-unreach		{ yylval->h = 3; return NUM; }
+icmp-sourcequench	{ yylval->h = 4; return NUM; }
+icmp-redirect		{ yylval->h = 5; return NUM; }
+icmp-echo		{ yylval->h = 8; return NUM; }
+icmp-routeradvert	{ yylval->h = 9; return NUM; }
+icmp-routersolicit	{ yylval->h = 10; return NUM; }
+icmp-timxceed		{ yylval->h = 11; return NUM; }
+icmp-paramprob		{ yylval->h = 12; return NUM; }
+icmp-tstamp		{ yylval->h = 13; return NUM; }
+icmp-tstampreply	{ yylval->h = 14; return NUM; }
+icmp-ireq		{ yylval->h = 15; return NUM; }
+icmp-ireqreply		{ yylval->h = 16; return NUM; }
+icmp-maskreq		{ yylval->h = 17; return NUM; }
+icmp-maskreply		{ yylval->h = 18; return NUM; }
 
-icmp6type       { yylval->i = 0; return NUM; }
-icmp6code       { yylval->i = 1; return NUM; }
+icmp6type       { yylval->h = 0; return NUM; }
+icmp6code       { yylval->h = 1; return NUM; }
 
-icmp6-echo      { yylval->i = 128; return NUM; }
-icmp6-echoreply { yylval->i = 129; return NUM; }
-icmp6-multicastlistenerquery    { yylval->i = 130; return NUM; }
-icmp6-multicastlistenerreportv1 { yylval->i = 131; return NUM; }
-icmp6-multicastlistenerdone     { yylval->i = 132; return NUM; }
-icmp6-routersolicit   { yylval->i = 133; return NUM; }
-icmp6-routeradvert    { yylval->i = 134; return NUM; }
-icmp6-neighborsolicit { yylval->i = 135; return NUM; }
-icmp6-neighboradvert  { yylval->i = 136; return NUM; }
-icmp6-redirect    { yylval->i = 137; return NUM; }
-icmp6-routerrenum { yylval->i = 138; return NUM; }
-icmp6-nodeinformationquery      { yylval->i = 139; return NUM; }
-icmp6-nodeinformationresponse   { yylval->i = 140; return NUM; }
-icmp6-ineighbordiscoverysolicit { yylval->i = 141; return NUM; }
-icmp6-ineighbordiscoveryadvert  { yylval->i = 142; return NUM; }
-icmp6-multicastlistenerreportv2 { yylval->i = 143; return NUM; }
-icmp6-homeagentdiscoveryrequest { yylval->i = 144; return NUM; }
-icmp6-homeagentdiscoveryreply   { yylval->i = 145; return NUM; }
-icmp6-mobileprefixsolicit       { yylval->i = 146; return NUM; }
-icmp6-mobileprefixadvert        { yylval->i = 147; return NUM; }
-icmp6-certpathsolicit           { yylval->i = 148; return NUM; }
-icmp6-certpathadvert            { yylval->i = 149; return NUM; }
-icmp6-multicastrouteradvert     { yylval->i = 151; return NUM; }
-icmp6-multicastroutersolicit    { yylval->i = 152; return NUM; }
-icmp6-multicastrouterterm       { yylval->i = 153; return NUM; }
+icmp6-destinationunreach	{ yylval->h = 1; return NUM; }
+icmp6-packettoobig		{ yylval->h = 2; return NUM; }
+icmp6-timeexceeded		{ yylval->h = 3; return NUM; }
+icmp6-parameterproblem		{ yylval->h = 4; return NUM; }
+icmp6-echo      { yylval->h = 128; return NUM; }
+icmp6-echoreply { yylval->h = 129; return NUM; }
+icmp6-multicastlistenerquery    { yylval->h = 130; return NUM; }
+icmp6-multicastlistenerreportv1 { yylval->h = 131; return NUM; }
+icmp6-multicastlistenerdone     { yylval->h = 132; return NUM; }
+icmp6-routersolicit   { yylval->h = 133; return NUM; }
+icmp6-routeradvert    { yylval->h = 134; return NUM; }
+icmp6-neighborsolicit { yylval->h = 135; return NUM; }
+icmp6-neighboradvert  { yylval->h = 136; return NUM; }
+icmp6-redirect    { yylval->h = 137; return NUM; }
+icmp6-routerrenum { yylval->h = 138; return NUM; }
+icmp6-nodeinformationquery      { yylval->h = 139; return NUM; }
+icmp6-nodeinformationresponse   { yylval->h = 140; return NUM; }
+icmp6-ineighbordiscoverysolicit { yylval->h = 141; return NUM; }
+icmp6-ineighbordiscoveryadvert  { yylval->h = 142; return NUM; }
+icmp6-multicastlistenerreportv2 { yylval->h = 143; return NUM; }
+icmp6-homeagentdiscoveryrequest { yylval->h = 144; return NUM; }
+icmp6-homeagentdiscoveryreply   { yylval->h = 145; return NUM; }
+icmp6-mobileprefixsolicit       { yylval->h = 146; return NUM; }
+icmp6-mobileprefixadvert        { yylval->h = 147; return NUM; }
+icmp6-certpathsolicit           { yylval->h = 148; return NUM; }
+icmp6-certpathadvert            { yylval->h = 149; return NUM; }
+icmp6-multicastrouteradvert     { yylval->h = 151; return NUM; }
+icmp6-multicastroutersolicit    { yylval->h = 152; return NUM; }
+icmp6-multicastrouterterm       { yylval->h = 153; return NUM; }
 
-tcpflags		{ yylval->i = 13; return NUM; }
-tcp-fin			{ yylval->i = 0x01; return NUM; }
-tcp-syn			{ yylval->i = 0x02; return NUM; }
-tcp-rst			{ yylval->i = 0x04; return NUM; }
-tcp-push		{ yylval->i = 0x08; return NUM; }
-tcp-ack			{ yylval->i = 0x10; return NUM; }
-tcp-urg			{ yylval->i = 0x20; return NUM; }
-tcp-ece			{ yylval->i = 0x40; return NUM; }
-tcp-cwr			{ yylval->i = 0x80; return NUM; }
+tcpflags		{ yylval->h = 13; return NUM; }
+tcp-fin			{ yylval->h = 0x01; return NUM; }
+tcp-syn			{ yylval->h = 0x02; return NUM; }
+tcp-rst			{ yylval->h = 0x04; return NUM; }
+tcp-push		{ yylval->h = 0x08; return NUM; }
+tcp-ack			{ yylval->h = 0x10; return NUM; }
+tcp-urg			{ yylval->h = 0x20; return NUM; }
+tcp-ece			{ yylval->h = 0x40; return NUM; }
+tcp-cwr			{ yylval->h = 0x80; return NUM; }
 [A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
 			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
 "\\"[^ !()\n\t]+	{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
-[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
-			bpf_error(yyextra, "illegal token: %s", yytext); }
-.			{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
+.			{ return LEX_ERROR; }
 %%
 
 /*
@@ -494,40 +487,110 @@
  */
 DIAG_ON_FLEX
 
-/* Hex digit to integer. */
-static inline int
-xdtoi(int c)
-{
-	if (isdigit(c))
-		return c - '0';
-	else if (islower(c))
-		return c - 'a' + 10;
-	else
-		return c - 'A' + 10;
-}
-
 /*
- * Convert string to integer.  Just like atoi(), but checks for
+ * Convert string to 32-bit unsigned integer.  Just like atoi(), but checks for
  * preceding 0x or 0 and uses hex or octal instead of decimal.
+ *
+ * On success, sets yylval->h to the value and returns NUM.
+ * On failure, sets the BPF error string and returns LEX_ERROR, to force
+ * the parse to stop.
  */
 static int
-stoi(char *s)
+stou(char *yytext_arg, YYSTYPE *yylval_arg, compiler_state_t *yyextra_arg)
 {
-	int base = 10;
-	int n = 0;
+	bpf_u_int32 n = 0;
+	unsigned int digit;
+	char *s = yytext_arg;
 
+	/*
+	 * yytext_arg is guaranteed either to be a string of decimal digits
+	 * or 0[xX] followed by a string of hex digits.
+	 */
 	if (*s == '0') {
 		if (s[1] == 'x' || s[1] == 'X') {
-			s += 2;
-			base = 16;
-		}
-		else {
-			base = 8;
+			/*
+			 * Begins with 0x or 0X, so hex.
+			 * Guaranteed to be all hex digits following the
+			 * prefix, so anything that's not 0-9 or a-f is
+			 * A-F.
+			 */
+			s += 2;	/* skip the prefix */
+			while ((digit = *s++) != '\0') {
+				if (digit >= '0' && digit <= '9')
+					digit = digit - '0';
+				else if (digit >= 'a' && digit <= 'f')
+					digit = digit - 'a' + 10;
+				else
+					digit = digit - 'A' + 10;
+
+				/*
+				 * Check for overflow.
+				 */
+				if (n > 0xFFFFFFFU) {
+					/*
+					 * We have more than 28 bits of
+					 * number, and are about to
+					 * add 4 more; that won't fit
+					 * in 32 bits.
+					 */
+					bpf_set_error(yyextra_arg,
+					    "number %s overflows 32 bits",
+					    yytext_arg);
+					return LEX_ERROR;
+				}
+				n = (n << 4) + digit;
+			}
+		} else {
+			/*
+			 * Begins with 0, but not 0x or 0X, so octal.
+			 * Guaranteed to be all *decimal* digits following
+			 * the prefix, so we need to catch 8 and 9 and
+			 * report an error.
+			 */
 			s += 1;
+			while ((digit = *s++) != '\0') {
+				if (digit >= '0' && digit <= '7')
+					digit = digit - '0';
+				else {
+					bpf_set_error(yyextra_arg,
+					    "number %s contains non-octal digit",
+					    yytext_arg);
+					return LEX_ERROR;
+				}
+				if (n > 03777777777U) {
+					/*
+					 * We have more than 29 bits of
+					 * number, and are about to add
+					 * 3 more; that won't fit in
+					 * 32 bits.
+					 */
+					bpf_set_error(yyextra_arg,
+					    "number %s overflows 32 bits",
+					    yytext_arg);
+					return LEX_ERROR;
+				}
+				n = (n << 3) + digit;
+			}
+		}
+	} else {
+		/*
+		 * Decimal.
+		 */
+		while ((digit = *s++) != '\0') {
+			digit = digit - '0';
+#define CUTOFF_DEC	(0xFFFFFFFFU / 10U)
+#define CUTLIM_DEC	(0xFFFFFFFFU % 10U)
+			if (n > CUTOFF_DEC ||
+			    (n == CUTOFF_DEC && digit > CUTLIM_DEC)) {
+				bpf_set_error(yyextra_arg,
+				    "number %s overflows 32 bits",
+				    yytext_arg);
+				return LEX_ERROR;
+			}
+			n = (n * 10) + digit;
 		}
 	}
-	while (*s)
-		n = n * base + xdtoi(*s++);
 
-	return n;
+	yylval_arg->h = n;
+	return NUM;
 }
diff --git a/sf-pcap.c b/sf-pcap.c
index 96cb308..d8443e9 100644
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -43,6 +43,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h> /* for INT_MAX */
 
 #include "pcap-int.h"
 
@@ -109,6 +110,20 @@
 
 static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
 
+#ifdef _WIN32
+/*
+ * This isn't exported on Windows, because it would only work if both
+ * libpcap and the code using it were using the same C runtime; otherwise they
+ * would be using different definitions of a FILE structure.
+ *
+ * Instead we define this as a macro in pcap/pcap.h that wraps the hopen
+ * version that we do export, passing it a raw OS HANDLE, as defined by the
+ * Win32 / Win64 ABI, obtained from the _fileno() and _get_osfhandle()
+ * functions of the appropriate CRT.
+ */
+static pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f);
+#endif /* _WIN32 */
+
 /*
  * Private data for reading pcap savefiles.
  */
@@ -135,9 +150,10 @@
  * relevant information from the header.
  */
 pcap_t *
-pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
+pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
 		  int *err)
 {
+	bpf_u_int32 magic_int;
 	struct pcap_file_header hdr;
 	size_t amt_read;
 	pcap_t *p;
@@ -154,11 +170,14 @@
 	 * number for a pcap savefile, or for a byte-swapped pcap
 	 * savefile.
 	 */
-	if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
-	    magic != NSEC_TCPDUMP_MAGIC) {
-		magic = SWAPLONG(magic);
-		if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
-		    magic != NSEC_TCPDUMP_MAGIC)
+	memcpy(&magic_int, magic, sizeof(magic_int));
+	if (magic_int != TCPDUMP_MAGIC &&
+	    magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+	    magic_int != NSEC_TCPDUMP_MAGIC) {
+		magic_int = SWAPLONG(magic_int);
+		if (magic_int != TCPDUMP_MAGIC &&
+		    magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+		    magic_int != NSEC_TCPDUMP_MAGIC)
 			return (NULL);	/* nope */
 		swapped = 1;
 	}
@@ -167,7 +186,7 @@
 	 * They are.  Put the magic number in the header, and read
 	 * the rest of the header.
 	 */
-	hdr.magic = magic;
+	hdr.magic = magic_int;
 	amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
 	    sizeof(hdr) - sizeof(hdr.magic), fp);
 	if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
@@ -175,10 +194,9 @@
 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "error reading dump file");
 		} else {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
-			    (unsigned long)sizeof(hdr),
-			    (unsigned long)amt_read);
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "truncated dump file; tried to read %zu file header bytes, only got %zu",
+			    sizeof(hdr), amt_read);
 		}
 		*err = 1;
 		return (NULL);
@@ -197,7 +215,7 @@
 	}
 
 	if (hdr.version_major < PCAP_VERSION_MAJOR) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "archaic pcap savefile format");
 		*err = 1;
 		return (NULL);
@@ -211,7 +229,7 @@
 		hdr.version_minor <= PCAP_VERSION_MINOR) ||
 	       (hdr.version_major == 543 &&
 		hdr.version_minor == 0))) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			 "unsupported pcap savefile version %u.%u",
 			 hdr.version_major, hdr.version_minor);
 		*err = 1;
@@ -222,7 +240,7 @@
 	 * OK, this is a good pcap file.
 	 * Allocate a pcap_t for it.
 	 */
-	p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
+	p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_sf);
 	if (p == NULL) {
 		/* Allocation failed. */
 		*err = 1;
@@ -231,21 +249,9 @@
 	p->swapped = swapped;
 	p->version_major = hdr.version_major;
 	p->version_minor = hdr.version_minor;
-	p->tzoff = hdr.thiszone;
-	p->snapshot = hdr.snaplen;
-	if (p->snapshot <= 0) {
-		/*
-		 * Bogus snapshot length; use the maximum for this
-		 * link-layer type as a fallback.
-		 *
-		 * XXX - the only reason why snapshot is signed is
-		 * that pcap_snapshot() returns an int, not an
-		 * unsigned int.
-		 */
-		p->snapshot = max_snaplen_for_dlt(hdr.linktype);
-	}
 	p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
 	p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
+	p->snapshot = pcap_adjust_snapshot(p->linktype, hdr.snaplen);
 
 	p->next_packet_op = pcap_next_packet;
 
@@ -260,7 +266,7 @@
 	switch (precision) {
 
 	case PCAP_TSTAMP_PRECISION_MICRO:
-		if (magic == NSEC_TCPDUMP_MAGIC) {
+		if (magic_int == NSEC_TCPDUMP_MAGIC) {
 			/*
 			 * The file has nanoseconds, the user
 			 * wants microseconds; scale the
@@ -277,7 +283,7 @@
 		break;
 
 	case PCAP_TSTAMP_PRECISION_NANO:
-		if (magic == NSEC_TCPDUMP_MAGIC) {
+		if (magic_int == NSEC_TCPDUMP_MAGIC) {
 			/*
 			 * The file has nanoseconds, the
 			 * user wants nanoseconds; nothing to do.
@@ -285,7 +291,7 @@
 			ps->scale_type = PASS_THROUGH;
 		} else {
 			/*
-			 * The file has microoseconds, the user
+			 * The file has microseconds, the user
 			 * wants nanoseconds; scale the
 			 * precision up.
 			 */
@@ -294,7 +300,7 @@
 		break;
 
 	default:
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown time stamp resolution %u", precision);
 		free(p);
 		*err = 1;
@@ -331,7 +337,7 @@
 		break;
 	}
 
-	if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
+	if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) {
 		/*
 		 * XXX - the patch that's in some versions of libpcap
 		 * changes the packet header but not the magic number,
@@ -371,8 +377,14 @@
 			 * length will be misleading if you use it to figure
 			 * out why a capture doesn't have all the packet data,
 			 * but there's not much we can do to avoid that.
+			 *
+			 * But don't grow the snapshot length past the
+			 * maximum value of an int.
 			 */
-			p->snapshot += 14;
+			if (p->snapshot <= INT_MAX - 14)
+				p->snapshot += 14;
+			else
+				p->snapshot = INT_MAX;
 		}
 	} else
 		ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
@@ -391,7 +403,7 @@
 		p->bufsize = 2048;
 	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 		free(p);
 		*err = 1;
 		return (NULL);
@@ -412,7 +424,7 @@
 
 	bigger_buffer = realloc(p->buffer, bufsize);
 	if (bigger_buffer == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 		return (0);
 	}
 	p->buffer = bigger_buffer;
@@ -449,10 +461,9 @@
 			return (-1);
 		} else {
 			if (amt_read != 0) {
-				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);
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "truncated dump file; tried to read %zu header bytes, only got %zu",
+				    ps->hdrsize, amt_read);
 				return (-1);
 			}
 			/* EOF */
@@ -534,11 +545,11 @@
 		 * below.)
 		 */
 		if (hdr->caplen > (bpf_u_int32)p->snapshot) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "invalid packet capture length %u, bigger than "
 			    "snaplen of %d", hdr->caplen, p->snapshot);
 		} else {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "invalid packet capture length %u, bigger than "
 			    "maximum of %u", hdr->caplen,
 			    max_snaplen_for_dlt(p->linktype));
@@ -610,9 +621,9 @@
 				 * 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",
-				    p->snapshot, (unsigned long)amt_read);
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "truncated dump file; tried to read %u captured bytes, only got %zu",
+				    p->snapshot, amt_read);
 			}
 			return (-1);
 		}
@@ -634,9 +645,9 @@
 					    PCAP_ERRBUF_SIZE, errno,
 					    "error reading dump file");
 				} else {
-					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-					    "truncated dump file; tried to read %u captured bytes, only got %lu",
-					    hdr->caplen, (unsigned long)bytes_read);
+					snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					    "truncated dump file; tried to read %u captured bytes, only got %zu",
+					    hdr->caplen, bytes_read);
 				}
 				return (-1);
 			}
@@ -649,6 +660,9 @@
 		 */
 		hdr->caplen = p->snapshot;
 	} else {
+		/*
+		 * The packet is within the snapshot length for this file.
+		 */
 		if (hdr->caplen > p->bufsize) {
 			/*
 			 * Grow the buffer to the next power of 2, or
@@ -658,7 +672,7 @@
 
 			new_bufsize = hdr->caplen;
 			/*
-			 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+			 * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
 			 */
 			new_bufsize--;
 			new_bufsize |= new_bufsize >> 1;
@@ -683,9 +697,9 @@
 				    PCAP_ERRBUF_SIZE, errno,
 				    "error reading dump file");
 			} else {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "truncated dump file; tried to read %u captured bytes, only got %lu",
-				    hdr->caplen, (unsigned long)amt_read);
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "truncated dump file; tried to read %u captured bytes, only got %zu",
+				    hdr->caplen, amt_read);
 			}
 			return (-1);
 		}
@@ -699,7 +713,7 @@
 }
 
 static int
-sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen)
+sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen)
 {
 	struct pcap_file_header hdr;
 
@@ -707,9 +721,15 @@
 	hdr.version_major = PCAP_VERSION_MAJOR;
 	hdr.version_minor = PCAP_VERSION_MINOR;
 
-	hdr.thiszone = thiszone;
-	hdr.snaplen = snaplen;
+	/*
+	 * https://www.tcpdump.org/manpages/pcap-savefile.5.txt states:
+	 * thiszone: 4-byte time zone offset; this is always 0.
+	 * sigfigs:  4-byte number giving the accuracy of time stamps
+	 *           in the file; this is always 0.
+	 */
+	hdr.thiszone = 0;
 	hdr.sigfigs = 0;
+	hdr.snaplen = snaplen;
 	hdr.linktype = linktype;
 
 	if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
@@ -728,8 +748,12 @@
 	struct pcap_sf_pkthdr sf_hdr;
 
 	f = (FILE *)user;
-	sf_hdr.ts.tv_sec  = h->ts.tv_sec;
-	sf_hdr.ts.tv_usec = h->ts.tv_usec;
+	/*
+	 * Better not try writing pcap files after
+	 * 2038-01-19 03:14:07 UTC; switch to pcapng.
+	 */
+	sf_hdr.ts.tv_sec  = (bpf_int32)h->ts.tv_sec;
+	sf_hdr.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
 	sf_hdr.caplen     = h->caplen;
 	sf_hdr.len        = h->len;
 	/* XXX we should check the return status */
@@ -754,7 +778,7 @@
 	else
 		setvbuf(f, NULL, _IONBF, 0);
 #endif
-	if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
+	if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "Can't write to %s", fname);
 		if (f != stdout)
@@ -778,14 +802,14 @@
 	 * link-layer type, so we can't use it.
 	 */
 	if (!p->activated) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		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) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: link-layer type %d isn't supported in savefiles",
 		    fname, p->linktype);
 		return (NULL);
@@ -793,7 +817,7 @@
 	linktype |= p->linktype_ext;
 
 	if (fname == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "A null pointer was supplied as the file name");
 		return NULL;
 	}
@@ -807,7 +831,7 @@
 		 * required on Windows, as the file is a binary file
 		 * and must be written in binary mode.
 		 */
-		f = fopen(fname, "wb");
+		f = charset_fopen(fname, "wb");
 		if (f == NULL) {
 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "%s", fname);
@@ -817,9 +841,42 @@
 	return (pcap_setup_dump(p, linktype, f, fname));
 }
 
+#ifdef _WIN32
+/*
+ * Initialize so that sf_write() will output to a stream wrapping the given raw
+ * OS file HANDLE.
+ */
+pcap_dumper_t *
+pcap_dump_hopen(pcap_t *p, intptr_t osfd)
+{
+	int fd;
+	FILE *file;
+
+	fd = _open_osfhandle(osfd, _O_APPEND);
+	if (fd < 0) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "_open_osfhandle");
+		return NULL;
+	}
+
+	file = _fdopen(fd, "wb");
+	if (file == NULL) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "_fdopen");
+		_close(fd);
+		return NULL;
+	}
+
+	return pcap_dump_fopen(p, file);
+}
+#endif /* _WIN32 */
+
 /*
  * Initialize so that sf_write() will output to the given stream.
  */
+#ifdef _WIN32
+static
+#endif /* _WIN32 */
 pcap_dumper_t *
 pcap_dump_fopen(pcap_t *p, FILE *f)
 {
@@ -827,7 +884,7 @@
 
 	linktype = dlt_to_linktype(p->linktype);
 	if (linktype == -1) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "stream: link-layer type %d isn't supported in savefiles",
 		    p->linktype);
 		return (NULL);
@@ -847,14 +904,14 @@
 
 	linktype = dlt_to_linktype(p->linktype);
 	if (linktype == -1) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		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,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "A null pointer was supplied as the file name");
 		return NULL;
 	}
@@ -862,11 +919,19 @@
 		return (pcap_setup_dump(p, linktype, stdout, "standard output"));
 
 	/*
+	 * "a" will cause the file *not* to be truncated if it exists
+	 * but will cause it to be created if it doesn't.  It will
+	 * also cause all writes to be done at the end of the file,
+	 * but will allow reads to be done anywhere in the file.  This
+	 * is what we need, because we need to read from the beginning
+	 * of the file to see if it already has a header and packets
+	 * or if it doesn't.
+	 *
 	 * "b" is supported as of C90, so *all* UN*Xes should support it,
 	 * even though it does nothing.  It's required on Windows, as the
 	 * file is a binary file and must be read in binary mode.
 	 */
-	f = fopen(fname, "rb+");
+	f = charset_fopen(fname, "ab+");
 	if (f == NULL) {
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 		    errno, "%s", fname);
@@ -875,18 +940,33 @@
 
 	/*
 	 * Try to read a pcap header.
+	 *
+	 * We do not assume that the file will be positioned at the
+	 * beginning immediately after we've opened it - we seek to
+	 * the beginning.  ISO C says it's implementation-defined
+	 * whether the file position indicator is at the beginning
+	 * or the end of the file after an append-mode open, and
+	 * it wasn't obvious from the Single UNIX Specification
+	 * or the Microsoft documentation how that works on SUS-
+	 * compliant systems or on Windows.
 	 */
+	if (fseek(f, 0, SEEK_SET) == -1) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "Can't seek to the beginning of %s", fname);
+		(void)fclose(f);
+		return (NULL);
+	}
 	amt_read = fread(&ph, 1, sizeof (ph), f);
 	if (amt_read != sizeof (ph)) {
 		if (ferror(f)) {
 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "%s", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		} else if (feof(f) && amt_read > 0) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: truncated pcap file header", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		}
 	}
@@ -920,42 +1000,42 @@
 
 		case TCPDUMP_MAGIC:
 			if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "%s: different time stamp precision, cannot append to file", fname);
-				fclose(f);
+				(void)fclose(f);
 				return (NULL);
 			}
 			break;
 
 		case NSEC_TCPDUMP_MAGIC:
 			if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "%s: different time stamp precision, cannot append to file", fname);
-				fclose(f);
+				(void)fclose(f);
 				return (NULL);
 			}
 			break;
 
 		case SWAPLONG(TCPDUMP_MAGIC):
 		case SWAPLONG(NSEC_TCPDUMP_MAGIC):
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different byte order, cannot append to file", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 
 		case KUZNETZOV_TCPDUMP_MAGIC:
 		case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
 		case NAVTEL_TCPDUMP_MAGIC:
 		case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: not a pcap file to which we can append", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 
 		default:
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: not a pcap file", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		}
 
@@ -964,29 +1044,29 @@
 		 */
 		if (ph.version_major != PCAP_VERSION_MAJOR ||
 		    ph.version_minor != PCAP_VERSION_MINOR) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: version is %u.%u, cannot append to file", fname,
 			    ph.version_major, ph.version_minor);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		}
 		if ((bpf_u_int32)linktype != ph.linktype) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different linktype, cannot append to file", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		}
 		if ((bpf_u_int32)p->snapshot != ph.snaplen) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different snaplen, cannot append to file", fname);
-			fclose(f);
+			(void)fclose(f);
 			return (NULL);
 		}
 	} else {
 		/*
 		 * A header isn't present; attempt to write it.
 		 */
-		if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
+		if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
 			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
 			    errno, "Can't write to %s", fname);
 			(void)fclose(f);
@@ -996,10 +1076,14 @@
 
 	/*
 	 * Start writing at the end of the file.
+	 *
+	 * XXX - this shouldn't be necessary, given that we're opening
+	 * the file in append mode, and ISO C specifies that all writes
+	 * are done at the end of the file in that mode.
 	 */
 	if (fseek(f, 0, SEEK_END) == -1) {
 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-		    errno, "Can't seek to end of %s", fname);
+		    errno, "Can't seek to the end of %s", fname);
 		(void)fclose(f);
 		return (NULL);
 	}
diff --git a/sf-pcap.h b/sf-pcap.h
index e9c7eaf..bc7150f 100644
--- a/sf-pcap.h
+++ b/sf-pcap.h
@@ -31,7 +31,7 @@
 #ifndef sf_pcap_h
 #define	sf_pcap_h
 
-extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp,
+extern pcap_t *pcap_check_header(const uint8_t *magic, FILE *fp,
     u_int precision, char *errbuf, int *err);
 
 #endif
diff --git a/sf-pcapng.c b/sf-pcapng.c
index 8c8e93e..f7f413d 100644
--- a/sf-pcapng.c
+++ b/sf-pcapng.c
@@ -85,7 +85,7 @@
  * Section Header Block.
  */
 #define BT_SHB			0x0A0D0D0A
-
+#define BT_SHB_INSANE_MAX       1024U*1024U*1U  /* 1MB should be enough */
 struct section_header_block {
 	bpf_u_int32	byte_order_magic;
 	u_short		major_version;
@@ -197,6 +197,7 @@
  * Per-interface information.
  */
 struct pcap_ng_if {
+	uint32_t snaplen;		/* snapshot length */
 	uint64_t tsresol;		/* time stamp resolution */
 	tstamp_scale_type_t scale_type;	/* how to scale */
 	uint64_t scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
@@ -231,16 +232,21 @@
 };
 
 /*
- * Maximum block size for a given maximum snapshot length; we calculate
- * this based
- *
- * We define it as the size of an EPB with a max_snaplen-sized
- * packet and 128KB of options.
+ * The maximum block size we start with; we use an arbitrary value of
+ * 16 MiB.
  */
-#define MAX_BLOCKSIZE(max_snaplen)	(sizeof (struct block_header) + \
-					 sizeof (struct enhanced_packet_block) + \
-					 (max_snaplen) + 131072 + \
-					 sizeof (struct block_trailer))
+#define INITIAL_MAX_BLOCKSIZE	(16*1024*1024)
+
+/*
+ * Maximum block size for a given maximum snapshot length; we define it
+ * as the size of an EPB with a max_snaplen-sized packet and 128KB of
+ * options.
+ */
+#define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
+	(sizeof (struct block_header) + \
+	 sizeof (struct enhanced_packet_block) + \
+	 (max_snaplen) + 131072 + \
+	 sizeof (struct block_trailer))
 
 static void pcap_ng_cleanup(pcap_t *p);
 static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
@@ -260,10 +266,9 @@
 		} else {
 			if (amt_read == 0 && !fail_on_eof)
 				return (0);	/* EOF */
-			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);
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "truncated pcapng dump file; tried to read %zu bytes, only got %zu",
+			    bytes_to_read, amt_read);
 		}
 		return (-1);
 	}
@@ -276,6 +281,7 @@
 	struct pcap_ng_sf *ps;
 	int status;
 	struct block_header bhdr;
+	struct block_trailer *btrlr;
 	u_char *bdata;
 	size_t data_remaining;
 
@@ -291,29 +297,28 @@
 	}
 
 	/*
-	 * Is this block "too big"?
-	 *
-	 * We choose 16MB as "too big", for now, so that we handle
-	 * "reasonably" large buffers but don't chew up all the
-	 * memory if we read a malformed file.
-	 */
-	if (bhdr.total_length > 16*1024*1024) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "pcapng block size %u > maximum %u",
-		    bhdr.total_length, 16*1024*1024);
-		    return (-1);
-	}
-
-	/*
 	 * Is this block "too small" - i.e., is it shorter than a block
 	 * header plus a block trailer?
 	 */
 	if (bhdr.total_length < sizeof(struct block_header) +
 	    sizeof(struct block_trailer)) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "block in pcapng dump file has a length of %u < %lu",
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "block in pcapng dump file has a length of %u < %zu",
 		    bhdr.total_length,
-		    (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
+		    sizeof(struct block_header) + sizeof(struct block_trailer));
+		return (-1);
+	}
+
+	/*
+	 * Is the block total length a multiple of 4?
+	 */
+	if ((bhdr.total_length % 4) != 0) {
+		/*
+		 * No.  Report that as an error.
+		 */
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "block in pcapng dump file has a length of %u that is not a multiple of 4",
+		    bhdr.total_length);
 		return (-1);
 	}
 
@@ -322,18 +327,19 @@
 	 */
 	if (p->bufsize < bhdr.total_length) {
 		/*
-		 * No - make it big enough, unless it's too big.
+		 * No - make it big enough, unless it's too big, in
+		 * which case we fail.
 		 */
 		void *bigger_buffer;
 
 		if (bhdr.total_length > ps->max_blocksize) {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "block is larger than maximum block size %u",
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
 			    ps->max_blocksize);
 			return (-1);
 		}
 		bigger_buffer = realloc(p->buffer, bhdr.total_length);
 		if (bigger_buffer == NULL) {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 			return (-1);
 		}
 		p->buffer = bigger_buffer;
@@ -350,6 +356,26 @@
 		return (-1);
 
 	/*
+	 * Get the block size from the trailer.
+	 */
+	btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
+	if (p->swapped)
+		btrlr->total_length = SWAPLONG(btrlr->total_length);
+
+	/*
+	 * Is the total length from the trailer the same as the total
+	 * length from the header?
+	 */
+	if (bhdr.total_length != btrlr->total_length) {
+		/*
+		 * No.
+		 */
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "block total length in header and trailer don't match");
+		return (-1);
+	}
+
+	/*
 	 * Initialize the cursor.
 	 */
 	cursor->data = bdata;
@@ -369,7 +395,7 @@
 	 * the block data.
 	 */
 	if (cursor->data_remaining < chunk_size) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "block of type %u in pcapng dump file is too short",
 		    cursor->block_type);
 		return (NULL);
@@ -470,7 +496,7 @@
 
 		case OPT_ENDOFOPT:
 			if (opthdr->option_length != 0) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has opt_endofopt option with length %u != 0",
 				    opthdr->option_length);
 				return (-1);
@@ -479,13 +505,13 @@
 
 		case IF_TSRESOL:
 			if (opthdr->option_length != 1) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has if_tsresol option with length %u != 1",
 				    opthdr->option_length);
 				return (-1);
 			}
 			if (saw_tsresol) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has more than one if_tsresol option");
 				return (-1);
 			}
@@ -502,7 +528,7 @@
 					 * Resolution is too high; 2^-{res}
 					 * won't fit in a 64-bit value.
 					 */
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
 					    tsresol_shift);
 					return (-1);
@@ -522,7 +548,7 @@
 					 * the largest 64-bit unsigned
 					 * value is ~1.8*10^19).
 					 */
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
 					    tsresol_opt);
 					return (-1);
@@ -536,13 +562,13 @@
 
 		case IF_TSOFFSET:
 			if (opthdr->option_length != 8) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has if_tsoffset option with length %u != 8",
 				    opthdr->option_length);
 				return (-1);
 			}
 			if (saw_tsoffset) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has more than one if_tsoffset option");
 				return (-1);
 			}
@@ -562,7 +588,8 @@
 }
 
 static int
-add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
+add_interface(pcap_t *p, struct interface_description_block *idbp,
+    struct block_cursor *cursor, char *errbuf)
 {
 	struct pcap_ng_sf *ps;
 	uint64_t tsresol;
@@ -619,7 +646,7 @@
 				 * possible 32-bit power of 2, as we do
 				 * size doubling.
 				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "more than %u interfaces in the file",
 				    0x80000000U);
 				return (0);
@@ -650,7 +677,7 @@
 				 * (unsigned) value divided by
 				 * sizeof (struct pcap_ng_if).
 				 */
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "more than %u interfaces in the file",
 				    0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
 				return (0);
@@ -662,7 +689,7 @@
 			 * We ran out of memory.
 			 * Give up.
 			 */
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "out of memory for per-interface information (%u interfaces)",
 			    ps->ifcount);
 			return (0);
@@ -671,6 +698,8 @@
 		ps->ifaces = new_ifaces;
 	}
 
+	ps->ifaces[ps->ifcount - 1].snaplen = idbp->snaplen;
+
 	/*
 	 * Set the default time stamp resolution and offset.
 	 */
@@ -736,9 +765,10 @@
  * relevant information from the header.
  */
 pcap_t *
-pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
-    int *err)
+pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
+    char *errbuf, int *err)
 {
+	bpf_u_int32 magic_int;
 	size_t amt_read;
 	bpf_u_int32 total_length;
 	bpf_u_int32 byte_order_magic;
@@ -760,7 +790,8 @@
 	 * Check whether the first 4 bytes of the file are the block
 	 * type for a pcapng savefile.
 	 */
-	if (magic != BT_SHB) {
+	memcpy(&magic_int, magic, sizeof(magic_int));
+	if (magic_int != BT_SHB) {
 		/*
 		 * XXX - check whether this looks like what the block
 		 * type would be after being munged by mapping between
@@ -829,11 +860,14 @@
 	/*
 	 * Check the sanity of the total length.
 	 */
-	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "Section Header Block in pcapng dump file has a length of %u < %lu",
+	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
+            (total_length > BT_SHB_INSANE_MAX)) {
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Section Header Block in pcapng dump file has invalid length %zu < _%u_ < %u (BT_SHB_INSANE_MAX)",
+		    sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
 		    total_length,
-		    (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
+		    BT_SHB_INSANE_MAX);
+
 		*err = 1;
 		return (NULL);
 	}
@@ -842,7 +876,7 @@
 	 * OK, this is a good pcapng file.
 	 * Allocate a pcap_t for it.
 	 */
-	p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
+	p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_ng_sf);
 	if (p == NULL) {
 		/* Allocation failed. */
 		*err = 1;
@@ -865,7 +899,7 @@
 		break;
 
 	default:
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown time stamp resolution %u", precision);
 		free(p);
 		*err = 1;
@@ -885,22 +919,22 @@
 	 *	leaving room for some options.
 	 *
 	 * If we find a bigger block, we reallocate the buffer, up to
-	 * the maximum size.  We start out with a maximum size based
-	 * on a maximum snapshot length of MAXIMUM_SNAPLEN; if we see
-	 * any link-layer header types with a larger maximum snapshot
-	 * length, we boost the maximum.
+	 * the maximum size.  We start out with a maximum size of
+	 * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
+	 * with a maximum snapshot that results in a larger maximum
+	 * block length, we boost the maximum.
 	 */
 	p->bufsize = 2048;
 	if (p->bufsize < total_length)
 		p->bufsize = total_length;
 	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 		free(p);
 		*err = 1;
 		return (NULL);
 	}
-	ps->max_blocksize = MAX_BLOCKSIZE(MAXIMUM_SNAPLEN);
+	ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
 
 	/*
 	 * Copy the stuff we've read to the buffer, and read the rest
@@ -908,12 +942,12 @@
 	 */
 	bhdrp = (struct block_header *)p->buffer;
 	shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
-	bhdrp->block_type = magic;
+	bhdrp->block_type = magic_int;
 	bhdrp->total_length = total_length;
 	shbp->byte_order_magic = byte_order_magic;
 	if (read_bytes(fp,
-	    (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
-	    total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+	    (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
+	    total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
 	    1, errbuf) == -1)
 		goto fail;
 
@@ -931,7 +965,7 @@
 	/* 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,
+		snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "unsupported pcapng savefile version %u.%u",
 		    shbp->major_version, shbp->minor_version);
 		goto fail;
@@ -954,7 +988,7 @@
 		status = read_block(fp, p, &cursor, errbuf);
 		if (status == 0) {
 			/* EOF - no IDB in this file */
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "the capture file has no Interface Description Blocks");
 			goto fail;
 		}
@@ -983,7 +1017,7 @@
 			/*
 			 * Try to add this interface.
 			 */
-			if (!add_interface(p, &cursor, errbuf))
+			if (!add_interface(p, idbp, &cursor, errbuf))
 				goto fail;
 
 			goto done;
@@ -996,7 +1030,7 @@
 			 * not valid, as we don't know what link-layer
 			 * encapsulation the packet has.
 			 */
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "the capture file has a packet block before any Interface Description Blocks");
 			goto fail;
 
@@ -1009,20 +1043,8 @@
 	}
 
 done:
-	p->tzoff = 0;	/* XXX - not used in pcap */
-	p->snapshot = idbp->snaplen;
-	if (p->snapshot <= 0) {
-		/*
-		 * Bogus snapshot length; use the maximum for this
-		 * link-layer type as a fallback.
-		 *
-		 * XXX - the only reason why snapshot is signed is
-		 * that pcap_snapshot() returns an int, not an
-		 * unsigned int.
-		 */
-		p->snapshot = max_snaplen_for_dlt(idbp->linktype);
-	}
 	p->linktype = linktype_to_dlt(idbp->linktype);
+	p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen);
 	p->linktype_ext = 0;
 
 	/*
@@ -1030,8 +1052,8 @@
 	 * snapshot length for this DLT_ is bigger than the current
 	 * maximum block size, increase the maximum.
 	 */
-	if (MAX_BLOCKSIZE(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
-		ps->max_blocksize = MAX_BLOCKSIZE(max_snaplen_for_dlt(p->linktype));
+	if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
+		ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
 
 	p->next_packet_op = pcap_ng_next_packet;
 	p->cleanup_op = pcap_ng_cleanup;
@@ -1212,14 +1234,20 @@
 			 * interfaces?
 			 */
 			if (p->linktype != idbp->linktype) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				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 ((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",
+
+			/*
+			 * Check against the *adjusted* value of this IDB's
+			 * snapshot length.
+			 */
+			if ((bpf_u_int32)p->snapshot !=
+			    pcap_adjust_snapshot(p->linktype, idbp->snaplen)) {
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "an interface has a snapshot length %u different from the snapshot length of the first interface",
 				    idbp->snaplen);
 				return (-1);
 			}
@@ -1227,7 +1255,7 @@
 			/*
 			 * Try to add this interface.
 			 */
-			if (!add_interface(p, &cursor, p->errbuf))
+			if (!add_interface(p, idbp, &cursor, p->errbuf))
 				return (-1);
 			break;
 
@@ -1270,7 +1298,7 @@
 				/*
 				 * Byte order changes.
 				 */
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "the file has sections with different byte orders");
 				return (-1);
 
@@ -1278,7 +1306,7 @@
 				/*
 				 * Not a valid SHB.
 				 */
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "the file has a section with a bad byte order magic field");
 				return (-1);
 			}
@@ -1288,7 +1316,7 @@
 			 * we handle.
 			 */
 			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "unknown pcapng savefile major version number %u",
 				    shbp->major_version);
 				return (-1);
@@ -1322,14 +1350,14 @@
 		/*
 		 * Yes.  Fail.
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
 		    interface_id);
 		return (-1);
 	}
 
 	if (hdr->caplen > (bpf_u_int32)p->snapshot) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "invalid packet capture length %u, bigger than "
 		    "snaplen of %d", hdr->caplen, p->snapshot);
 		return (-1);
diff --git a/sf-pcapng.h b/sf-pcapng.h
index d99b0d4..835082a 100644
--- a/sf-pcapng.h
+++ b/sf-pcapng.h
@@ -26,7 +26,7 @@
 #ifndef sf_pcapng_h
 #define	sf_pcapng_h
 
-extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp,
+extern pcap_t *pcap_ng_check_header(const uint8_t *magic, FILE *fp,
     u_int precision, char *errbuf, int *err);
 
 #endif
diff --git a/sockutils.c b/sockutils.c
index ef3fe76..c1ec9a5 100644
--- a/sockutils.c
+++ b/sockutils.c
@@ -56,11 +56,7 @@
 #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 <limits.h>	/* for INT_MAX */
 
 #include "pcap-int.h"
 
@@ -71,7 +67,7 @@
   /*
    * Winsock initialization.
    *
-   * Ask for WinSock 2.2.
+   * Ask for Winsock 2.2.
    */
   #define WINSOCK_MAJOR_VERSION 2
   #define WINSOCK_MINOR_VERSION 2
@@ -124,50 +120,44 @@
  *                                                  *
  ****************************************************/
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+const uint8_t *fuzzBuffer;
+size_t fuzzSize;
+size_t fuzzPos;
+
+void sock_initfuzz(const uint8_t *Data, size_t Size) {
+	fuzzPos = 0;
+	fuzzSize = Size;
+	fuzzBuffer = Data;
+}
+
+static int fuzz_recv(char *bufp, int remaining) {
+	if (remaining > fuzzSize - fuzzPos) {
+		remaining = fuzzSize - fuzzPos;
+	}
+	if (fuzzPos < fuzzSize) {
+		memcpy(bufp, fuzzBuffer + fuzzPos, remaining);
+	}
+	fuzzPos += remaining;
+	return remaining;
+}
+#endif
+
 /*
- * Format an error message given an errno value (UN*X) or a WinSock error
+ * Format an error message given an errno value (UN*X) or a Winsock error
  * (Windows).
  */
 void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
 {
+	if (errbuf == NULL)
+		return;
+
 #ifdef _WIN32
-	int retval;
-	char message[SOCK_ERRBUF_SIZE];	/* We're forcing "ANSI" */
-
-	if (errbuf == NULL)
-		return;
-
-	retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
-		FORMAT_MESSAGE_MAX_WIDTH_MASK,
-		NULL, errcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		message, sizeof(message) / sizeof(TCHAR), NULL);
-
-	if (retval == 0)
-	{
-		if ((caller) && (*caller))
-			pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
-		else
-			pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
-	}
-	else
-	{
-		if ((caller) && (*caller))
-			pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
-		else
-			pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
-	}
+	pcap_fmt_errmsg_for_win32_err(errbuf, errbuflen, errcode,
+	    "%s", caller);
 #else
-	char *message;
-
-	if (errbuf == NULL)
-		return;
-
-	message = strerror(errcode);
-
-	if ((caller) && (*caller))
-		pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
-	else
-		pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
+	pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errcode,
+	    "%s", caller);
 #endif
 }
 
@@ -180,7 +170,7 @@
  *
  * \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.
+ * comes from the recv() call at line 31'.
  *
  * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
  * error message. This buffer has to be at least 'errbuflen' in length.
@@ -194,31 +184,30 @@
 void sock_geterror(const char *caller, char *errbuf, int errbuflen)
 {
 #ifdef _WIN32
-	if (errbuf == NULL)
-		return;
 	sock_fmterror(caller, GetLastError(), errbuf, errbuflen);
 #else
-	if (errbuf == NULL)
-		return;
 	sock_fmterror(caller, errno, errbuf, errbuflen);
 #endif
 }
 
 /*
- * \brief It initializes sockets.
+ * \brief This function initializes the socket mechanism if it hasn't
+ * already been initialized or reinitializes it after it has been
+ * cleaned up.
  *
- * 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.
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs to
+ * initialize Winsock.
  *
- * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
- * error message. This buffer has to be at least 'errbuflen' in length.
- * It can be NULL; in this case the error cannot be printed.
+ * \param errbuf: a pointer to an user-allocated buffer that will contain
+ * the complete error message. This buffer has to be at least 'errbuflen'
+ * in length. It can be NULL; in this case no error message is supplied.
  *
- * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
- * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ * \param errbuflen: length of the buffer that will contains the error.
+ * The error message cannot be larger than 'errbuflen - 1' because the
+ * last char is reserved for the string terminator.
  *
- * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
- * in the 'errbuf' variable.
+ * \return '0' if everything is fine, '-1' if some errors occurred. The
+ * error message is returned in the buffer pointed to by 'errbuf' variable.
  */
 #ifdef _WIN32
 int sock_init(char *errbuf, int errbuflen)
@@ -231,7 +220,7 @@
 		    WINSOCK_MINOR_VERSION), &wsaData) != 0)
 		{
 			if (errbuf)
-				pcap_snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
+				snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
 
 			WSACleanup();
 
@@ -240,18 +229,24 @@
 	}
 
 	sockcount++;
+	return 0;
+}
 #else
 int sock_init(char *errbuf _U_, int errbuflen _U_)
 {
-#endif
+	/*
+	 * Nothing to do on UN*Xes.
+	 */
 	return 0;
 }
+#endif
 
 /*
- * \brief It deallocates sockets.
+ * \brief This function cleans up the socket mechanism if we have no
+ * sockets left open.
  *
- * 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.
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs
+ * to clean up Winsock.
  *
  * \return No error values.
  */
@@ -295,7 +290,7 @@
  *
  * In case of a server socket, the function calls socket(), bind() and listen().
  *
- * This function is usually preceeded by the sock_initaddress().
+ * This function is usually preceded 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
@@ -327,7 +322,7 @@
 	sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
 	if (sock == INVALID_SOCKET)
 	{
-		sock_geterror("socket(): ", errbuf, errbuflen);
+		sock_geterror("socket()", errbuf, errbuflen);
 		return INVALID_SOCKET;
 	}
 
@@ -350,6 +345,16 @@
 	/* This is a server socket */
 	if (server)
 	{
+		/*
+		 * Allow a new server to bind the socket after the old one
+		 * exited, even if lingering sockets are still present.
+		 *
+		 * Don't treat an error as a failure.
+		 */
+		int optval = 1;
+		(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+		    (char *)&optval, sizeof (optval));
+
 #if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
 		/*
 		 * Force the use of IPv6-only addresses.
@@ -389,7 +394,7 @@
 			    (char *)&on, sizeof (int)) == -1)
 			{
 				if (errbuf)
-					pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)");
+					snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)");
 				closesocket(sock);
 				return INVALID_SOCKET;
 			}
@@ -399,7 +404,7 @@
 		/* 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);
+			sock_geterror("bind()", errbuf, errbuflen);
 			closesocket(sock);
 			return INVALID_SOCKET;
 		}
@@ -407,7 +412,7 @@
 		if (addrinfo->ai_socktype == SOCK_STREAM)
 			if (listen(sock, nconn) == -1)
 			{
-				sock_geterror("listen(): ", errbuf, errbuflen);
+				sock_geterror("listen()", errbuf, errbuflen);
 				closesocket(sock);
 				return INVALID_SOCKET;
 			}
@@ -433,7 +438,9 @@
 		 */
 		while (tempaddrinfo)
 		{
-
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+			break;
+#endif
 			if (connect(sock, tempaddrinfo->ai_addr, (int) tempaddrinfo->ai_addrlen) == -1)
 			{
 				size_t msglen;
@@ -444,13 +451,14 @@
 				 * 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));
+				sock_geterror("Connect to socket failed",
+				    SocketErrorMessage, sizeof(SocketErrorMessage));
 
 				/* Returns the numeric address of the host that triggered the error */
 				sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer));
 
-				pcap_snprintf(errbufptr, bufspaceleft,
-				    "Is the server properly installed on %s?  connect() failed: %s", TmpBuffer, SocketErrorMessage);
+				snprintf(errbufptr, bufspaceleft,
+				    "Is the server properly installed on %s?  %s", TmpBuffer, SocketErrorMessage);
 
 				/* In case more then one 'connect' fails, we manage to keep all the error messages */
 				msglen = strlen(errbufptr);
@@ -508,7 +516,7 @@
 	 */
 	if (shutdown(sock, SHUT_WR))
 	{
-		sock_geterror("shutdown(): ", errbuf, errbuflen);
+		sock_geterror("shutdown()", errbuf, errbuflen);
 		/* close the socket anyway */
 		closesocket(sock);
 		return -1;
@@ -519,6 +527,157 @@
 }
 
 /*
+ * gai_errstring() has some problems:
+ *
+ * 1) on Windows, Microsoft explicitly says it's not thread-safe;
+ * 2) on UN*X, the Single UNIX Specification doesn't say it *is*
+ *    thread-safe, so an implementation might use a static buffer
+ *    for unknown error codes;
+ * 3) the error message for the most likely error, EAI_NONAME, is
+ *    truly horrible on several platforms ("nodename nor servname
+ *    provided, or not known"?  It's typically going to be "not
+ *    known", not "oopsie, I passed null pointers for the host name
+ *    and service name", not to mention they forgot the "neither");
+ *
+ * so we roll our own.
+ */
+static void
+get_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err,
+    const char *hostname, const char *portname)
+{
+	char hostport[PCAP_ERRBUF_SIZE];
+
+	if (hostname != NULL && portname != NULL)
+		snprintf(hostport, PCAP_ERRBUF_SIZE, "%s:%s",
+		    hostname, portname);
+	else if (hostname != NULL)
+		snprintf(hostport, PCAP_ERRBUF_SIZE, "%s",
+		    hostname);
+	else if (portname != NULL)
+		snprintf(hostport, PCAP_ERRBUF_SIZE, ":%s",
+		    portname);
+	else
+		snprintf(hostport, PCAP_ERRBUF_SIZE, "<no host or port!>");
+	switch (err)
+	{
+#ifdef EAI_ADDRFAMILY
+		case EAI_ADDRFAMILY:
+			snprintf(errbuf, errbuflen,
+			    "%sAddress family for %s not supported",
+			    prefix, hostport);
+			break;
+#endif
+
+		case EAI_AGAIN:
+			snprintf(errbuf, errbuflen,
+			    "%s%s could not be resolved at this time",
+			    prefix, hostport);
+			break;
+
+		case EAI_BADFLAGS:
+			snprintf(errbuf, errbuflen,
+			    "%sThe ai_flags parameter for looking up %s had an invalid value",
+			    prefix, hostport);
+			break;
+
+		case EAI_FAIL:
+			snprintf(errbuf, errbuflen,
+			    "%sA non-recoverable error occurred when attempting to resolve %s",
+			    prefix, hostport);
+			break;
+
+		case EAI_FAMILY:
+			snprintf(errbuf, errbuflen,
+			    "%sThe address family for looking up %s was not recognized",
+			    prefix, hostport);
+			break;
+
+		case EAI_MEMORY:
+			snprintf(errbuf, errbuflen,
+			    "%sOut of memory trying to allocate storage when looking up %s",
+			    prefix, hostport);
+			break;
+
+		/*
+		 * RFC 2553 had both EAI_NODATA and EAI_NONAME.
+		 *
+		 * RFC 3493 has only EAI_NONAME.
+		 *
+		 * Some implementations define EAI_NODATA and EAI_NONAME
+		 * to the same value, others don't.  If EAI_NODATA is
+		 * defined and isn't the same as EAI_NONAME, we handle
+		 * EAI_NODATA.
+		 */
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+		case EAI_NODATA:
+			snprintf(errbuf, errbuflen,
+			    "%sNo address associated with %s",
+			    prefix, hostport);
+			break;
+#endif
+
+		case EAI_NONAME:
+			snprintf(errbuf, errbuflen,
+			    "%sThe host name %s couldn't be resolved",
+			    prefix, hostport);
+			break;
+
+		case EAI_SERVICE:
+			snprintf(errbuf, errbuflen,
+			    "%sThe service value specified when looking up %s as not recognized for the socket type",
+			    prefix, hostport);
+			break;
+
+		case EAI_SOCKTYPE:
+			snprintf(errbuf, errbuflen,
+			    "%sThe socket type specified when looking up %s as not recognized",
+			    prefix, hostport);
+			break;
+
+#ifdef EAI_SYSTEM
+		case EAI_SYSTEM:
+			/*
+			 * Assumed to be UN*X.
+			 */
+			pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errno,
+			    "%sAn error occurred when looking up %s",
+			    prefix, hostport);
+			break;
+#endif
+
+#ifdef EAI_BADHINTS
+		case EAI_BADHINTS:
+			snprintf(errbuf, errbuflen,
+			    "%sInvalid value for hints when looking up %s",
+			    prefix, hostport);
+			break;
+#endif
+
+#ifdef EAI_PROTOCOL
+		case EAI_PROTOCOL:
+			snprintf(errbuf, errbuflen,
+			    "%sResolved protocol when looking up %s is unknown",
+			    prefix, hostport);
+			break;
+#endif
+
+#ifdef EAI_OVERFLOW
+		case EAI_OVERFLOW:
+			snprintf(errbuf, errbuflen,
+			    "%sArgument buffer overflow when looking up %s",
+			    prefix, hostport);
+			break;
+#endif
+
+		default:
+			snprintf(errbuf, errbuflen,
+			    "%sgetaddrinfo() error %d when looking up %s",
+			    prefix, err, hostport);
+			break;
+	}
+}
+
+/*
  * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
  *
  * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
@@ -564,17 +723,10 @@
 	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
+			get_gai_errstring(errbuf, errbuflen, "", retval,
+			    host, port);
 		}
 		return -1;
 	}
@@ -595,7 +747,7 @@
 	    ((*addrinfo)->ai_family != PF_INET6))
 	{
 		if (errbuf)
-			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
+			snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
 		freeaddrinfo(*addrinfo);
 		*addrinfo = NULL;
 		return -1;
@@ -608,7 +760,7 @@
 	    (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
 	{
 		if (errbuf)
-			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
+			snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
 		freeaddrinfo(*addrinfo);
 		*addrinfo = NULL;
 		return -1;
@@ -644,7 +796,7 @@
  * '-2' if we got one of those errors.
  * For errors, an error message is returned in the 'errbuf' variable.
  */
-int sock_send(SOCKET sock, const char *buffer, size_t size,
+int sock_send(SOCKET sock, SSL *ssl _U_NOSSL_, const char *buffer, size_t size,
     char *errbuf, int errbuflen)
 {
 	int remaining;
@@ -654,8 +806,8 @@
 	{
 		if (errbuf)
 		{
-			pcap_snprintf(errbuf, errbuflen,
-			    "Can't send more than %u bytes with sock_recv",
+			snprintf(errbuf, errbuflen,
+			    "Can't send more than %u bytes with sock_send",
 			    INT_MAX);
 		}
 		return -1;
@@ -663,6 +815,13 @@
 	remaining = (int)size;
 
 	do {
+#ifdef HAVE_OPENSSL
+		if (ssl) return ssl_send(ssl, buffer, remaining, errbuf, errbuflen);
+#endif
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+		nsent = remaining;
+#else
 #ifdef MSG_NOSIGNAL
 		/*
 		 * Send with MSG_NOSIGNAL, so that we don't get SIGPIPE
@@ -674,6 +833,7 @@
 #else
 		nsent = send(sock, buffer, remaining, 0);
 #endif
+#endif //FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 
 		if (nsent == -1)
 		{
@@ -697,7 +857,7 @@
 				 */
 				return -2;
 			}
-			sock_fmterror("send(): ", errcode, errbuf, errbuflen);
+			sock_fmterror("send()", errcode, errbuf, errbuflen);
 #else
 			errcode = errno;
 			if (errcode == ECONNRESET || errcode == EPIPE)
@@ -709,7 +869,7 @@
 				 */
 				return -2;
 			}
-			sock_fmterror("send(): ", errcode, errbuf, errbuflen);
+			sock_fmterror("send()", errcode, errbuf, errbuflen);
 #endif
 			return -1;
 		}
@@ -781,7 +941,7 @@
 	if ((*offset + size) > totsize)
 	{
 		if (errbuf)
-			pcap_snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
+			snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
 		return -1;
 	}
 
@@ -839,29 +999,32 @@
  * The error message is returned in the 'errbuf' variable.
  */
 
-int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
-    char *errbuf, int errbuflen)
+int sock_recv(SOCKET sock, SSL *ssl _U_NOSSL_, void *buffer, size_t size,
+    int flags, char *errbuf, int errbuflen)
 {
+	int recv_flags = 0;
 	char *bufp = buffer;
 	int remaining;
 	ssize_t nread;
 
 	if (size == 0)
 	{
-		SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
 		return 0;
 	}
 	if (size > INT_MAX)
 	{
 		if (errbuf)
 		{
-			pcap_snprintf(errbuf, errbuflen,
+			snprintf(errbuf, errbuflen,
 			    "Can't read more than %u bytes with sock_recv",
 			    INT_MAX);
 		}
 		return -1;
 	}
 
+	if (flags & SOCK_MSG_PEEK)
+		recv_flags |= MSG_PEEK;
+
 	bufp = (char *) buffer;
 	remaining = (int) size;
 
@@ -870,7 +1033,22 @@
 	 * Win32.
 	 */
 	for (;;) {
-		nread = recv(sock, bufp, remaining, 0);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+		nread = fuzz_recv(bufp, remaining);
+#elif defined(HAVE_OPENSSL)
+		if (ssl)
+		{
+			/*
+			 * XXX - what about MSG_PEEK?
+			 */
+			nread = ssl_recv(ssl, bufp, remaining, errbuf, errbuflen);
+			if (nread == -2) return -1;
+		}
+		else
+			nread = recv(sock, bufp, remaining, recv_flags);
+#else
+		nread = recv(sock, bufp, remaining, recv_flags);
+#endif
 
 		if (nread == -1)
 		{
@@ -878,7 +1056,7 @@
 			if (errno == EINTR)
 				return -3;
 #endif
-			sock_geterror("recv(): ", errbuf, errbuflen);
+			sock_geterror("recv()", errbuf, errbuflen);
 			return -1;
 		}
 
@@ -894,7 +1072,7 @@
 				 */
 				if (errbuf)
 				{
-					pcap_snprintf(errbuf, errbuflen,
+					snprintf(errbuf, errbuflen,
 					    "The other host terminated the connection.");
 				}
 				return -1;
@@ -928,7 +1106,7 @@
  *
  * Returns the size of the datagram on success or -1 on error.
  */
-int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+int sock_recv_dgram(SOCKET sock, SSL *ssl _U_NOSSL_, void *buffer, size_t size,
     char *errbuf, int errbuflen)
 {
 	ssize_t nread;
@@ -939,27 +1117,35 @@
 
 	if (size == 0)
 	{
-		SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
 		return 0;
 	}
 	if (size > INT_MAX)
 	{
 		if (errbuf)
 		{
-			pcap_snprintf(errbuf, errbuflen,
+			snprintf(errbuf, errbuflen,
 			    "Can't read more than %u bytes with sock_recv_dgram",
 			    INT_MAX);
 		}
 		return -1;
 	}
 
+#ifdef HAVE_OPENSSL
+	// TODO: DTLS
+	if (ssl)
+	{
+		snprintf(errbuf, errbuflen, "DTLS not implemented yet");
+		return -1;
+	}
+#endif
+
 	/*
 	 * This should be a datagram socket, so we should get the
 	 * entire datagram in one recv() or recvmsg() call, and
 	 * don't need to loop.
 	 */
 #ifdef _WIN32
-	nread = recv(sock, buffer, size, 0);
+	nread = recv(sock, buffer, (int)size, 0);
 	if (nread == SOCKET_ERROR)
 	{
 		/*
@@ -975,7 +1161,7 @@
 		 * supplied to us, the excess data is discarded,
 		 * and we'll report an error.
 		 */
-		sock_geterror("recv(): ", errbuf, errbuflen);
+		sock_geterror("recv()", errbuf, errbuflen);
 		return -1;
 	}
 #else /* _WIN32 */
@@ -1003,12 +1189,16 @@
 #ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
 	message.msg_flags = 0;
 #endif
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+	nread = fuzz_recv(buffer, size);
+#else
 	nread = recvmsg(sock, &message, 0);
+#endif
 	if (nread == -1)
 	{
 		if (errno == EINTR)
 			return -3;
-		sock_geterror("recv(): ", errbuf, errbuflen);
+		sock_geterror("recv()", errbuf, errbuflen);
 		return -1;
 	}
 #ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
@@ -1025,7 +1215,7 @@
 		 * Report this as an error, as the Microsoft documentation
 		 * implies we'd do in a similar case on Windows.
 		 */
-		pcap_snprintf(errbuf, errbuflen, "recv(): Message too long");
+		snprintf(errbuf, errbuflen, "recv(): Message too long");
 		return -1;
 	}
 #endif /* HAVE_STRUCT_MSGHDR_MSG_FLAGS */
@@ -1063,7 +1253,7 @@
  * \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)
+int sock_discard(SOCKET sock, SSL *ssl, int size, char *errbuf, int errbuflen)
 {
 #define TEMP_BUF_SIZE 32768
 
@@ -1079,7 +1269,7 @@
 	 */
 	while (size > TEMP_BUF_SIZE)
 	{
-		if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+		if (sock_recv(sock, ssl, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
 			return -1;
 
 		size -= TEMP_BUF_SIZE;
@@ -1091,12 +1281,10 @@
 	 */
 	if (size)
 	{
-		if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+		if (sock_recv(sock, ssl, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
 			return -1;
 	}
 
-	SOCK_DEBUG_MESSAGE("I'm currently discarding data\n");
-
 	return 0;
 }
 
@@ -1137,6 +1325,7 @@
 		struct addrinfo *addrinfo, *ai_next;
 		char *temphostlist;
 		char *lasts;
+		int getaddrinfo_failed = 0;
 
 		/*
 		 * The problem is that strtok modifies the original variable by putting '0' at the end of each token
@@ -1164,13 +1353,19 @@
 			hints.ai_family = PF_UNSPEC;
 			hints.ai_socktype = SOCK_STREAM;
 
-			retval = getaddrinfo(token, "0", &hints, &addrinfo);
+			retval = getaddrinfo(token, NULL, &hints, &addrinfo);
 			if (retval != 0)
 			{
 				if (errbuf)
-					pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
+					get_gai_errstring(errbuf, errbuflen,
+					    "Allowed host list error: ",
+					    retval, token, NULL);
 
-				SOCK_DEBUG_MESSAGE(errbuf);
+				/*
+				 * Note that at least one call to getaddrinfo()
+				 * failed.
+				 */
+				getaddrinfo_failed = 1;
 
 				/* Get next token */
 				token = pcap_strtok_r(NULL, sep, &lasts);
@@ -1208,11 +1403,25 @@
 			addrinfo = NULL;
 		}
 
-		if (errbuf)
-			pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
-
 		free(temphostlist);
-		return -1;
+
+		if (getaddrinfo_failed) {
+			/*
+			 * At least one getaddrinfo() call failed;
+			 * treat that as an error, so rpcapd knows
+			 * that it should log it locally as well
+			 * as telling the client about it.
+			 */
+			return -2;
+		} else {
+			/*
+			 * All getaddrinfo() calls succeeded, but
+			 * the host wasn't in the list.
+			 */
+			if (errbuf)
+				snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
+			return -1;
+		}
 	}
 
 	/* No hostlist, so we have to return 'empty list' */
@@ -1311,7 +1520,7 @@
 
 	if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1)
 	{
-		sock_geterror("getsockname(): ", errbuf, errbuflen);
+		sock_geterror("getsockname()", errbuf, errbuflen);
 		return 0;
 	}
 
@@ -1389,7 +1598,7 @@
 			(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);
+				pcap_strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
 			return retval;
 		}
 	}
@@ -1399,19 +1608,19 @@
 		/* If the user wants to receive an error message */
 		if (errbuf)
 		{
-			sock_geterror("getnameinfo(): ", errbuf, errbuflen);
+			sock_geterror("getnameinfo()", errbuf, errbuflen);
 			errbuf[errbuflen - 1] = 0;
 		}
 
 		if (address)
 		{
-			strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
+			pcap_strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
 			address[addrlen - 1] = 0;
 		}
 
 		if (port)
 		{
-			strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
+			pcap_strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
 			port[portlen - 1] = 0;
 		}
 
@@ -1480,7 +1689,7 @@
 		freeaddrinfo(addrinfo);
 
 		if (errbuf)
-			pcap_snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
+			snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
 		return -2;
 	}
 
diff --git a/sockutils.h b/sockutils.h
index 1df1ef7..e748662 100644
--- a/sockutils.h
+++ b/sockutils.h
@@ -37,54 +37,11 @@
 #pragma once
 #endif
 
-#ifdef _WIN32
-  /* Need windef.h for defines used in winsock2.h under MingW32 */
-  #ifdef __MINGW32__
-    #include <windef.h>
-  #endif
-  #include <winsock2.h>
-  #include <ws2tcpip.h>
+#include "pcap/socket.h"
 
-  /*
-   * Winsock doesn't have this UN*X type; it's used in the UN*X
-   * sockets API.
-   *
-   * XXX - do we need to worry about UN*Xes so old that *they*
-   * don't have it, either?
-   */
-  typedef int socklen_t;
-#else
+#ifndef _WIN32
   /* 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
 
   /*!
    * \brief In Winsock, the close() call cannot be used on a socket;
@@ -95,6 +52,8 @@
   #define closesocket(a) close(a)
 #endif
 
+#include "sslutils.h"  // for SSL type, whatever that turns out to be
+
 /*
  * MingW headers include this definition, but only for Windows XP and above.
  * MSDN states that this function is available for most versions on Windows.
@@ -122,35 +81,6 @@
  * \{
  */
 
-/*
- * \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_DEBUG_MESSAGE(msg) ((void)0)
-#else
-  #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_DEBUG_MESSAGE(msg) { _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%s\n", msg); fprintf(stderr, "%s\n", msg); }
-  #else
-    #define SOCK_DEBUG_MESSAGE(msg) { fprintf(stderr, "%s\n", msg); }
-  #endif
-#endif
-
 /****************************************************
  *                                                  *
  * Exported functions / definitions                 *
@@ -176,6 +106,8 @@
 #define SOCK_EOF_ISNT_ERROR	0x00000000	/* Return 0 on EOF */
 #define SOCK_EOF_IS_ERROR	0x00000002	/* Return an error on EOF */
 
+#define SOCK_MSG_PEEK		0x00000004	/* Return data but leave it in the socket queue */
+
 /*
  * \}
  */
@@ -200,17 +132,17 @@
 int sock_initaddress(const char *address, const char *port,
     struct addrinfo *hints, struct addrinfo **addrinfo,
     char *errbuf, int errbuflen);
-int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+int sock_recv(SOCKET sock, SSL *, void *buffer, size_t size, int receiveall,
     char *errbuf, int errbuflen);
-int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+int sock_recv_dgram(SOCKET sock, SSL *, void *buffer, size_t size,
     char *errbuf, int errbuflen);
 SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
 int sock_close(SOCKET sock, char *errbuf, int errbuflen);
 
-int sock_send(SOCKET sock, const char *buffer, size_t size,
+int sock_send(SOCKET sock, SSL *, const char *buffer, size_t size,
     char *errbuf, int errbuflen);
 int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen);
-int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen);
+int sock_discard(SOCKET sock, SSL *, int size, char *errbuf, int errbuflen);
 int	sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen);
 int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second);
 
diff --git a/sslutils.c b/sslutils.c
new file mode 100644
index 0000000..7274cc3
--- /dev/null
+++ b/sslutils.c
@@ -0,0 +1,239 @@
+/*
+ * 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
+
+#ifdef HAVE_OPENSSL
+#include <stdlib.h>
+
+#include "portability.h"
+
+#include "sslutils.h"
+
+static const char *ssl_keyfile = "";   //!< file containing the private key in PEM format
+static const char *ssl_certfile = "";  //!< file containing the server's certificate in PEM format
+static const char *ssl_rootfile = "";  //!< file containing the list of CAs trusted by the client
+// TODO: a way to set ssl_rootfile from the command line, or an envvar?
+
+// TODO: lock?
+static SSL_CTX *ctx;
+
+void ssl_set_certfile(const char *certfile)
+{
+	ssl_certfile = certfile;
+}
+
+void ssl_set_keyfile(const char *keyfile)
+{
+	ssl_keyfile = keyfile;
+}
+
+int ssl_init_once(int is_server, int enable_compression, char *errbuf, size_t errbuflen)
+{
+	static int inited = 0;
+	if (inited) return 0;
+
+	SSL_library_init();
+	SSL_load_error_strings();
+	OpenSSL_add_ssl_algorithms();
+	if (enable_compression)
+		SSL_COMP_get_compression_methods();
+
+	SSL_METHOD const *meth =
+	    is_server ? SSLv23_server_method() : SSLv23_client_method();
+	ctx = SSL_CTX_new(meth);
+	if (! ctx)
+	{
+		snprintf(errbuf, errbuflen, "Cannot get a new SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
+		goto die;
+	}
+
+	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+
+	if (is_server)
+	{
+		char const *certfile = ssl_certfile[0] ? ssl_certfile : "cert.pem";
+		if (1 != SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
+		{
+			snprintf(errbuf, errbuflen, "Cannot read certificate file %s: %s", certfile, ERR_error_string(ERR_get_error(), NULL));
+			goto die;
+		}
+
+		char const *keyfile = ssl_keyfile[0] ? ssl_keyfile : "key.pem";
+		if (1 != SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
+		{
+			snprintf(errbuf, errbuflen, "Cannot read private key file %s: %s", keyfile, ERR_error_string(ERR_get_error(), NULL));
+			goto die;
+		}
+	}
+	else
+	{
+		if (ssl_rootfile[0])
+		{
+			if (! SSL_CTX_load_verify_locations(ctx, ssl_rootfile, 0))
+			{
+				snprintf(errbuf, errbuflen, "Cannot read CA list from %s", ssl_rootfile);
+				goto die;
+			}
+		}
+		else
+		{
+			SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+		}
+	}
+
+#if 0
+	if (! RAND_load_file(RANDOM, 1024*1024))
+	{
+		snprintf(errbuf, errbuflen, "Cannot init random");
+		goto die;
+	}
+
+	if (is_server)
+	{
+		SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, sizeof(s_server_session_id_context));
+	}
+#endif
+
+	inited = 1;
+	return 0;
+
+die:
+	return -1;
+}
+
+SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen)
+{
+	if (ssl_init_once(is_server, 1, errbuf, errbuflen) < 0) {
+		return NULL;
+	}
+
+	SSL *ssl = SSL_new(ctx); // TODO: also a DTLS context
+	SSL_set_fd(ssl, (int)s);
+
+	if (is_server) {
+		if (SSL_accept(ssl) <= 0) {
+			snprintf(errbuf, errbuflen, "SSL_accept(): %s",
+					ERR_error_string(ERR_get_error(), NULL));
+			return NULL;
+		}
+	} else {
+		if (SSL_connect(ssl) <= 0) {
+			snprintf(errbuf, errbuflen, "SSL_connect(): %s",
+					ERR_error_string(ERR_get_error(), NULL));
+			return NULL;
+		}
+	}
+
+	return ssl;
+}
+
+// Finish using an SSL handle; shut down the connection and free the
+// handle.
+void ssl_finish(SSL *ssl)
+{
+	//
+	// We won't be using this again, so we can just send the
+	// shutdown alert and free up the handle, and have our
+	// caller close the socket.
+	//
+	// XXX - presumably, if the connection is shut down on
+	// our side, either our peer won't have a problem sending
+	// their shutdown alert or will not treat such a problem
+	// as an error.  If this causes errors to be reported,
+	// fix that as appropriate.
+	//
+	SSL_shutdown(ssl);
+	SSL_free(ssl);
+}
+
+// Same return value as sock_send:
+// 0 on OK, -1 on error but closed connection (-2).
+int ssl_send(SSL *ssl, char const *buffer, int size, char *errbuf, size_t errbuflen)
+{
+	int status = SSL_write(ssl, buffer, size);
+	if (status > 0)
+	{
+		// "SSL_write() will only return with success, when the complete contents (...) has been written."
+		return 0;
+	}
+	else
+	{
+		int ssl_err = SSL_get_error(ssl, status); // TODO: does it pop the error?
+		if (ssl_err == SSL_ERROR_ZERO_RETURN)
+		{
+			return -2;
+		}
+		else if (ssl_err == SSL_ERROR_SYSCALL)
+		{
+#ifndef _WIN32
+			if (errno == ECONNRESET || errno == EPIPE) return -2;
+#endif
+		}
+		snprintf(errbuf, errbuflen, "SSL_write(): %s",
+		    ERR_error_string(ERR_get_error(), NULL));
+		return -1;
+	}
+}
+
+// Returns the number of bytes read, or -1 on syserror, or -2 on SSL error.
+int ssl_recv(SSL *ssl, char *buffer, int size, char *errbuf, size_t errbuflen)
+{
+	int status = SSL_read(ssl, buffer, size);
+	if (status <= 0)
+	{
+		int ssl_err = SSL_get_error(ssl, status);
+		if (ssl_err == SSL_ERROR_ZERO_RETURN)
+		{
+			return 0;
+		}
+		else if (ssl_err == SSL_ERROR_SYSCALL)
+		{
+			return -1;
+		}
+		else
+		{
+			// Should not happen
+			snprintf(errbuf, errbuflen, "SSL_read(): %s",
+			    ERR_error_string(ERR_get_error(), NULL));
+			return -2;
+		}
+	}
+	else
+	{
+		return status;
+	}
+}
+
+#endif // HAVE_OPENSSL
diff --git a/sslutils.h b/sslutils.h
new file mode 100644
index 0000000..6316364
--- /dev/null
+++ b/sslutils.h
@@ -0,0 +1,66 @@
+/*
+ * 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 __SSLUTILS_H__
+#define __SSLUTILS_H__
+
+#ifdef HAVE_OPENSSL
+#include "pcap/socket.h"  // for SOCKET
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+/*
+ * Utility functions
+ */
+
+void ssl_set_certfile(const char *certfile);
+void ssl_set_keyfile(const char *keyfile);
+int ssl_init_once(int is_server, int enable_compression, char *errbuf, size_t errbuflen);
+SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen);
+void ssl_finish(SSL *ssl);
+int ssl_send(SSL *, char const *buffer, int size, char *errbuf, size_t errbuflen);
+int ssl_recv(SSL *, char *buffer, int size, char *errbuf, size_t errbuflen);
+
+// The SSL parameters are used
+#define _U_NOSSL_
+
+#else   // HAVE_OPENSSL
+
+// This saves us from a lot of ifdefs:
+#define SSL void const
+
+// The SSL parameters are unused
+#define _U_NOSSL_	_U_
+
+#endif  // HAVE_OPENSSL
+
+#endif  // __SSLUTILS_H__
diff --git a/testprogs/.gitignore b/testprogs/.gitignore
index b9178b4..b57c7bb 100644
--- a/testprogs/.gitignore
+++ b/testprogs/.gitignore
@@ -7,7 +7,9 @@
 can_set_rfmon_test
 filtertest
 findalldevstest
+findalldevstest-perf
 opentest
 reactivatetest
 selpolltest
 threadsignaltest
+writecaptest
diff --git a/testprogs/BPF/1.txt b/testprogs/BPF/1.txt
index 6608695..733651e 100644
--- a/testprogs/BPF/1.txt
+++ b/testprogs/BPF/1.txt
@@ -1,2 +1,2 @@
-# common block merging, same block elimination, result propogation
+# common block merging, same block elimination, result propagation
 host 192.168.1.1
diff --git a/testprogs/CMakeLists.txt b/testprogs/CMakeLists.txt
index b8ef9b7..bf57361 100644
--- a/testprogs/CMakeLists.txt
+++ b/testprogs/CMakeLists.txt
@@ -19,6 +19,10 @@
     target_link_libraries(${_executable}
       ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
   endif(WIN32)
+  if(NOT "${LINKER_FLAGS}" STREQUAL "")
+    set_target_properties(${_executable} PROPERTIES
+      LINK_FLAGS "${LINKER_FLAGS}")
+  endif()
   add_dependencies(testprogs ${_executable})
 endmacro()
 
@@ -26,8 +30,10 @@
 add_test_executable(capturetest)
 add_test_executable(filtertest)
 add_test_executable(findalldevstest)
+add_test_executable(findalldevstest-perf)
 add_test_executable(opentest)
 add_test_executable(reactivatetest)
+add_test_executable(writecaptest)
 
 if(NOT WIN32)
   add_test_executable(selpolltest)
@@ -38,3 +44,5 @@
 if(NOT WIN32)
   add_test_executable(valgrindtest)
 endif()
+
+add_subdirectory(fuzz)
diff --git a/testprogs/Makefile.in b/testprogs/Makefile.in
index ec0a472..43af561 100644
--- a/testprogs/Makefile.in
+++ b/testprogs/Makefile.in
@@ -38,6 +38,7 @@
 
 # VPATH
 srcdir = @srcdir@
+top_srcdir = @top_srcdir@
 VPATH = @srcdir@
 
 #
@@ -79,14 +80,16 @@
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
 
 SRC = @VALGRINDTEST_SRC@ \
-	capturetest.c \
 	can_set_rfmon_test.c \
+	capturetest.c \
 	filtertest.c \
+	findalldevstest-perf.c \
 	findalldevstest.c \
 	opentest.c \
 	reactivatetest.c \
 	selpolltest.c \
-	threadsignaltest.c
+	threadsignaltest.c \
+	writecaptest.c
 
 TESTS = $(SRC:.c=)
 
@@ -109,6 +112,9 @@
 findalldevstest: $(srcdir)/findalldevstest.c ../libpcap.a
 	$(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/findalldevstest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
 
+findalldevstest-perf: $(srcdir)/findalldevstest-perf.c ../libpcap.a
+	$(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest-perf $(srcdir)/findalldevstest-perf.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
 opentest: $(srcdir)/opentest.c ../libpcap.a
 	$(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/opentest.c ../libpcap.a $(LIBS)
 
@@ -124,6 +130,9 @@
 valgrindtest: $(srcdir)/valgrindtest.c ../libpcap.a
 	$(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/valgrindtest.c ../libpcap.a $(LIBS)
 
+writecaptest: $(srcdir)/writecaptest.c ../libpcap.a
+	$(CC) $(FULL_CFLAGS) -I. -L. -o writecaptest $(srcdir)/writecaptest.c ../libpcap.a $(LIBS)
+
 clean:
 	rm -f $(CLEANFILES)
 	rm -rf *.dSYM
@@ -141,4 +150,4 @@
 	ctags -wtd $(TAGFILES)
 
 depend:
-	../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+	$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/testprogs/can_set_rfmon_test.c b/testprogs/can_set_rfmon_test.c
index f6188ba..96816f9 100644
--- a/testprogs/can_set_rfmon_test.c
+++ b/testprogs/can_set_rfmon_test.c
@@ -70,7 +70,6 @@
 		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;
diff --git a/testprogs/capturetest.c b/testprogs/capturetest.c
index d625cb4..4eadd33 100644
--- a/testprogs/capturetest.c
+++ b/testprogs/capturetest.c
@@ -38,6 +38,9 @@
   #include <unistd.h>
 #endif
 #include <errno.h>
+#ifndef _WIN32
+  #include <signal.h>
+#endif
 #include <sys/types.h>
 
 #include <pcap.h>
@@ -58,6 +61,37 @@
 static char *copy_argv(char **);
 
 static pcap_t *pd;
+#ifndef _WIN32
+static int breaksigint = 0;
+#endif
+
+#ifndef _WIN32
+static void
+sigint_handler(int signum _U_)
+{
+	if (breaksigint)
+		pcap_breakloop(pd);
+}
+#endif
+
+#ifdef _WIN32
+/*
+ * We don't have UN*X-style signals, so we don't have anything to test.
+ */
+#define B_OPTION	""
+#define R_OPTION	""
+#define S_OPTION	""
+#else
+/*
+ * We do have UN*X-style signals (we assume that "not Windows" means "UN*X").
+ */
+#define B_OPTION	"b"
+#define R_OPTION	"r"
+#define S_OPTION	"s"
+#endif
+
+#define COMMAND_OPTIONS	B_OPTION "i:mn" R_OPTION S_OPTION "t:"
+#define USAGE_OPTIONS	"-" B_OPTION "mn" R_OPTION S_OPTION
 
 int
 main(int argc, char **argv)
@@ -69,6 +103,10 @@
 	int timeout = 1000;
 	int immediate = 0;
 	int nonblock = 0;
+#ifndef _WIN32
+	int sigrestart = 0;
+	int catchsigint = 0;
+#endif
 	pcap_if_t *devlist;
 	bpf_u_int32 localnet, netmask;
 	struct bpf_program fcode;
@@ -83,9 +121,15 @@
 		program_name = argv[0];
 
 	opterr = 0;
-	while ((op = getopt(argc, argv, "i:mnt:")) != -1) {
+	while ((op = getopt(argc, argv, COMMAND_OPTIONS)) != -1) {
 		switch (op) {
 
+#ifndef _WIN32
+		case 'b':
+			breaksigint = 1;
+			break;
+#endif
+
 		case 'i':
 			device = optarg;
 			break;
@@ -98,6 +142,16 @@
 			nonblock = 1;
 			break;
 
+#ifndef _WIN32
+		case 'r':
+			sigrestart = 1;
+			break;
+
+		case 's':
+			catchsigint = 1;
+			break;
+#endif
+
 		case 't':
 			longarg = strtol(optarg, &p, 10);
 			if (p == optarg || *p != '\0') {
@@ -132,6 +186,28 @@
 		pcap_freealldevs(devlist);
 	}
 	*ebuf = '\0';
+
+#ifndef _WIN32
+	/*
+	 * If we were told to catch SIGINT, do so.
+	 */
+	if (catchsigint) {
+		struct sigaction action;
+
+		action.sa_handler = sigint_handler;
+		sigemptyset(&action.sa_mask);
+
+		/*
+		 * Should SIGINT interrupt, or restart, system calls?
+		 */
+		action.sa_flags = sigrestart ? SA_RESTART : 0;
+
+		if (sigaction(SIGINT, &action, NULL) == -1)
+			error("Can't catch SIGINT: %s\n",
+			    strerror(errno));
+	}
+#endif
+
 	pd = pcap_create(device, ebuf);
 	if (pd == NULL)
 		error("%s", ebuf);
@@ -188,6 +264,10 @@
 		if (status != 0) {
 			printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
 			    status, packet_count);
+			struct pcap_stat ps;
+			pcap_stats(pd, &ps);
+			printf("%d ps_recv, %d ps_drop, %d ps_ifdrop\n",
+			    ps.ps_recv, ps.ps_drop, ps.ps_ifdrop);
 		}
 	}
 	if (status == -2) {
@@ -197,13 +277,14 @@
 		 * Print an extra newline, just in case.
 		 */
 		putchar('\n');
+		printf("Broken out of loop from SIGINT handler\n");
 	}
 	(void)fflush(stdout);
 	if (status == -1) {
 		/*
 		 * Error.  Report it.
 		 */
-		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
+		(void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
 		    program_name, pcap_geterr(pd));
 	}
 	pcap_close(pd);
@@ -223,7 +304,7 @@
 static void
 usage(void)
 {
-	(void)fprintf(stderr, "Usage: %s [ -mn ] [ -i interface ] [ -t timeout] [expression]\n",
+	(void)fprintf(stderr, "Usage: %s [ " USAGE_OPTIONS " ] [ -i interface ] [ -t timeout] [expression]\n",
 	    program_name);
 	exit(1);
 }
@@ -271,7 +352,7 @@
 copy_argv(register char **argv)
 {
 	register char **p;
-	register u_int len = 0;
+	register size_t len = 0;
 	char *buf;
 	char *src, *dst;
 
diff --git a/testprogs/filtertest.c b/testprogs/filtertest.c
index 7e2d6d6..440b550 100644
--- a/testprogs/filtertest.c
+++ b/testprogs/filtertest.c
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <limits.h>
 #ifdef _WIN32
   #include "getopt.h"
   #include "unix.h"
@@ -56,6 +57,8 @@
 
 #include "pcap/funcattrs.h"
 
+#define MAXIMUM_SNAPLEN		262144
+
 #ifdef BDEBUG
 /*
  * We have pcap_set_optimizer_debug() and pcap_set_print_dot_graph() in
@@ -99,11 +102,21 @@
 	if (fstat(fd, &buf) < 0)
 		error("can't stat %s: %s", fname, pcap_strerror(errno));
 
+	/*
+	 * _read(), on Windows, has an unsigned int byte count and an
+	 * int return value, so we can't handle a file bigger than
+	 * INT_MAX - 1 bytes (and have no reason to do so; a filter *that*
+	 * big will take forever to compile).  (The -1 is for the '\0' at
+	 * the end of the string.)
+	 */
+	if (buf.st_size > INT_MAX - 1)
+		error("%s is larger than %d bytes; that's too large", fname,
+		    INT_MAX - 1);
 	cp = malloc((u_int)buf.st_size + 1);
 	if (cp == NULL)
 		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
 			fname, pcap_strerror(errno));
-	cc = read(fd, cp, (u_int)buf.st_size);
+	cc = (int)read(fd, cp, (u_int)buf.st_size);
 	if (cc < 0)
 		error("read %s: %s", fname, pcap_strerror(errno));
 	if (cc != buf.st_size)
@@ -163,7 +176,7 @@
 copy_argv(register char **argv)
 {
 	register char **p;
-	register u_int len = 0;
+	register size_t len = 0;
 	char *buf;
 	char *src, *dst;
 
@@ -196,10 +209,12 @@
 	char *cp;
 	int op;
 	int dflag;
+#ifdef BDEBUG
 	int gflag;
+#endif
 	char *infile;
 	int Oflag;
-	long snaplen;
+	int snaplen;
 	char *p;
 	int dlt;
 	int have_fcode = 0;
@@ -214,11 +229,13 @@
 #endif /* _WIN32 */
 
 	dflag = 1;
+#ifdef BDEBUG
 	gflag = 0;
+#endif
 
 	infile = NULL;
 	Oflag = 1;
-	snaplen = 68;
+	snaplen = MAXIMUM_SNAPLEN;
 
 	if ((cp = strrchr(argv[0], '/')) != NULL)
 		program_name = cp + 1;
@@ -272,13 +289,19 @@
 
 		case 's': {
 			char *end;
+			long long_snaplen;
 
-			snaplen = strtol(optarg, &end, 0);
+			long_snaplen = strtol(optarg, &end, 0);
 			if (optarg == end || *end != '\0'
-			    || snaplen < 0 || snaplen > 65535)
+			    || long_snaplen < 0
+			    || long_snaplen > MAXIMUM_SNAPLEN)
 				error("invalid snaplen %s", optarg);
-			else if (snaplen == 0)
-				snaplen = 65535;
+			else {
+				if (snaplen == 0)
+					snaplen = MAXIMUM_SNAPLEN;
+				else
+					snaplen = (int)long_snaplen;
+			}
 			break;
 		}
 
diff --git a/testprogs/findalldevstest-perf.c b/testprogs/findalldevstest-perf.c
new file mode 100644
index 0000000..4087566
--- /dev/null
+++ b/testprogs/findalldevstest-perf.c
@@ -0,0 +1,100 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+  #include <windows.h>
+#else
+  #include <unistd.h>
+  #include <sys/resource.h>
+#endif
+
+#include <pcap.h>
+
+#include "varattrs.h"
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+#include "portability.h"
+#endif
+
+int main(int argc _U_, char **argv _U_)
+{
+  pcap_if_t *alldevs;
+  int exit_status = 0;
+  char errbuf[PCAP_ERRBUF_SIZE+1];
+#ifdef _WIN32
+  FILETIME start_ktime, start_utime, end_ktime, end_utime;
+  FILETIME dummy1, dummy2;
+  ULARGE_INTEGER start_kticks, end_kticks, start_uticks, end_uticks;
+  ULONGLONG ktime, utime, tottime;
+#else
+  struct rusage start_rusage, end_rusage;
+  struct timeval ktime, utime, tottime;
+#endif
+
+#ifdef _WIN32
+  if (!GetProcessTimes(GetCurrentProcess(), &dummy1, &dummy2,
+                       &start_ktime, &start_utime))
+  {
+    fprintf(stderr, "GetProcessTimes() fails at start\n");
+    exit(1);
+  }
+  start_kticks.LowPart = start_ktime.dwLowDateTime;
+  start_kticks.HighPart = start_ktime.dwHighDateTime;
+  start_uticks.LowPart = start_utime.dwLowDateTime;
+  start_uticks.HighPart = start_utime.dwHighDateTime;
+#else
+  if (getrusage(RUSAGE_SELF, &start_rusage) == -1) {
+    fprintf(stderr, "getrusage() fails at start\n");
+    exit(1);
+  }
+#endif
+  for (int i = 0; i < 500; i++)
+  {
+    if (pcap_findalldevs(&alldevs, errbuf) == -1)
+    {
+      fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+      exit(1);
+    }
+    pcap_freealldevs(alldevs);
+  }
+
+#ifdef _WIN32
+  if (!GetProcessTimes(GetCurrentProcess(), &dummy1, &dummy2,
+                       &end_ktime, &end_utime))
+  {
+    fprintf(stderr, "GetProcessTimes() fails at end\n");
+    exit(1);
+  }
+  end_kticks.LowPart = end_ktime.dwLowDateTime;
+  end_kticks.HighPart = end_ktime.dwHighDateTime;
+  end_uticks.LowPart = end_utime.dwLowDateTime;
+  end_uticks.HighPart = end_utime.dwHighDateTime;
+  ktime = end_kticks.QuadPart - start_kticks.QuadPart;
+  utime = end_uticks.QuadPart - start_uticks.QuadPart;
+  tottime = ktime + utime;
+  printf("Total CPU secs: kernel %g, user %g, total %g\n",
+      ((double)ktime) / 10000000.0,
+      ((double)utime) / 10000000.0,
+      ((double)tottime) / 10000000.0);
+#else
+  if (getrusage(RUSAGE_SELF, &end_rusage) == -1) {
+    fprintf(stderr, "getrusage() fails at end\n");
+    exit(1);
+  }
+  timersub(&end_rusage.ru_stime, &start_rusage.ru_stime, &ktime);
+  timersub(&end_rusage.ru_utime, &start_rusage.ru_utime, &utime);
+  timeradd(&ktime, &utime, &tottime);
+  printf("Total CPU secs: kernel %g, user %g, total %g\n",
+      (double)ktime.tv_sec + ((double)ktime.tv_usec / 1000000.0),
+      (double)utime.tv_sec + ((double)utime.tv_usec / 1000000.0),
+      (double)tottime.tv_sec + ((double)tottime.tv_usec / 1000000.0));
+#endif
+  exit(exit_status);
+}
diff --git a/testprogs/findalldevstest.c b/testprogs/findalldevstest.c
index e535e25..092fd04 100644
--- a/testprogs/findalldevstest.c
+++ b/testprogs/findalldevstest.c
@@ -19,6 +19,7 @@
 
 #include <pcap.h>
 
+#include "varattrs.h"
 #include "pcap/funcattrs.h"
 
 static int ifprint(pcap_if_t *d);
@@ -94,7 +95,11 @@
 }
 #endif
 
+#ifdef ENABLE_REMOTE
 int main(int argc, char **argv)
+#else
+int main(int argc _U_, char **argv _U_)
+#endif
 {
   pcap_if_t *alldevs;
   pcap_if_t *d;
@@ -152,8 +157,24 @@
   {
     if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
     {
-      fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
-      exit_status = 2;
+      /*
+       * XXX - this doesn't distinguish between "a real error
+       * occurred" and "this interface doesn't *have* an IPv4
+       * address".  The latter shouldn't be treated as an error.
+       *
+       * We look for the interface name, followed by a colon and
+       * a space, and, if we find it,w e see if what follows it
+       * is "no IPv4 address assigned".
+       */
+      size_t devnamelen = strlen(alldevs->name);
+      if (strncmp(errbuf, alldevs->name, devnamelen) == 0 &&
+          strncmp(errbuf + devnamelen, ": ", 2) == 0 &&
+          strcmp(errbuf + devnamelen + 2, "no IPv4 address assigned") == 0)
+        printf("Preferred device is not on an IPv4 network\n");
+      else {
+        fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
+        exit_status = 2;
+      }
     }
     else
     {
diff --git a/testprogs/fuzz/CMakeLists.txt b/testprogs/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..67250cc
--- /dev/null
+++ b/testprogs/fuzz/CMakeLists.txt
@@ -0,0 +1,43 @@
+add_executable(fuzz_pcap onefile.c fuzz_pcap.c)
+target_link_libraries(fuzz_pcap ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set_target_properties(fuzz_pcap PROPERTIES
+      LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_filter onefile.c fuzz_filter.c)
+target_link_libraries(fuzz_filter ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set_target_properties(fuzz_filter PROPERTIES
+      LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_both onefile.c fuzz_both.c)
+target_link_libraries(fuzz_both ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set_target_properties(fuzz_both PROPERTIES
+      LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+if(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
+add_executable(fuzz_rclient onefile.c fuzz_rclient.c)
+target_link_libraries(fuzz_rclient ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set_target_properties(fuzz_rclient PROPERTIES
+      LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_rserver onefile.c fuzz_rserver.c ../../rpcapd/daemon.c)
+check_function_exists(crypt HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+if(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+    set(HAVE_CRYPT TRUE)
+else(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+     set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} crypt)
+endif(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+target_link_libraries(fuzz_rserver ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+  set_target_properties(fuzz_rserver PROPERTIES
+      LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+endif(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
diff --git a/testprogs/fuzz/fuzz_both.c b/testprogs/fuzz/fuzz_both.c
new file mode 100644
index 0000000..59e3d40
--- /dev/null
+++ b/testprogs/fuzz/fuzz_both.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+
+static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
+    FILE * fd;
+    if (remove(name) != 0) {
+        if (errno != ENOENT) {
+            printf("failed remove, errno=%d\n", errno);
+            return -1;
+        }
+    }
+    fd = fopen(name, "wb");
+    if (fd == NULL) {
+        printf("failed open, errno=%d\n", errno);
+        return -2;
+    }
+    if (fwrite (Data, 1, Size, fd) != Size) {
+        fclose(fd);
+        return -3;
+    }
+    fclose(fd);
+    return 0;
+}
+
+void fuzz_openFile(const char * name) {
+    if (outfile != NULL) {
+        fclose(outfile);
+    }
+    outfile = fopen(name, "w");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    pcap_t * pkts;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    const u_char *pkt;
+    struct pcap_pkthdr *header;
+    int r;
+    size_t filterSize;
+    char * filter;
+    struct bpf_program bpf;
+
+
+    //initialize output file
+    if (outfile == NULL) {
+        outfile = fopen("/dev/null", "w");
+        if (outfile == NULL) {
+            return 0;
+        }
+    }
+
+    if (Size < 1) {
+        return 0;
+    }
+    filterSize = Data[0];
+    if (Size < 1+filterSize || filterSize == 0) {
+        return 0;
+    }
+
+    //rewrite buffer to a file as libpcap does not have buffer inputs
+    if (bufferToFile("/tmp/fuzz.pcap", Data+1+filterSize, Size-(1+filterSize)) < 0) {
+        return 0;
+    }
+
+    //initialize structure
+    pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
+    if (pkts == NULL) {
+        fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
+        return 0;
+    }
+
+    filter = malloc(filterSize);
+    memcpy(filter, Data+1, filterSize);
+    //null terminate string
+    filter[filterSize-1] = 0;
+
+    if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
+        //loop over packets
+        r = pcap_next_ex(pkts, &header, &pkt);
+        while (r > 0) {
+            //checks filter
+            fprintf(outfile, "packet length=%d/%d filter=%d\n",header->caplen, header->len, pcap_offline_filter(&bpf, header, pkt));
+            r = pcap_next_ex(pkts, &header, &pkt);
+        }
+        //close structure
+        pcap_close(pkts);
+        pcap_freecode(&bpf);
+    }
+    else {
+        pcap_close(pkts);
+    }
+    free(filter);
+
+    return 0;
+}
diff --git a/testprogs/fuzz/fuzz_both.options b/testprogs/fuzz/fuzz_both.options
new file mode 100644
index 0000000..0824b19
--- /dev/null
+++ b/testprogs/fuzz/fuzz_both.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/testprogs/fuzz/fuzz_filter.c b/testprogs/fuzz/fuzz_filter.c
new file mode 100644
index 0000000..de35067
--- /dev/null
+++ b/testprogs/fuzz/fuzz_filter.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pcap/pcap.h>
+
+void fuzz_openFile(const char * name){
+    //do nothing
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    pcap_t * pkts;
+    struct bpf_program bpf;
+    char * filter;
+
+    //we need at least 1 byte for linktype
+    if (Size < 1) {
+        return 0;
+    }
+
+    //initialize structure snaplen = 65535
+    pkts = pcap_open_dead(Data[Size-1], 0xFFFF);
+    if (pkts == NULL) {
+        printf("pcap_open_dead failed\n");
+        return 0;
+    }
+    filter = malloc(Size);
+    memcpy(filter, Data, Size);
+    //null terminate string
+    filter[Size-1] = 0;
+
+    if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
+        pcap_setfilter(pkts, &bpf);
+        pcap_close(pkts);
+        pcap_freecode(&bpf);
+    }
+    else {
+        pcap_close(pkts);
+    }
+    free(filter);
+
+    return 0;
+}
diff --git a/testprogs/fuzz/fuzz_filter.options b/testprogs/fuzz/fuzz_filter.options
new file mode 100644
index 0000000..9fda93f
--- /dev/null
+++ b/testprogs/fuzz/fuzz_filter.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 4096
diff --git a/testprogs/fuzz/fuzz_pcap.c b/testprogs/fuzz/fuzz_pcap.c
new file mode 100644
index 0000000..fba5312
--- /dev/null
+++ b/testprogs/fuzz/fuzz_pcap.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+
+static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
+    FILE * fd;
+    if (remove(name) != 0) {
+        if (errno != ENOENT) {
+            printf("failed remove, errno=%d\n", errno);
+            return -1;
+        }
+    }
+    fd = fopen(name, "wb");
+    if (fd == NULL) {
+        printf("failed open, errno=%d\n", errno);
+        return -2;
+    }
+    if (fwrite (Data, 1, Size, fd) != Size) {
+        fclose(fd);
+        return -3;
+    }
+    fclose(fd);
+    return 0;
+}
+
+void fuzz_openFile(const char * name) {
+    if (outfile != NULL) {
+        fclose(outfile);
+    }
+    outfile = fopen(name, "w");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    pcap_t * pkts;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    const u_char *pkt;
+    struct pcap_pkthdr *header;
+    struct pcap_stat stats;
+    int r;
+
+    //initialize output file
+    if (outfile == NULL) {
+        outfile = fopen("/dev/null", "w");
+        if (outfile == NULL) {
+            return 0;
+        }
+    }
+
+    //rewrite buffer to a file as libpcap does not have buffer inputs
+    if (bufferToFile("/tmp/fuzz.pcap", Data, Size) < 0) {
+        return 0;
+    }
+
+    //initialize structure
+    pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
+    if (pkts == NULL) {
+        fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
+        return 0;
+    }
+
+    //loop over packets
+    r = pcap_next_ex(pkts, &header, &pkt);
+    while (r > 0) {
+        //TODO pcap_offline_filter
+        fprintf(outfile, "packet length=%d/%d\n",header->caplen, header->len);
+        r = pcap_next_ex(pkts, &header, &pkt);
+    }
+    if (pcap_stats(pkts, &stats) == 0) {
+        fprintf(outfile, "number of packets=%d\n", stats.ps_recv);
+    }
+    //close structure
+    pcap_close(pkts);
+
+    return 0;
+}
diff --git a/testprogs/fuzz/fuzz_pcap.options b/testprogs/fuzz/fuzz_pcap.options
new file mode 100644
index 0000000..0824b19
--- /dev/null
+++ b/testprogs/fuzz/fuzz_pcap.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/testprogs/fuzz/fuzz_rclient.c b/testprogs/fuzz/fuzz_rclient.c
new file mode 100644
index 0000000..b5a6a91
--- /dev/null
+++ b/testprogs/fuzz/fuzz_rclient.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+struct pcap_rmtauth auth;
+
+void fuzz_openFile(const char * name) {
+    if (outfile != NULL) {
+        fclose(outfile);
+    }
+    outfile = fopen(name, "w");
+    auth.type = RPCAP_RMTAUTH_PWD;
+    auth.username = "user";
+    auth.password = "pass";
+}
+
+void sock_initfuzz(const uint8_t *Data, size_t Size);
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    pcap_t * pkts;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    const u_char *pkt;
+    struct pcap_pkthdr *header;
+    struct pcap_stat stats;
+    int r;
+
+    //initialization
+    if (outfile == NULL) {
+        fuzz_openFile("/dev/null");
+    }
+
+    sock_initfuzz(Data, Size);
+    //initialize structure
+    pkts = pcap_open("rpcap://127.0.0.1/fuzz.pcap", 0, 0, 1000, &auth, errbuf);
+    if (pkts == NULL) {
+        fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
+        return 0;
+    }
+
+    //loop over packets
+    r = pcap_next_ex(pkts, &header, &pkt);
+    while (r > 0) {
+        fprintf(outfile, "packet length=%d/%d\n",header->caplen, header->len);
+        r = pcap_next_ex(pkts, &header, &pkt);
+    }
+    if (pcap_stats(pkts, &stats) == 0) {
+        fprintf(outfile, "number of packets=%d\n", stats.ps_recv);
+    }
+    //close structure
+    pcap_close(pkts);
+
+    return 0;
+}
diff --git a/testprogs/fuzz/fuzz_rserver.c b/testprogs/fuzz/fuzz_rserver.c
new file mode 100644
index 0000000..c79a373
--- /dev/null
+++ b/testprogs/fuzz/fuzz_rserver.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+
+void fuzz_openFile(const char * name) {
+    if (outfile != NULL) {
+        fclose(outfile);
+    }
+    outfile = fopen(name, "w");
+}
+
+typedef enum {
+    LOGPRIO_DEBUG,
+    LOGPRIO_INFO,
+    LOGPRIO_WARNING,
+    LOGPRIO_ERROR
+} log_priority;
+
+void rpcapd_log(log_priority priority, const char *message, ...)
+{
+    va_list ap;
+
+    va_start(ap, message);
+    fprintf(outfile, "rpcapd[%d]:", priority);
+    vfprintf(outfile, message, ap);
+    putc('\n', outfile);
+    va_end(ap);
+}
+
+void sock_initfuzz(const uint8_t *Data, size_t Size);
+int daemon_serviceloop(int sockctrl, int isactive, char *passiveClients, int nullAuthAllowed, int uses_ssl);
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    int sock;
+
+    //initialization
+    if (outfile == NULL) {
+        fuzz_openFile("/dev/null");
+    }
+
+    sock_initfuzz(Data, Size);
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    if (sock == INVALID_SOCKET) {
+        abort();
+    }
+    //dummy socket, active, null auth allowed, no ssl
+    daemon_serviceloop(sock, 1, malloc(0), 1, 0);
+
+    return 0;
+}
diff --git a/testprogs/fuzz/onefile.c b/testprogs/fuzz/onefile.c
new file mode 100644
index 0000000..690a63b
--- /dev/null
+++ b/testprogs/fuzz/onefile.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+void fuzz_openFile(const char * name);
+
+int main(int argc, char** argv)
+{
+    FILE * fp;
+    uint8_t *Data;
+    size_t Size;
+
+    if (argc == 3) {
+        fuzz_openFile(argv[2]);
+    } else if (argc != 2) {
+        return 1;
+    }
+    //opens the file, get its size, and reads it into a buffer
+    fp = fopen(argv[1], "rb");
+    if (fp == NULL) {
+        return 2;
+    }
+    if (fseek(fp, 0L, SEEK_END) != 0) {
+        fclose(fp);
+        return 2;
+    }
+    Size = ftell(fp);
+    if (Size == (size_t) -1) {
+        fclose(fp);
+        return 2;
+    }
+    if (fseek(fp, 0L, SEEK_SET) != 0) {
+        fclose(fp);
+        return 2;
+    }
+    Data = malloc(Size);
+    if (Data == NULL) {
+        fclose(fp);
+        return 2;
+    }
+    if (fread(Data, Size, 1, fp) != 1) {
+        fclose(fp);
+        free(Data);
+        return 2;
+    }
+
+    //launch fuzzer
+    LLVMFuzzerTestOneInput(Data, Size);
+    free(Data);
+    fclose(fp);
+    return 0;
+}
+
diff --git a/testprogs/opentest.c b/testprogs/opentest.c
index bad38eb..a441dda 100644
--- a/testprogs/opentest.c
+++ b/testprogs/opentest.c
@@ -45,7 +45,7 @@
   #include "portability.h"
 #endif
 
-#define MAXIMUM_SNAPLEN		65535
+#define MAXIMUM_SNAPLEN		262144
 
 static char *program_name;
 
@@ -81,7 +81,7 @@
 		switch (op) {
 
 		case 'i':
-			device = optarg;
+			device = strdup(optarg);
 			break;
 
 		case 'I':
@@ -95,13 +95,19 @@
 
 		case 's': {
 			char *end;
+			long long_snaplen;
 
-			snaplen = strtol(optarg, &end, 0);
+			long_snaplen = strtol(optarg, &end, 0);
 			if (optarg == end || *end != '\0'
-			    || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
+			    || long_snaplen < 0
+			    || long_snaplen > MAXIMUM_SNAPLEN)
 				error("invalid snaplen %s", optarg);
-			else if (snaplen == 0)
-				snaplen = MAXIMUM_SNAPLEN;
+			else {
+				if (snaplen == 0)
+					snaplen = MAXIMUM_SNAPLEN;
+				else
+					snaplen = (int)long_snaplen;
+			}
 			break;
 		}
 
@@ -186,6 +192,7 @@
 		else
 			printf("%s opened successfully\n", device);
 	}
+	free(device);
 	pcap_close(pd);
 	exit(status < 0 ? 1 : 0);
 }
diff --git a/testprogs/reactivatetest.c b/testprogs/reactivatetest.c
index d7f3e32..a9c987a 100644
--- a/testprogs/reactivatetest.c
+++ b/testprogs/reactivatetest.c
@@ -51,7 +51,6 @@
 		if (pd == NULL) {
 			error("Neither lo0 nor lo could be opened: %s",
 			    ebuf);
-			return 2;
 		}
 	}
 	status = pcap_activate(pd);
diff --git a/testprogs/selpolltest.c b/testprogs/selpolltest.c
index 329281d..569c829 100644
--- a/testprogs/selpolltest.c
+++ b/testprogs/selpolltest.c
@@ -69,13 +69,13 @@
 	register int op;
 	bpf_u_int32 localnet, netmask;
 	register char *cp, *cmdbuf, *device;
-	int doselect, dopoll, dotimeout, dononblock;
+	int doselect, dopoll, dotimeout, dononblock, quiet;
 	const char *mechanism;
 	struct bpf_program fcode;
 	char ebuf[PCAP_ERRBUF_SIZE];
 	pcap_if_t *devlist;
 	int selectable_fd;
-	struct timeval *required_timeout;
+	const struct timeval *required_timeout;
 	int status;
 	int packet_count;
 
@@ -85,13 +85,14 @@
 	mechanism = NULL;
 	dotimeout = 0;
 	dononblock = 0;
+	quiet = 0;
 	if ((cp = strrchr(argv[0], '/')) != NULL)
 		program_name = cp + 1;
 	else
 		program_name = argv[0];
 
 	opterr = 0;
-	while ((op = getopt(argc, argv, "i:sptn")) != -1) {
+	while ((op = getopt(argc, argv, "i:sptnq")) != -1) {
 		switch (op) {
 
 		case 'i':
@@ -116,6 +117,10 @@
 			dononblock = 1;
 			break;
 
+		case 'q':
+			quiet = 1;
+			break;
+
 		default:
 			usage();
 			/* NOTREACHED */
@@ -196,6 +201,7 @@
 		for (;;) {
 			fd_set setread, setexcept;
 			struct timeval seltimeout;
+			struct timeval *timeoutp;
 
 			FD_ZERO(&setread);
 			if (selectable_fd != -1) {
@@ -203,6 +209,7 @@
 				FD_ZERO(&setexcept);
 				FD_SET(selectable_fd, &setexcept);
 			}
+			required_timeout = pcap_get_required_select_timeout(pd);
 			if (dotimeout) {
 				seltimeout.tv_sec = 0;
 				if (required_timeout != NULL &&
@@ -210,37 +217,34 @@
 					seltimeout.tv_usec = required_timeout->tv_usec;
 				else
 					seltimeout.tv_usec = 1000;
-				status = select(selectable_fd + 1, &setread,
-				    NULL, &setexcept, &seltimeout);
+				timeoutp = &seltimeout;
 			} else if (required_timeout != NULL) {
 				seltimeout = *required_timeout;
-				status = select(selectable_fd + 1, &setread,
-				    NULL, &setexcept, &seltimeout);
+				timeoutp = &seltimeout;
 			} else {
-				status = select((selectable_fd == -1) ?
-				    0 : selectable_fd + 1, &setread,
-				    NULL, &setexcept, NULL);
+				timeoutp = NULL;
 			}
+			status = select((selectable_fd == -1) ?
+			    0 : selectable_fd + 1, &setread, NULL, &setexcept,
+			    timeoutp);
 			if (status == -1) {
 				printf("Select returns error (%s)\n",
 				    strerror(errno));
 			} else {
-				if (selectable_fd == -1) {
-					if (status != 0)
-						printf("Select returned a descriptor\n");
-				} else {
+				if (!quiet) {
 					if (status == 0)
 						printf("Select timed out: ");
-					else
+					else{
 						printf("Select returned a descriptor: ");
-					if (FD_ISSET(selectable_fd, &setread))
-						printf("readable, ");
-					else
-						printf("not readable, ");
-					if (FD_ISSET(selectable_fd, &setexcept))
-						printf("exceptional condition\n");
-					else
-						printf("no exceptional condition\n");
+						if (FD_ISSET(selectable_fd, &setread))
+							printf("readable, ");
+						else
+							printf("not readable, ");
+						if (FD_ISSET(selectable_fd, &setexcept))
+							printf("exceptional condition\n");
+						else
+							printf("no exceptional condition\n");
+					}
 				}
 				packet_count = 0;
 				status = pcap_dispatch(pd, -1, countme,
@@ -268,11 +272,12 @@
 
 			fd.fd = selectable_fd;
 			fd.events = POLLIN;
+			required_timeout = pcap_get_required_select_timeout(pd);
 			if (dotimeout)
 				polltimeout = 1;
 			else if (required_timeout != NULL &&
 			    required_timeout->tv_usec >= 1000)
-				polltimeout = required_timeout->tv_usec/1000;
+				polltimeout = (int)(required_timeout->tv_usec/1000);
 			else
 				polltimeout = -1;
 			status = poll(&fd, (selectable_fd == -1) ? 0 : 1, polltimeout);
@@ -280,10 +285,7 @@
 				printf("Poll returns error (%s)\n",
 				    strerror(errno));
 			} else {
-				if (selectable_fd == -1) {
-					if (status != 0)
-						printf("Poll returned a descriptor\n");
-				} else {
+				if (!quiet) {
 					if (status == 0)
 						printf("Poll timed out\n");
 					else {
@@ -349,7 +351,7 @@
 		/*
 		 * Error.  Report it.
 		 */
-		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
+		(void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
 		    program_name, pcap_geterr(pd));
 	}
 	pcap_close(pd);
@@ -367,7 +369,7 @@
 static void
 usage(void)
 {
-	(void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
+	(void)fprintf(stderr, "Usage: %s [ -sptnq ] [ -i interface ] [expression]\n",
 	    program_name);
 	exit(1);
 }
@@ -415,7 +417,7 @@
 copy_argv(register char **argv)
 {
 	register char **p;
-	register u_int len = 0;
+	register size_t len = 0;
 	char *buf;
 	char *src, *dst;
 
diff --git a/testprogs/threadsignaltest.c b/testprogs/threadsignaltest.c
index a60bb49..c9ade76 100644
--- a/testprogs/threadsignaltest.c
+++ b/testprogs/threadsignaltest.c
@@ -157,7 +157,7 @@
 		} else
 			printf("No packets seen by pcap_dispatch\n");
 	}
-	if (status == -2) {
+	if (status == PCAP_ERROR_BREAK) {
 		/*
 		 * We got interrupted, so perhaps we didn't
 		 * manage to finish a line we were printing.
@@ -167,11 +167,11 @@
 		printf("Loop got broken\n");
 	}
 	(void)fflush(stdout);
-	if (status == -1) {
+	if (status == PCAP_ERROR) {
 		/*
 		 * Error.  Report it.
 		 */
-		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
+		(void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
 		    program_name, pcap_geterr(pd));
 	}
 	return 0;
@@ -182,7 +182,7 @@
 {
 	register int op;
 	register char *cp, *cmdbuf, *device;
-	int immediate = 0;
+	int do_wakeup = 1;
 	pcap_if_t *devlist;
 	bpf_u_int32 localnet, netmask;
 	struct bpf_program fcode;
@@ -200,13 +200,17 @@
 		program_name = argv[0];
 
 	opterr = 0;
-	while ((op = getopt(argc, argv, "i:")) != -1) {
+	while ((op = getopt(argc, argv, "i:n")) != -1) {
 		switch (op) {
 
 		case 'i':
 			device = optarg;
 			break;
 
+		case 'n':
+			do_wakeup = 0;
+			break;
+
 		default:
 			usage();
 			/* NOTREACHED */
@@ -229,12 +233,6 @@
 	if (status != 0)
 		error("%s: pcap_set_snaplen failed: %s",
 			    device, pcap_statustostr(status));
-	if (immediate) {
-		status = pcap_set_immediate_mode(pd, 1);
-		if (status != 0)
-			error("%s: pcap_set_immediate_mode failed: %s",
-			    device, pcap_statustostr(status));
-	}
 	status = pcap_set_timeout(pd, 5*60*1000);
 	if (status != 0)
 		error("%s: pcap_set_timeout failed: %s",
@@ -280,21 +278,39 @@
 		error("Can't create capture thread: %s", strerror(status));
 #endif
 	sleep_secs(60);
+	printf("Doing pcap_breakloop()\n");
 	pcap_breakloop(pd);
+	if (do_wakeup) {
+		/*
+		 * Force a wakeup in the capture thread.
+		 *
+		 * On some platforms, with some devices,, pcap_breakloop()
+		 * can't do that itself.  On Windows, poke the device's
+		 * event handle; on UN*X, send a SIGUSR1 to the thread.
+		 */
 #ifdef _WIN32
-	printf("Setting event\n");
-	if (!SetEvent(pcap_getevent(pd)))
-		error("Can't set event for pcap_t: %s",
-		    win32_strerror(GetLastError()));
+		printf("Setting event\n");
+		if (!SetEvent(pcap_getevent(pd)))
+			error("Can't set event for pcap_t: %s",
+			    win32_strerror(GetLastError()));
+#else
+		printf("Sending SIGUSR1\n");
+		status = pthread_kill(capture_thread, SIGUSR1);
+		if (status != 0)
+			warning("Can't interrupt capture thread: %s",
+			strerror(status));
+#endif
+	}
+
+	/*
+	 * Now wait for the capture thread to terminate.
+	 */
+#ifdef _WIN32
 	if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED)
 		error("Wait for thread termination failed: %s",
 		    win32_strerror(GetLastError()));
 	CloseHandle(capture_thread);
 #else
-	printf("Sending SIGUSR1\n");
-	status = pthread_kill(capture_thread, SIGUSR1);
-	if (status != 0)
-		warning("Can't interrupt capture thread: %s", strerror(status));
 	status = pthread_join(capture_thread, &retval);
 	if (status != 0)
 		error("Wait for thread termination failed: %s",
@@ -317,7 +333,7 @@
 static void
 usage(void)
 {
-	(void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n",
+	(void)fprintf(stderr, "Usage: %s [ -n ] [ -i interface ] [ expression ]\n",
 	    program_name);
 	exit(1);
 }
@@ -365,7 +381,7 @@
 copy_argv(register char **argv)
 {
 	register char **p;
-	register u_int len = 0;
+	register size_t len = 0;
 	char *buf;
 	char *src, *dst;
 
diff --git a/testprogs/valgrindtest.c b/testprogs/valgrindtest.c
index 104ef6a..058b18b 100644
--- a/testprogs/valgrindtest.c
+++ b/testprogs/valgrindtest.c
@@ -59,6 +59,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <limits.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -99,6 +100,23 @@
 
 #endif
 
+/*
+ * Squelch a warning.
+ *
+ * We include system headers to be able to directly set the filter to
+ * a program with uninitialized content, to make sure what we're testing
+ * is Valgrind's checking of the system call to set the filter, and we
+ * also include <pcap.h> to open the device in the first place, and that
+ * means that we may get collisions between their definitions of
+ * BPF_STMT and BPF_JUMP - and do, in fact, get them on Linux (the
+ * definitons may be semantically the same, but that's not sufficient to
+ * avoid the warnings, as the preprocessor doesn't know that u_short is
+ * just unsigned short).
+ *
+ * So we undefine BPF_STMT and BPF_JUMP to avoid the warning.
+ */
+#undef BPF_STMT
+#undef BPF_JUMP
 #include <pcap.h>
 
 static char *program_name;
@@ -132,11 +150,21 @@
 	if (fstat(fd, &buf) < 0)
 		error("can't stat %s: %s", fname, pcap_strerror(errno));
 
+	/*
+	 * _read(), on Windows, has an unsigned int byte count and an
+	 * int return value, so we can't handle a file bigger than
+	 * INT_MAX - 1 bytes (and have no reason to do so; a filter *that*
+	 * big will take forever to compile).  (The -1 is for the '\0' at
+	 * the end of the string.)
+	 */
+	if (buf.st_size > INT_MAX - 1)
+		error("%s is larger than %d bytes; that's too large", fname,
+		    INT_MAX - 1);
 	cp = malloc((u_int)buf.st_size + 1);
 	if (cp == NULL)
 		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
 			fname, pcap_strerror(errno));
-	cc = read(fd, cp, (u_int)buf.st_size);
+	cc = (int)read(fd, cp, (u_int)buf.st_size);
 	if (cc < 0)
 		error("read %s: %s", fname, pcap_strerror(errno));
 	if (cc != buf.st_size)
@@ -196,7 +224,7 @@
 copy_argv(register char **argv)
 {
 	register char **p;
-	register u_int len = 0;
+	register size_t len = 0;
 	char *buf;
 	char *src, *dst;
 
@@ -421,7 +449,7 @@
 	(void)fprintf(stderr, "%s, with %s\n", program_name,
 	    pcap_lib_version());
 	(void)fprintf(stderr,
-	    "Usage: %s [-aI] [ -F file ] [ -I interface ] [ expression ]\n",
+	    "Usage: %s [-aI] [ -F file ] [ -i interface ] [ expression ]\n",
 	    program_name);
 	exit(1);
 }
diff --git a/testprogs/visopts.py b/testprogs/visopts.py
index 03aa804..80c1463 100755
--- a/testprogs/visopts.py
+++ b/testprogs/visopts.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 """
-This program parse the output from pcap_compile() to visualize the CFG after
+This program parses the output from pcap_compile() to visualize the CFG after
 each optimize phase.
 
 Usage guide:
@@ -15,23 +15,24 @@
        testprogs/filtertest -g EN10MB host 192.168.1.1 > a.txt
 3. Send a.txt to this program's standard input
        cat a.txt | testprogs/visopts.py
+   (Graphviz must be installed)
 4. Step 2&3 can be merged:
        testprogs/filtertest -g EN10MB host 192.168.1.1 | testprogs/visopts.py
 5. The standard output is something like this:
        generated files under directory: /tmp/visopts-W9ekBw
          the directory will be removed when this programs finished.
        open this link: http://localhost:39062/expr1.html
-6. Using open link at the 3rd line `http://localhost:39062/expr1.html'
+6. Open the URL at the 3rd line in a browser.
 
 Note:
-1. The CFG is translated to SVG an document, expr1.html embeded them as external
-   document. If you open expr1.html as local file using file:// protocol, some
-   browsers will deny such requests so the web pages will not shown properly.
-   For chrome, you can run it using following command to avoid this:
+1. The CFG is translated to SVG images, expr1.html embeds them as external
+   documents. If you open expr1.html as local file using file:// protocol, some
+   browsers will deny such requests so the web page will not work properly.
+   For Chrome, you can run it using the following command to avoid this:
        chromium --disable-web-security
-   That's why this program start a localhost http server.
-2. expr1.html use jquery from http://ajax.googleapis.com, so you need internet
-   access to show the web page.
+   That's why this program starts a localhost HTTP server.
+2. expr1.html uses jQuery from https://ajax.googleapis.com, so it needs Internet
+   access to work.
 """
 
 import sys, os
@@ -52,7 +53,7 @@
       }
     </style>
 
-    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
+    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
     <!--script type="text/javascript" src="./jquery.min.js"/></script-->
     <script type="text/javascript">
       var expr = '$expr';
@@ -142,7 +143,7 @@
       }
       function load_left(index) {
         var url = gurl(index);
-        var frag = "<embed id='leftsvgc'  type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        var frag = "<embed id='leftsvgc'  type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
         $$("#lsvg").html(frag);
         $$("#lcomment").html(logs[index]);
         $$("#lsvglink").attr("href", url);
@@ -151,7 +152,7 @@
       }
       function load_right(index) {
         var url = gurl(index);
-        var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
         $$("#rsvg").html(frag);
         $$("#rcomment").html(logs[index]);
         $$("#rsvglink").attr("href", url);
@@ -255,7 +256,13 @@
             log += line
 
         if indot == 2:
-            p = subprocess.Popen(['dot', '-Tsvg'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+            try:
+                p = subprocess.Popen(['dot', '-Tsvg'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+            except OSError as ose:
+                print "Failed to run 'dot':", ose
+                print "(Is Graphviz installed?)"
+                exit(1)
+
             svg = p.communicate(dot)[0]
             with file("expr1_g%03d.svg" % (gid), "wt") as f:
                 f.write(svg)
@@ -296,7 +303,7 @@
     os.chdir(tempfile.mkdtemp(prefix="visopts-"))
     atexit.register(shutil.rmtree, os.getcwd())
     print "generated files under directory: %s" % os.getcwd()
-    print "  the directory will be removed when this programs finished."
+    print "  the directory will be removed when this program has finished."
 
     if not render_on_html(sys.stdin):
         return 1
diff --git a/testprogs/writecaptest.c b/testprogs/writecaptest.c
new file mode 100644
index 0000000..4db532c
--- /dev/null
+++ b/testprogs/writecaptest.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#ifdef _WIN32
+  #include "getopt.h"
+#else
+  #include <unistd.h>
+#endif
+#include <errno.h>
+#ifndef _WIN32
+  #include <signal.h>
+#endif
+#include <sys/types.h>
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+  #include "portability.h"
+#endif
+
+static char *program_name;
+
+/* 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);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+#ifdef _WIN32
+static BOOL WINAPI
+stop_capture(DWORD ctrltype _U_)
+{
+	pcap_breakloop(pd);
+	return TRUE;
+}
+#else
+static void
+stop_capture(int signum _U_)
+{
+	pcap_breakloop(pd);
+}
+#endif
+
+static long
+parse_interface_number(const char *device)
+{
+	const char *p;
+	long devnum;
+	char *end;
+
+	/*
+	 * Search for a colon, terminating any scheme at the beginning
+	 * of the device.
+	 */
+	p = strchr(device, ':');
+	if (p != NULL) {
+		/*
+		 * We found it.  Is it followed by "//"?
+		 */
+		p++;	/* skip the : */
+		if (strncmp(p, "//", 2) == 0) {
+			/*
+			 * Yes.  Search for the next /, at the end of the
+			 * authority part of the URL.
+			 */
+			p += 2;	/* skip the // */
+			p = strchr(p, '/');
+			if (p != NULL) {
+				/*
+				 * OK, past the / is the path.
+				 */
+				device = p + 1;
+			}
+		}
+	}
+	devnum = strtol(device, &end, 10);
+	if (device != end && *end == '\0') {
+		/*
+		 * It's all-numeric, but is it a valid number?
+		 */
+		if (devnum <= 0) {
+			/*
+			 * No, it's not an ordinal.
+			 */
+			error("Invalid adapter index");
+		}
+		return (devnum);
+	} else {
+		/*
+		 * It's not all-numeric; return -1, so our caller
+		 * knows that.
+		 */
+		return (-1);
+	}
+}
+
+static char *
+find_interface_by_number(long devnum)
+{
+	pcap_if_t *dev, *devlist;
+	long i;
+	char ebuf[PCAP_ERRBUF_SIZE];
+	char *device;
+	int status;
+
+	status = pcap_findalldevs(&devlist, ebuf);
+	if (status < 0)
+		error("%s", ebuf);
+	/*
+	 * Look for the devnum-th entry in the list of devices (1-based).
+	 */
+	for (i = 0, dev = devlist; i < devnum-1 && dev != NULL;
+	    i++, dev = dev->next)
+		;
+	if (dev == NULL)
+		error("Invalid adapter index");
+	device = strdup(dev->name);
+	pcap_freealldevs(devlist);
+	return (device);
+}
+
+static pcap_t *
+open_interface(const char *device, int snaplen_set, int snaplen, char *ebuf)
+{
+	pcap_t *pc;
+	int status;
+	char *cp;
+
+	pc = pcap_create(device, ebuf);
+	if (pc == NULL) {
+		/*
+		 * If this failed with "No such device", that means
+		 * the interface doesn't exist; return NULL, so that
+		 * the caller can see whether the device name is
+		 * actually an interface index.
+		 */
+		if (strstr(ebuf, "No such device") != NULL)
+			return (NULL);
+		error("%s", ebuf);
+	}
+	if (snaplen_set) {
+		status = pcap_set_snaplen(pc, snaplen);
+		if (status != 0)
+			error("%s: pcap_set_snaplen failed: %s",
+			    device, pcap_statustostr(status));
+	}
+	status = pcap_set_timeout(pc, 100);
+	if (status != 0)
+		error("%s: pcap_set_timeout failed: %s",
+		    device, pcap_statustostr(status));
+	status = pcap_activate(pc);
+	if (status < 0) {
+		/*
+		 * pcap_activate() failed.
+		 */
+		cp = pcap_geterr(pc);
+		if (status == PCAP_ERROR)
+			error("%s", cp);
+		else if (status == PCAP_ERROR_NO_SUCH_DEVICE) {
+			/*
+			 * Return an error for our caller to handle.
+			 */
+			snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
+			    device, pcap_statustostr(status), cp);
+		} else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
+			error("%s: %s\n(%s)", device,
+			    pcap_statustostr(status), cp);
+		else
+			error("%s: %s", device,
+			    pcap_statustostr(status));
+		pcap_close(pc);
+		return (NULL);
+	} else if (status > 0) {
+		/*
+		 * pcap_activate() succeeded, but it's warning us
+		 * of a problem it had.
+		 */
+		cp = pcap_geterr(pc);
+		if (status == PCAP_WARNING)
+			warning("%s", cp);
+		else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
+		         *cp != '\0')
+			warning("%s: %s\n(%s)", device,
+			    pcap_statustostr(status), cp);
+		else
+			warning("%s: %s", device,
+			    pcap_statustostr(status));
+	}
+	return (pc);
+}
+
+#define COMMAND_OPTIONS	"DLi:s:w:y:"
+
+int
+main(int argc, char **argv)
+{
+	int op;
+	char *cp, *cmdbuf = NULL, *device, *end, *savefile = NULL;
+	int snaplen = 0;
+	int snaplen_set = 0;
+	pcap_if_t *devlist;
+	long devnum;
+	int show_interfaces = 0;
+	int show_dlt_types = 0;
+	int ndlts;
+	int *dlts;
+	bpf_u_int32 localnet, netmask;
+	struct bpf_program fcode;
+	char ebuf[PCAP_ERRBUF_SIZE];
+#ifndef _WIN32
+	struct sigaction action;
+#endif
+	int dlt;
+	const char *dlt_name = NULL;
+	int status;
+	pcap_dumper_t *pdd;
+
+	device = NULL;
+	if ((cp = strrchr(argv[0], '/')) != NULL)
+		program_name = cp + 1;
+	else
+		program_name = argv[0];
+
+	opterr = 0;
+	while ((op = getopt(argc, argv, COMMAND_OPTIONS)) != -1) {
+		switch (op) {
+
+		case 'D':
+			show_interfaces = 1;
+			break;
+
+		case 'L':
+			show_dlt_types = 1;
+			break;
+
+		case 'i':
+			device = optarg;
+			break;
+
+		case 's':
+			snaplen = (int)strtol(optarg, &end, 0);
+			if (optarg == end || *end != '\0' || snaplen < 0)
+				error("invalid snaplen %s (must be >= 0)",
+				    optarg);
+			snaplen_set = 1;
+			break;
+
+		case 'w':
+			savefile = optarg;
+			break;
+
+		case 'y':
+			dlt_name = optarg;
+			break;
+
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	}
+
+	if (show_interfaces) {
+		pcap_if_t *dev;
+		int i;
+
+		if (pcap_findalldevs(&devlist, ebuf) < 0)
+			error("%s", ebuf);
+		for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) {
+			printf("%d.%s", i+1, dev->name);
+			if (dev->description != NULL)
+				printf(" (%s)", dev->description);
+			printf("\n");
+		}
+		pcap_freealldevs(devlist);
+		return (0);
+	}
+
+	if (device == NULL) {
+		if (pcap_findalldevs(&devlist, ebuf) == -1)
+			error("%s", ebuf);
+		if (devlist == NULL)
+			error("no interfaces available for capture");
+		device = strdup(devlist->name);
+		pcap_freealldevs(devlist);
+	}
+	if (show_dlt_types) {
+		pd = pcap_create(device, ebuf);
+		if (pd == NULL)
+			error("%s", ebuf);
+		status = pcap_activate(pd);
+		if (status < 0) {
+			/*
+			 * pcap_activate() failed.
+			 */
+			error("%s: %s\n(%s)", device,
+			    pcap_statustostr(status), pcap_geterr(pd));
+		}
+		ndlts = pcap_list_datalinks(pd, &dlts);
+		if (ndlts < 0) {
+			/*
+			 * pcap_list_datalinks() failed.
+			 */
+			error("%s: %s\n(%s)", device,
+			    pcap_statustostr(status), pcap_geterr(pd));
+		}
+		for (int i = 0; i < ndlts; i++) {
+			dlt_name = pcap_datalink_val_to_name(dlts[i]);
+			if (dlt_name == NULL)
+				printf("DLT %d", dlts[i]);
+			else
+				printf("%s", dlt_name);
+			printf("\n");
+		}
+		pcap_free_datalinks(dlts);
+		pcap_close(pd);
+		return 0;
+	}
+
+	if (savefile == NULL)
+		error("no savefile specified");
+
+	*ebuf = '\0';
+
+	pd = open_interface(device, snaplen_set, snaplen, ebuf);
+	if (pd == NULL) {
+		/*
+		 * That failed because the interface couldn't be found.
+		 *
+		 * If we can get a list of interfaces, and the interface name
+		 * is purely numeric, try to use it as a 1-based index
+		 * in the list of interfaces.
+		 */
+		devnum = parse_interface_number(device);
+		if (devnum == -1) {
+			/*
+			 * It's not a number; just report
+			 * the open error and fail.
+			 */
+			error("%s", ebuf);
+		}
+
+		/*
+		 * OK, it's a number; try to find the
+		 * interface with that index, and try
+		 * to open it.
+		 *
+		 * find_interface_by_number() exits if it
+		 * couldn't be found.
+		 */
+		device = find_interface_by_number(devnum);
+		pd = open_interface(device, snaplen_set, snaplen, ebuf);
+		if (pd == NULL)
+			error("%s", ebuf);
+	}
+
+	if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+		localnet = 0;
+		netmask = 0;
+		warning("%s", ebuf);
+	}
+
+	if (dlt_name != NULL) {
+		dlt = pcap_datalink_name_to_val(dlt_name);
+		if (dlt == PCAP_ERROR)
+			error("%s isn't a valid DLT name", dlt_name);
+		if (pcap_set_datalink(pd, dlt) == PCAP_ERROR)
+			error("%s: %s", device, pcap_geterr(pd));
+	}
+
+	/*
+	 * Don't set a filter unless we were given one on the
+	 * command line; if capturing doesn't work, or doesn't
+	 * use the snapshot length, without a filter, that's
+	 * a bug.
+	 */
+	if (optind < argc) {
+		cmdbuf = copy_argv(&argv[optind]);
+
+		if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+			error("%s", pcap_geterr(pd));
+
+		if (pcap_setfilter(pd, &fcode) < 0)
+			error("%s", pcap_geterr(pd));
+	}
+
+	pdd = pcap_dump_open(pd, savefile);
+	if (pdd == NULL)
+		error("%s", pcap_geterr(pd));
+
+#ifdef _WIN32
+	SetConsoleCtrlHandler(stop_capture, TRUE);
+#else
+	action.sa_handler = stop_capture;
+	sigemptyset(&action.sa_mask);
+	action.sa_flags = 0;
+	if (sigaction(SIGINT, &action, NULL) == -1)
+		error("Can't catch SIGINT: %s\n", strerror(errno));
+#endif
+
+	printf("Listening on %s, link-type ", device);
+	dlt = pcap_datalink(pd);
+	dlt_name = pcap_datalink_val_to_name(dlt);
+	if (dlt_name == NULL)
+		printf("DLT %d", dlt);
+	else
+		printf("%s", dlt_name);
+	printf("\n");
+	for (;;) {
+		status = pcap_dispatch(pd, -1, pcap_dump, (u_char *)pdd);
+		if (status < 0)
+			break;
+		if (status != 0) {
+			printf("%d packets seen\n", status);
+			struct pcap_stat ps;
+			pcap_stats(pd, &ps);
+			printf("%d ps_recv, %d ps_drop, %d ps_ifdrop\n",
+			    ps.ps_recv, ps.ps_drop, ps.ps_ifdrop);
+		}
+	}
+	if (status == -2) {
+		/*
+		 * We got interrupted, so perhaps we didn't
+		 * manage to finish a line we were printing.
+		 * Print an extra newline, just in case.
+		 */
+		putchar('\n');
+		printf("Broken out of loop from SIGINT handler\n");
+	}
+	(void)fflush(stdout);
+	if (status == -1) {
+		/*
+		 * Error.  Report it.
+		 */
+		(void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
+		    program_name, pcap_geterr(pd));
+	}
+	pcap_close(pd);
+	if (cmdbuf != NULL) {
+		pcap_freecode(&fcode);
+		free(cmdbuf);
+	}
+	exit(status == -1 ? 1 : 0);
+}
+
+static void
+usage(void)
+{
+	(void)fprintf(stderr, "Usage: %s -D -L [ -i interface ] [ -s snaplen ] [ -w file ] [ -y dlt ] [expression]\n",
+	    program_name);
+	exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+	va_list ap;
+
+	(void)fprintf(stderr, "%s: ", program_name);
+	va_start(ap, fmt);
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	if (*fmt) {
+		fmt += strlen(fmt);
+		if (fmt[-1] != '\n')
+			(void)fputc('\n', stderr);
+	}
+	exit(1);
+	/* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+	va_list ap;
+
+	(void)fprintf(stderr, "%s: WARNING: ", program_name);
+	va_start(ap, fmt);
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	if (*fmt) {
+		fmt += strlen(fmt);
+		if (fmt[-1] != '\n')
+			(void)fputc('\n', stderr);
+	}
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+	register char **p;
+	register size_t len = 0;
+	char *buf;
+	char *src, *dst;
+
+	p = argv;
+	if (*p == 0)
+		return 0;
+
+	while (*p)
+		len += strlen(*p++) + 1;
+
+	buf = (char *)malloc(len);
+	if (buf == NULL)
+		error("copy_argv: malloc");
+
+	p = argv;
+	dst = buf;
+	while ((src = *p++) != NULL) {
+		while ((*dst++ = *src++) != '\0')
+			;
+		dst[-1] = ' ';
+	}
+	dst[-1] = '\0';
+
+	return buf;
+}