Upgrade to libpcap-1.10.4

This a breaking change and depends on changes to fuchsia.git found in
https://fuchsia-review.googlesource.com/c/fuchsia/+/917279
(change ID is Ib87596690d5fa272a00803af06e67e9e1746a6d0).

Bug: 133434
Change-Id: Ibd8fca1ab0bd8498121dae9586a905e7bad2c3b5
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/github.com/the-tcpdump-group/libpcap/+/916389
Reviewed-by: Chris Lewis <cflewis@google.com>
Reviewed-by: Brian Bosak <bbosak@google.com>
diff --git a/CREDITS b/CREDITS
index d01e832..4b820ee 100644
--- a/CREDITS
+++ b/CREDITS
@@ -33,6 +33,7 @@
     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>
+    Biswapriyo Nath               <nathbappai at gmail dot com>
     blazeable                     <blazeable at blazeable dot eu>
     bleader                       <bleader at ratonland dot org>
     Brent Cook                    <brent at boundary dot com>
@@ -58,6 +59,7 @@
     Dave Barach                   <dave at barachs dot net>
     David Clark                   <david dot clark at datasoft dot com>
     David Kaelbling               <drk at sgi dot com>
+    David Karoly                  <david dot karoly at outlook 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>
@@ -68,11 +70,13 @@
     Dustin Spicuzza               <dustin at virtualroadside dot com>
     dzejarczech                   <dzejarczech at sourceforge dot net>
     Edward Sheldrake              <ejs1920 at sourceforge dot net>
+    Eli Schwartz                  <eschwartz93 at gmail dot com>
     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>
+    fghzxm                        <fghzxm at outlook dot com>
     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>
@@ -132,6 +136,7 @@
     Kris Katterjohn               <katterjohn at gmail dot com>
     Krzysztof Halasa              <khc at pm dot waw dot pl>
     Lennert Buytenhek             <buytenh at wantstofly dot org>
+    Li kunyu                      <kunyu at nfschina dot com>
     lixiaoyan                     <lixiaoyan at google dot com>
     Lorenzo Cavallaro             <sullivan at sikurezza dot org>
     Loris Degioanni               <loris at netgroup-serv dot polito dot it>
@@ -157,6 +162,7 @@
     Max Laier                     <max at love2party dot net>
     Michal Kubecek                <mkubecek at suse dot cz>
     Michal Labedzki               <michal dot labedzki at tieto dot com>
+    Michal Ruprich                <michalruprich at gmail dot com>
     Michal Sekletar               <msekleta at redhat dot com>
     Mike Frysinger                <vapier at gmail dot com>
     Mike Kershaw                  <dragorn at kismetwireless dot net>
@@ -166,6 +172,7 @@
     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>
+    nic-kaczinsky                 <68271784+nic-kaczinsky at users dot noreply dot github dot com>
     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>
@@ -181,7 +188,7 @@
     Ø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>
+    Patrick McHardy               <kaber at trash dot 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>
@@ -193,6 +200,7 @@
     Philippe Antoine              <contact at catenacyber dot fr>
     Phil Wood                     <cpw at lanl dot gov>
     Rafal Maszkowski              <rzm at icm dot edu dot pl>
+    ramin                         <lordrasmus at gmail dot com>
                                   <rcb-isis at users dot sourceforge dot net>
     Richard Stearn                <richard at rns-stearn dot demon dot co dot uk>
     Rick Jones                    <raj at cup dot hp dot com>
@@ -208,6 +216,7 @@
     Sebastian Krahmer             <krahmer at cs dot uni-potsdam dot de>
     Sebastien Roy                 <Sebastien dot Roy at Sun dot COM>
     Sepherosa Ziehau              <sepherosa at gmail dot com>
+    Shane Kerr                    <shane at time-travellers dot org>
     Shaun Clowes                  <delius at progsoc dot uts dot edu dot au>
     solofox                       <wensg100 at sina dot com>
     Solomon Peachy                <pizza at shaftnet dot org>
diff --git a/README.md b/README.md
index d89e3bb..e38b9a1 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@
 system-dependent packet capture modules in each application.
 
 ```text
-formerly from 	Lawrence Berkeley National Laboratory
+formerly from	Lawrence Berkeley National Laboratory
 		Network Research Group <libpcap@ee.lbl.gov>
 		ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
 ```
@@ -52,12 +52,10 @@
 with the underlying kernel subsystem, but this is not yet implemented.
 
 BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, OpenBSD, DragonFly
-BSD, and macOS; an older, modified and undocumented version is standard
-in AIX.  {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the packetfilter
-interface but has been extended to accept BPF filters (which libpcap
-utilizes).  Also, you can add BPF filter support to Ultrix using the
-kernel source and/or object patches available
-[here](https://www.tcpdump.org/other/bpfext42.tar.Z).
+BSD, macOS, and Solaris 11; an older, modified and undocumented version
+is standard in AIX.  {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the
+packetfilter interface but has been extended to accept BPF filters
+(which libpcap utilizes).
 
 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
diff --git a/RELEASE_VERSION b/RELEASE_VERSION
index 4dae298..18b3114 100644
--- a/RELEASE_VERSION
+++ b/RELEASE_VERSION
@@ -1 +1 @@
-1.10.1
+1.10.4
diff --git a/charconv.h b/charconv.h
index a37d424..93103d4 100644
--- a/charconv.h
+++ b/charconv.h
@@ -32,8 +32,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef charonv_h
-#define charonv_h
+#ifndef charconv_h
+#define charconv_h
 
 #ifdef _WIN32
 extern wchar_t *cp_to_utf_16le(UINT codepage, const char *cp_string, DWORD flags);
@@ -41,4 +41,4 @@
 extern void utf_8_to_acp_truncated(char *);
 #endif
 
-#endif
+#endif /* charconv_h */
diff --git a/config.h.in b/config.h.in
index a1e371a..282a955 100644
--- a/config.h.in
+++ b/config.h.in
@@ -72,8 +72,8 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
-/* Define to 1 if you have the `dag' library (-ldag). */
-#undef HAVE_LIBDAG
+/* Define to 1 if you have the `bsd' library (-lbsd). */
+#undef HAVE_LIBBSD
 
 /* if libdlpi exists */
 #undef HAVE_LIBDLPI
@@ -132,9 +132,6 @@
 /* Define to 1 if you have the <net/pfilt.h> header file. */
 #undef HAVE_NET_PFILT_H
 
-/* Define to 1 if you have the <net/pfvar.h> header file. */
-#undef HAVE_NET_PFVAR_H
-
 /* Define to 1 if you have the <net/raw.h> header file. */
 #undef HAVE_NET_RAW_H
 
@@ -144,9 +141,6 @@
 /* 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
 
@@ -271,9 +265,6 @@
 /* IPv6 */
 #undef INET6
 
-/* path for device for USB sniffing */
-#undef LINUX_USB_MON_DEV
-
 /* Define to 1 if netinet/ether.h declares `ether_hostton' */
 #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
 
@@ -328,6 +319,12 @@
 /* target host supports RDMA sniffing */
 #undef PCAP_SUPPORT_RDMASNIFF
 
+/* The size of `const void *', as computed by sizeof. */
+#undef SIZEOF_CONST_VOID_P
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
diff --git a/diag-control.h b/diag-control.h
index 47d31b9..ae2641b 100644
--- a/diag-control.h
+++ b/diag-control.h
@@ -37,12 +37,12 @@
 
 #include "pcap/compiler-tests.h"
 
-#ifndef _MSC_VER
+#if PCAP_IS_AT_LEAST_CLANG_VERSION(2,8) || PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
   /*
    * Clang and GCC both support this way of putting pragmas into #defines.
-   * We don't use it unless we have a compiler that supports it; the
-   * warning-suppressing pragmas differ between Clang and GCC, so we test
-   * for both of those separately.
+   * We use it only if we have a compiler that supports it; see below
+   * for the code that uses it and the #defines that control whether
+   * that code is used.
    */
   #define PCAP_DO_PRAGMA(x) _Pragma (#x)
 #endif
@@ -86,7 +86,51 @@
 /*
  * Suppress Flex, narrowing, and deprecation warnings.
  */
-#if defined(_MSC_VER)
+#if PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+  /*
+   * This is Clang 2.8 or later; we can use "clang diagnostic
+   * ignored -Wxxx" and "clang diagnostic push/pop".
+   *
+   * Suppress -Wdocumentation warnings; GCC doesn't support -Wdocumentation,
+   * at least according to the GCC 7.3 documentation.  Apparently, Flex
+   * generates code that upsets at least some versions of Clang's
+   * -Wdocumentation.
+   *
+   * (This could be clang-cl, which defines _MSC_VER, so test this
+   * before testing _MSC_VER.)
+   */
+  #define DIAG_OFF_FLEX \
+    PCAP_DO_PRAGMA(clang diagnostic push) \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wsign-compare") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdocumentation") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-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)
+  #define DIAG_OFF_FORMAT_TRUNCATION
+  #define DIAG_ON_FORMAT_TRUNCATION
+#elif defined(_MSC_VER)
   /*
    * This is Microsoft Visual Studio; we can use __pragma(warning(disable:XXXX))
    * and __pragma(warning(push/pop)).
@@ -121,45 +165,8 @@
     __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
-   * ignored -Wxxx" and "clang diagnostic push/pop".
-   *
-   * Suppress -Wdocumentation warnings; GCC doesn't support -Wdocumentation,
-   * at least according to the GCC 7.3 documentation.  Apparently, Flex
-   * generates code that upsets at least some versions of Clang's
-   * -Wdocumentation.
-   */
-  #define DIAG_OFF_FLEX \
-    PCAP_DO_PRAGMA(clang diagnostic push) \
-    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wsign-compare") \
-    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdocumentation") \
-    PCAP_DO_PRAGMA(clang diagnostic ignored "-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)
+  #define DIAG_OFF_FORMAT_TRUNCATION
+  #define DIAG_ON_FORMAT_TRUNCATION
 #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
   /*
    * This is GCC 4.6 or later, or a compiler claiming to be that.
@@ -188,6 +195,22 @@
     PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")
   #define DIAG_ON_DEPRECATION \
     PCAP_DO_PRAGMA(GCC diagnostic pop)
+
+  /*
+   * Suppress format-truncation= warnings.
+   * GCC 7.1 had introduced this warning option. Earlier versions (at least
+   * one particular copy of GCC 4.6.4) treat the request as a warning.
+   */
+  #if PCAP_IS_AT_LEAST_GNUC_VERSION(7,1)
+    #define DIAG_OFF_FORMAT_TRUNCATION \
+      PCAP_DO_PRAGMA(GCC diagnostic push) \
+      PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wformat-truncation=")
+    #define DIAG_ON_FORMAT_TRUNCATION \
+      PCAP_DO_PRAGMA(GCC diagnostic pop)
+  #else
+   #define DIAG_OFF_FORMAT_TRUNCATION
+   #define DIAG_ON_FORMAT_TRUNCATION
+  #endif
 #else
   /*
    * Neither Visual Studio, nor Clang 2.8 or later, nor GCC 4.6 or later
@@ -200,6 +223,8 @@
   #define DIAG_ON_NARROWING
   #define DIAG_OFF_DEPRECATION
   #define DIAG_ON_DEPRECATION
+  #define DIAG_OFF_FORMAT_TRUNCATION
+  #define DIAG_ON_FORMAT_TRUNCATION
 #endif
 
 #ifdef YYBYACC
@@ -219,21 +244,21 @@
    * In addition, the generated code may have functions with unreachable
    * code, so suppress warnings about those.
    */
-  #if defined(_MSC_VER)
+  #if PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+    /*
+     * This is Clang 2.8 or later (including clang-cl, so test this
+     * before _MSC_VER); we can use "clang diagnostic ignored -Wxxx".
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshadow") \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+  #elif defined(_MSC_VER)
     /*
      * This is Microsoft Visual Studio; we can use
      * __pragma(warning(disable:XXXX)).
      */
     #define DIAG_OFF_BISON_BYACC \
       __pragma(warning(disable:4702))
-  #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
-    /*
-     * This is Clang 2.8 or later; we can use "clang diagnostic
-     * ignored -Wxxx".
-     */
-    #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshadow") \
-      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
   #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
     /*
      * This is GCC 4.6 or later, or a compiler claiming to be that.
@@ -257,7 +282,14 @@
    * 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)
+  #if PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+    /*
+     * This is Clang 2.8 or later (including clang-cl, so test this
+     * before _MSC_VER); we can use "clang diagnostic ignored -Wxxx".
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+  #elif defined(_MSC_VER)
     /*
      * This is Microsoft Visual Studio; we can use
      * __pragma(warning(disable:XXXX)).
@@ -270,13 +302,6 @@
       __pragma(warning(disable:4242)) \
       __pragma(warning(disable:4244)) \
       __pragma(warning(disable:4702))
-  #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
-    /*
-     * This is Clang 2.8 or later; we can use "clang diagnostic
-     * ignored -Wxxx".
-     */
-    #define DIAG_OFF_BISON_BYACC \
-      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
   #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
     /*
      * This is GCC 4.6 or later, or a compiler claiming to be that.
@@ -294,4 +319,20 @@
   #endif
 #endif
 
+/*
+ * GCC needs this on AIX for longjmp().
+ */
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(5,1)
+  /*
+   * Beware that the effect of this builtin is more than just squelching the
+   * warning! GCC trusts it enough for the process to segfault if the control
+   * flow reaches the builtin (an infinite empty loop in the same context would
+   * squelch the warning and ruin the process too, albeit in a different way).
+   * So please remember to use this very carefully.
+   */
+  #define PCAP_UNREACHABLE __builtin_unreachable();
+#else
+  #define PCAP_UNREACHABLE
+#endif
+
 #endif /* _diag_control_h */
diff --git a/doc/README.capture-module b/doc/README.capture-module
deleted file mode 100644
index e13eaf3..0000000
--- a/doc/README.capture-module
+++ /dev/null
@@ -1,353 +0,0 @@
-		    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/extract.h b/extract.h
index e776a9e..33579b1 100644
--- a/extract.h
+++ b/extract.h
@@ -127,7 +127,7 @@
  * cast the pointer to point to one of those, and fetch through it;
  * the GCC manual doesn't appear to explicitly say that
  * __attribute__((packed)) causes the compiler to generate unaligned-safe
- * code, but it apppears to do so.
+ * code, but it appears to do so.
  *
  * We do this in case the compiler can generate code using those
  * instructions to do an unaligned load and pass stuff to "ntohs()" or
diff --git a/fmtutils.c b/fmtutils.c
index 5c7ddad..2d35762 100644
--- a/fmtutils.c
+++ b/fmtutils.c
@@ -270,13 +270,21 @@
     const char *fmt, ...)
 {
 	va_list ap;
+
+	va_start(ap, fmt);
+	pcap_vfmt_errmsg_for_errno(errbuf, errbuflen, errnum, fmt, ap);
+	va_end(ap);
+}
+
+void
+pcap_vfmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
+    const char *fmt, va_list ap)
+{
 	size_t msglen;
 	char *p;
 	size_t errbuflen_remaining;
 
-	va_start(ap, fmt);
-	vsnprintf(errbuf, errbuflen, fmt, ap);
-	va_end(ap);
+	(void)vsnprintf(errbuf, errbuflen, fmt, ap);
 	msglen = strlen(errbuf);
 
 	/*
@@ -378,6 +386,16 @@
     const char *fmt, ...)
 {
 	va_list ap;
+
+	va_start(ap, fmt);
+	pcap_vfmt_errmsg_for_win32_err(errbuf, errbuflen, errnum, fmt, ap);
+	va_end(ap);
+}
+
+void
+pcap_vfmt_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;
@@ -385,9 +403,7 @@
 	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);
 
 	/*
diff --git a/fmtutils.h b/fmtutils.h
index ba0f66c..4fa3448 100644
--- a/fmtutils.h
+++ b/fmtutils.h
@@ -34,6 +34,8 @@
 #ifndef fmtutils_h
 #define	fmtutils_h
 
+#include <stdarg.h>	/* we declare varargs functions */
+
 #include "pcap/funcattrs.h"
 
 #ifdef __cplusplus
@@ -44,10 +46,14 @@
 
 void	pcap_fmt_errmsg_for_errno(char *, size_t, int,
     PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+void	pcap_vfmt_errmsg_for_errno(char *, size_t, int,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(4, 0);
 
 #ifdef _WIN32
 void	pcap_fmt_errmsg_for_win32_err(char *, size_t, DWORD,
     PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+void	pcap_vfmt_errmsg_for_win32_err(char *, size_t, DWORD,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(4, 0);
 #endif
 
 #ifdef __cplusplus
diff --git a/ftmacros.h b/ftmacros.h
index 3cd7505..7975463 100644
--- a/ftmacros.h
+++ b/ftmacros.h
@@ -45,7 +45,12 @@
  * namespace to the maximum extent possible"?
  */
 #if defined(sun) || defined(__sun)
-  #define __EXTENSIONS__
+  /*
+   * On Solaris Clang defines __EXTENSIONS__ automatically.
+   */
+  #ifndef __EXTENSIONS__
+    #define __EXTENSIONS__
+  #endif
 
   /*
    * We also need to define _XPG4_2 in order to get
diff --git a/gencode.c b/gencode.c
index efdcb98..496e02f 100644
--- a/gencode.c
+++ b/gencode.c
@@ -1,4 +1,3 @@
-/*#define CHASE_CHAIN*/
 /*
  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
  *	The Regents of the University of California.  All rights reserved.
@@ -24,7 +23,6 @@
 #include <config.h>
 #endif
 
-#include <pcap-types.h>
 #ifdef _WIN32
   #include <ws2tcpip.h>
 #else
@@ -43,25 +41,12 @@
 #include <memory.h>
 #include <setjmp.h>
 #include <stdarg.h>
+#include <stdio.h>
 
 #ifdef MSDOS
 #include "pcap-dos.h"
 #endif
 
-#ifdef HAVE_NET_PFVAR_H
-/*
- * In NetBSD <net/if.h> includes <net/dlt.h>, which is an older version of
- * "pcap/dlt.h" with a lower value of DLT_MATCHING_MAX. Include the headers
- * below before "pcap-int.h", which eventually includes "pcap/dlt.h", which
- * redefines DLT_MATCHING_MAX from what this version of NetBSD has to what
- * this version of libpcap has.
- */
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif /* HAVE_NET_PFVAR_H */
-
 #include "pcap-int.h"
 
 #include "extract.h"
@@ -73,12 +58,13 @@
 #include "ieee80211.h"
 #include "atmuni31.h"
 #include "sunatmpos.h"
+#include "pflog.h"
 #include "ppp.h"
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
 #include "arcnet.h"
+#include "diag-control.h"
 
-#include "grammar.h"
 #include "scanner.h"
 
 #if defined(linux)
@@ -475,6 +461,9 @@
 	va_end(ap);
 	longjmp(cstate->top_ctx, 1);
 	/*NOTREACHED*/
+#ifdef _AIX
+	PCAP_UNREACHABLE
+#endif /* _AIX */
 }
 
 static int init_linktype(compiler_state_t *, pcap_t *);
@@ -521,6 +510,7 @@
 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_pflog_llprefixlen(compiler_state_t *);
 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 *);
@@ -574,7 +564,9 @@
     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);
+#if !defined(NO_PROTOCHAIN)
 static struct block *gen_protochain(compiler_state_t *, bpf_u_int32, int);
+#endif /* !defined(NO_PROTOCHAIN) */
 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 *);
@@ -741,7 +733,7 @@
 	if (!p->activated) {
 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "not-yet-activated pcap_t passed to pcap_compile");
-		return (-1);
+		return (PCAP_ERROR);
 	}
 
 #ifdef _WIN32
@@ -789,7 +781,7 @@
 	if (cstate.snaplen == 0) {
 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snaplen of 0 rejects all packets");
-		rc = -1;
+		rc = PCAP_ERROR;
 		goto quit;
 	}
 
@@ -805,7 +797,7 @@
 	pcap_set_extra(&cstate, scanner);
 
 	if (init_linktype(&cstate, p) == -1) {
-		rc = -1;
+		rc = PCAP_ERROR;
 		goto quit;
 	}
 	if (pcap_parse(scanner, &cstate) != 0) {
@@ -815,7 +807,7 @@
 #endif
 		if (cstate.e != NULL)
 			free(cstate.e);
-		rc = -1;
+		rc = PCAP_ERROR;
 		goto quit;
 	}
 
@@ -824,7 +816,7 @@
 		 * Catch errors reported by gen_retblk().
 		 */
 		if (setjmp(cstate.top_ctx)) {
-			rc = -1;
+			rc = PCAP_ERROR;
 			goto quit;
 		}
 		cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
@@ -833,14 +825,14 @@
 	if (optimize && !cstate.no_optimize) {
 		if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
 			/* Failure */
-			rc = -1;
+			rc = PCAP_ERROR;
 			goto quit;
 		}
 		if (cstate.ic.root == NULL ||
 		    (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;
+			rc = PCAP_ERROR;
 			goto quit;
 		}
 	}
@@ -848,7 +840,7 @@
 	    cstate.ic.root, &len, p->errbuf);
 	if (program->bf_insns == NULL) {
 		/* Failure */
-		rc = -1;
+		rc = PCAP_ERROR;
 		goto quit;
 	}
 	program->bf_len = len;
@@ -886,7 +878,7 @@
 
 	p = pcap_open_dead(linktype_arg, snaplen_arg);
 	if (p == NULL)
-		return (-1);
+		return (PCAP_ERROR);
 	ret = pcap_compile(p, program, buf, optimize, mask);
 	pcap_close(p);
 	return (ret);
@@ -1265,6 +1257,7 @@
 	case DLT_PPP:
 	case DLT_PPP_PPPD:
 	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
+	case DLT_HDLC:			/* NetBSD (Cisco) HDLC */
 	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
 		cstate->off_linktype.constant_part = 2;	/* skip HDLC-like framing */
 		cstate->off_linkpl.constant_part = 4;	/* skip HDLC-like framing and protocol field */
@@ -1513,14 +1506,13 @@
 		cstate->off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
 		break;
 
-#ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
 		cstate->off_linktype.constant_part = 0;
-		cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+		cstate->off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
+		cstate->off_linkpl.is_variable = 1;
 		cstate->off_nl = 0;
 		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
-#endif
 
         case DLT_JUNIPER_MFR:
         case DLT_JUNIPER_MLFR:
@@ -1722,7 +1714,8 @@
 			cstate->off_nl = OFFSET_NOT_SET;
 			cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		} else {
-			bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
+			bpf_set_error(cstate, "unknown data link type %d (min %d, max %d)",
+			    cstate->linktype, DLT_MATCHING_MIN, DLT_MATCHING_MAX);
 			return (-1);
 		}
 		break;
@@ -2344,6 +2337,59 @@
 	}
 }
 
+/*
+ * Load a value relative to the beginning of the link-layer header after the
+ * pflog header.
+ */
+static struct slist *
+gen_load_pflog_llprefixlen(compiler_state_t *cstate)
+{
+	struct slist *s1, *s2;
+
+	/*
+	 * Generate code to load the length of the pflog header into
+	 * the register assigned to hold that length, if one has been
+	 * assigned.  (If one hasn't been assigned, no code we've
+	 * generated uses that prefix, so we don't need to generate any
+	 * code to load it.)
+	 */
+	if (cstate->off_linkpl.reg != -1) {
+		/*
+		 * The length is in the first byte of the header.
+		 */
+		s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+		s1->s.k = 0;
+
+		/*
+		 * Round it up to a multiple of 4.
+		 * Add 3, and clear the lower 2 bits.
+		 */
+		s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+		s2->s.k = 3;
+		sappend(s1, s2);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+		s2->s.k = 0xfffffffc;
+		sappend(s1, s2);
+
+		/*
+		 * Now allocate a register to hold that value and store
+		 * it.
+		 */
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkpl.reg;
+		sappend(s1, s2);
+
+		/*
+		 * Now move it into the X register.
+		 */
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+		sappend(s1, s2);
+
+		return (s1);
+	} else
+		return (NULL);
+}
+
 static struct slist *
 gen_load_prism_llprefixlen(compiler_state_t *cstate)
 {
@@ -2931,6 +2977,10 @@
 	case DLT_PPI:
 		s = gen_load_802_11_header_len(cstate, s, b->stmts);
 		break;
+
+	case DLT_PFLOG:
+		s = gen_load_pflog_llprefixlen(cstate);
+		break;
 	}
 
 	/*
@@ -3166,6 +3216,7 @@
 		/*NOTREACHED*/
 
 	case DLT_C_HDLC:
+	case DLT_HDLC:
 		switch (ll_proto) {
 
 		case LLCSAP_ISONS:
@@ -3395,7 +3446,6 @@
 			return gen_false(cstate);
 		}
 
-#ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
 		/*
 		 * af field is host byte order in contrast to the rest of
@@ -3410,7 +3460,6 @@
 		else
 			return gen_false(cstate);
 		/*NOTREACHED*/
-#endif /* HAVE_NET_PFVAR_H */
 
 	case DLT_ARCNET:
 	case DLT_ARCNET_LINUX:
@@ -5310,21 +5359,15 @@
 	switch (proto) {
 
 	case Q_SCTP:
-		b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_SCTP, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 	case Q_TCP:
-		b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_TCP, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 	case Q_UDP:
-		b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_UDP, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 	case Q_ICMP:
@@ -5351,9 +5394,7 @@
 #endif
 
 	case Q_PIM:
-		b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_PIM, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 #ifndef IPPROTO_VRRP
@@ -5430,18 +5471,14 @@
 #define IPPROTO_AH	51
 #endif
 	case Q_AH:
-		b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_AH, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 #ifndef IPPROTO_ESP
 #define IPPROTO_ESP	50
 #endif
 	case Q_ESP:
-		b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
-		gen_or(b0, b1);
+		b1 = gen_proto(cstate, IPPROTO_ESP, Q_DEFAULT, Q_DEFAULT);
 		break;
 
 	case Q_ISO:
@@ -6035,20 +6072,10 @@
 	return v;
 }
 
-#if 0
-struct stmt *
-gen_joinsp(struct stmt **s, int n)
-{
-	return NULL;
-}
-#endif
-
+#if !defined(NO_PROTOCHAIN)
 static struct block *
 gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
 {
-#ifdef NO_PROTOCHAIN
-	return gen_proto(cstate, v, proto);
-#else
 	struct block *b0, *b;
 	struct slist *s[100];
 	int fix2, fix3, fix4, fix5;
@@ -6342,8 +6369,8 @@
 
 	gen_and(b0, b);
 	return b;
-#endif
 }
+#endif /* !defined(NO_PROTOCHAIN) */
 
 static struct block *
 gen_check_802_11_data_frame(compiler_state_t *cstate)
@@ -6384,9 +6411,7 @@
 gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
 {
 	struct block *b0, *b1;
-#ifndef CHASE_CHAIN
 	struct block *b2;
-#endif
 
 	if (dir != Q_DEFAULT)
 		bpf_error(cstate, "direction applied to 'proto'");
@@ -6418,11 +6443,7 @@
 		 * So we always check for ETHERTYPE_IP.
 		 */
 		b0 = gen_linktype(cstate, ETHERTYPE_IP);
-#ifndef CHASE_CHAIN
 		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;
 
@@ -6484,7 +6505,6 @@
 
 	case Q_IPV6:
 		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
-#ifndef CHASE_CHAIN
 		/*
 		 * Also check for a fragment header before the final
 		 * header.
@@ -6494,9 +6514,6 @@
 		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;
 
@@ -6550,6 +6567,7 @@
 			/*NOTREACHED*/
 
 		case DLT_C_HDLC:
+		case DLT_HDLC:
 			/*
 			 * Cisco uses an Ethertype lookalike - for OSI,
 			 * it's 0xfefe.
@@ -6935,12 +6953,14 @@
 		else
 			bpf_error(cstate, "unknown protocol: %s", name);
 
+#if !defined(NO_PROTOCHAIN)
 	case Q_PROTOCHAIN:
 		real_proto = lookup_proto(cstate, name, proto);
 		if (real_proto >= 0)
 			return gen_protochain(cstate, real_proto, proto);
 		else
 			bpf_error(cstate, "unknown protocol: %s", name);
+#endif /* !defined(NO_PROTOCHAIN) */
 
 	case Q_UNDEF:
 		syntax(cstate);
@@ -7113,8 +7133,10 @@
 	case Q_PROTO:
 		return gen_proto(cstate, v, proto, dir);
 
+#if !defined(NO_PROTOCHAIN)
 	case Q_PROTOCHAIN:
 		return gen_protochain(cstate, v, proto);
+#endif
 
 	case Q_UNDEF:
 		syntax(cstate);
@@ -7968,7 +7990,7 @@
 		default:
 			bpf_error(cstate, "not a broadcast link");
 		}
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_IP:
 		/*
@@ -8300,12 +8322,10 @@
 		}
 		break;
 
-#ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
 		b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
 		    ((dir == 0) ? PF_IN : PF_OUT));
 		break;
-#endif
 
 	case DLT_PPP_PPPD:
 		if (dir) {
@@ -8396,7 +8416,6 @@
 	return (b0);
 }
 
-#ifdef HAVE_NET_PFVAR_H
 /* PF firewall log matched interface */
 struct block *
 gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
@@ -8547,91 +8566,6 @@
 	    (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*/
-}
-
-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*/
-}
-
-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*/
-}
-
-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*/
-}
-
-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*/
-}
-
-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*/
-}
-#endif /* HAVE_NET_PFVAR_H */
 
 /* IEEE 802.11 wireless header */
 struct block *
@@ -8721,7 +8655,7 @@
 			return (b);
 		} else
 			bpf_error(cstate, "ARCnet address used in non-arc expression");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	default:
 		bpf_error(cstate, "aid supported only on ARCnet");
@@ -8757,27 +8691,27 @@
 
 	case Q_ADDR1:
 		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_ADDR2:
 		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_ADDR3:
 		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_ADDR4:
 		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_RA:
 		bpf_error(cstate, "'ra' is only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 
 	case Q_TA:
 		bpf_error(cstate, "'ta' is only supported on 802.11");
- 		/*NOTREACHED*/
+		/*NOTREACHED*/
 	}
 	abort();
 	/*NOTREACHED*/
@@ -8788,7 +8722,7 @@
 {
 	struct block *b0, *b1;
 
-	/* check for VLAN, including QinQ */
+	/* check for VLAN, including 802.1ad and QinQ */
 	b0 = gen_linktype(cstate, ETHERTYPE_8021Q);
 	b1 = gen_linktype(cstate, ETHERTYPE_8021AD);
 	gen_or(b0,b1);
@@ -9095,6 +9029,7 @@
             switch (cstate->linktype) {
 
             case DLT_C_HDLC: /* fall through */
+            case DLT_HDLC:
             case DLT_EN10MB:
             case DLT_NETANALYZER:
             case DLT_NETANALYZER_TRANSPARENT:
diff --git a/gencode.h b/gencode.h
index 053e85f..93ca521 100644
--- a/gencode.h
+++ b/gencode.h
@@ -19,7 +19,19 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#ifndef gencode_h
+#define gencode_h
+
 #include "pcap/funcattrs.h"
+/*
+ * pcap/bpf.h (a public header) needs u_char, u_short and u_int, which can be
+ * made available via either pcap-types.h (a private header) or pcap/pcap.h
+ * (a public header), none of which pcap/bpf.h includes.  Include the private
+ * header to keep things simple, this way this private header should compile
+ * even if included early from another file.
+ */
+#include "pcap-types.h"
+#include "pcap/bpf.h" /* bpf_u_int32 and BPF_MEMWORDS */
 
 /*
  * ATM support:
@@ -400,3 +412,5 @@
 /* XXX */
 #define JT(b)  ((b)->et.succ)
 #define JF(b)  ((b)->ef.succ)
+
+#endif /* gencode_h */
diff --git a/grammar.c b/grammar.c
index 6bfb96c..8a1caeb 100644
--- a/grammar.c
+++ b/grammar.c
@@ -3,9 +3,9 @@
 /* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
 
 #define YYBYACC 1
-#define YYMAJOR 1
-#define YYMINOR 9
-#define YYPATCH 20140715
+#define YYMAJOR 2
+#define YYMINOR 0
+#define YYPATCH 20221106
 
 #define YYEMPTY        (-1)
 #define yyclearin      (yychar = YYEMPTY)
@@ -13,6 +13,9 @@
 #define YYRECOVERING() (yyerrflag != 0)
 #define YYENOMEM       (-2)
 #define YYEOF          0
+#undef YYBTYACC
+#define YYBTYACC 0
+#define YYDEBUGSTR YYPREFIX "debug"
 
 #ifndef yyparse
 #define yyparse    pcap_parse
@@ -62,6 +65,10 @@
 #define yydefred   pcap_defred
 #endif /* yydefred */
 
+#ifndef yystos
+#define yystos     pcap_stos
+#endif /* yystos */
+
 #ifndef yydgoto
 #define yydgoto    pcap_dgoto
 #endif /* yydgoto */
@@ -93,6 +100,19 @@
 #ifndef yyrule
 #define yyrule     pcap_rule
 #endif /* yyrule */
+
+#if YYBTYACC
+
+#ifndef yycindex
+#define yycindex   pcap_cindex
+#endif /* yycindex */
+
+#ifndef yyctable
+#define yyctable   pcap_ctable
+#endif /* yyctable */
+
+#endif /* YYBTYACC */
+
 #define YYPREFIX "pcap_"
 
 #define YYPURE 1
@@ -124,6 +144,13 @@
 #include <config.h>
 #endif
 
+/*
+ * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
+ * (see ftmacros.h), so include it early.
+ */
+#include "gencode.h"
+#include "grammar.h"
+
 #include <stdlib.h>
 
 #ifndef _WIN32
@@ -145,17 +172,11 @@
 
 #include "pcap-int.h"
 
-#include "gencode.h"
-#include "grammar.h"
 #include "scanner.h"
 
-#ifdef HAVE_NET_PFVAR_H
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif
 #include "llc.h"
 #include "ieee80211.h"
+#include "pflog.h"
 #include <pcap/namedb.h>
 
 #ifdef HAVE_OS_PROTO_H
@@ -307,60 +328,87 @@
 	bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
-#ifdef HAVE_NET_PFVAR_H
+static const struct tok pflog_reasons[] = {
+	{ PFRES_MATCH,		"match" },
+	{ PFRES_BADOFF,		"bad-offset" },
+	{ PFRES_FRAG,		"fragment" },
+	{ PFRES_SHORT,		"short" },
+	{ PFRES_NORM,		"normalize" },
+	{ PFRES_MEMORY,		"memory" },
+	{ PFRES_TS,		"bad-timestamp" },
+	{ PFRES_CONGEST,	"congestion" },
+	{ PFRES_IPOPTIONS,	"ip-option" },
+	{ PFRES_PROTCKSUM,	"proto-cksum" },
+	{ PFRES_BADSTATE,	"state-mismatch" },
+	{ PFRES_STATEINS,	"state-insert" },
+	{ PFRES_MAXSTATES,	"state-limit" },
+	{ PFRES_SRCLIMIT,	"src-limit" },
+	{ PFRES_SYNPROXY,	"synproxy" },
+#if defined(__FreeBSD__)
+	{ PFRES_MAPFAILED,	"map-failed" },
+#elif defined(__NetBSD__)
+	{ PFRES_STATELOCKED,	"state-locked" },
+#elif defined(__OpenBSD__)
+	{ PFRES_TRANSLATE,	"translate" },
+	{ PFRES_NOROUTE,	"no-route" },
+#elif defined(__APPLE__)
+	{ PFRES_DUMMYNET,	"dummynet" },
+#endif
+	{ 0, NULL }
+};
+
 static int
 pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
-	const char *reasons[] = PFRES_NAMES;
 	int i;
 
-	for (i = 0; reasons[i]; i++) {
-		if (pcap_strcasecmp(reason, reasons[i]) == 0)
-			return (i);
-	}
-	bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
-	return (-1);
+	i = str2tok(reason, pflog_reasons);
+	if (i == -1)
+		bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
+	return (i);
 }
 
+static const struct tok pflog_actions[] = {
+	{ PF_PASS,		"pass" },
+	{ PF_PASS,		"accept" },	/* alias for "pass" */
+	{ PF_DROP,		"drop" },
+	{ PF_DROP,		"block" },	/* alias for "drop" */
+	{ PF_SCRUB,		"scrub" },
+	{ PF_NOSCRUB,		"noscrub" },
+	{ PF_NAT,		"nat" },
+	{ PF_NONAT,		"nonat" },
+	{ PF_BINAT,		"binat" },
+	{ PF_NOBINAT,		"nobinat" },
+	{ PF_RDR,		"rdr" },
+	{ PF_NORDR,		"nordr" },
+	{ PF_SYNPROXY_DROP,	"synproxy-drop" },
+#if defined(__FreeBSD__)
+	{ PF_DEFER,		"defer" },
+#elif defined(__OpenBSD__)
+	{ PF_DEFER,		"defer" },
+	{ PF_MATCH,		"match" },
+	{ PF_DIVERT,		"divert" },
+	{ PF_RT,		"rt" },
+	{ PF_AFRT,		"afrt" },
+#elif defined(__APPLE__)
+	{ PF_DUMMYNET,		"dummynet" },
+	{ PF_NODUMMYNET,	"nodummynet" },
+	{ PF_NAT64,		"nat64" },
+	{ PF_NONAT64,		"nonat64" },
+#endif
+	{ 0, NULL },
+};
+
 static int
 pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
-	if (pcap_strcasecmp(action, "pass") == 0 ||
-	    pcap_strcasecmp(action, "accept") == 0)
-		return (PF_PASS);
-	else if (pcap_strcasecmp(action, "drop") == 0 ||
-		pcap_strcasecmp(action, "block") == 0)
-		return (PF_DROP);
-#if HAVE_PF_NAT_THROUGH_PF_NORDR
-	else if (pcap_strcasecmp(action, "rdr") == 0)
-		return (PF_RDR);
-	else if (pcap_strcasecmp(action, "nat") == 0)
-		return (PF_NAT);
-	else if (pcap_strcasecmp(action, "binat") == 0)
-		return (PF_BINAT);
-	else if (pcap_strcasecmp(action, "nordr") == 0)
-		return (PF_NORDR);
-#endif
-	else {
-		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
-		return (-1);
-	}
-}
-#else /* !HAVE_NET_PFVAR_H */
-static int
-pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
-{
-	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-	return (-1);
-}
+	int i;
 
-static int
-pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
-{
-	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-	return (-1);
+	i = str2tok(action, pflog_actions);
+	if (i == -1)
+		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
+	return (i);
 }
-#endif /* HAVE_NET_PFVAR_H */
 
 /*
  * For calls that might return an "an error occurred" value.
@@ -369,14 +417,14 @@
 #define CHECK_PTR_VAL(val)	if (val == NULL) YYABORT
 
 DIAG_OFF_BISON_BYACC
-#line 321 "grammar.y"
 #ifdef YYSTYPE
 #undef  YYSTYPE_IS_DECLARED
 #define YYSTYPE_IS_DECLARED 1
 #endif
 #ifndef YYSTYPE_IS_DECLARED
 #define YYSTYPE_IS_DECLARED 1
-typedef union {
+#line 349 "grammar.y"
+typedef union YYSTYPE {
 	int i;
 	bpf_u_int32 h;
 	char *s;
@@ -391,7 +439,7 @@
 	struct block *rblk;
 } YYSTYPE;
 #endif /* !YYSTYPE_IS_DECLARED */
-#line 395 "grammar.c"
+#line 443 "grammar.c"
 
 /* compatibility with bison */
 #ifdef YYPARSE_PARAM
@@ -402,7 +450,7 @@
 #  define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
 # endif
 #else
-# define YYPARSE_DECL() yyparse(void * yyscanner, compiler_state_t * cstate)
+# define YYPARSE_DECL() yyparse(void *yyscanner, compiler_state_t *cstate)
 #endif
 
 /* Parameters sent to lex. */
@@ -414,13 +462,13 @@
 # endif
 # define YYLEX yylex(&yylval, YYLEX_PARAM)
 #else
-# define YYLEX_DECL() yylex(YYSTYPE *yylval, void * yyscanner)
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, void *yyscanner)
 # define YYLEX yylex(&yylval, yyscanner)
 #endif
 
 /* Parameters sent to yyerror. */
 #ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(void * yyscanner, compiler_state_t * cstate, const char *s)
+#define YYERROR_DECL() yyerror(void *yyscanner, compiler_state_t *cstate, const char *s)
 #endif
 #ifndef YYERROR_CALL
 #define YYERROR_CALL(msg) yyerror(yyscanner, cstate, msg)
@@ -550,7 +598,7 @@
 #define AND 376
 #define UMINUS 377
 #define YYERRCODE 256
-typedef short YYINT;
+typedef int YYINT;
 static const YYINT pcap_lhs[] = {                        -1,
     0,    0,   24,    1,    1,    1,    1,    1,   20,   21,
     2,    2,    2,    3,    3,    3,    3,    3,    3,    3,
@@ -631,6 +679,40 @@
     0,  196,    0,  217,    0,   26,   27,  139,  140,  133,
     0,  199,  220,  159,
 };
+#if defined(YYDESTRUCT_CALL) || defined(YYSTYPE_TOSTRING)
+static const YYINT pcap_stos[] = {                        0,
+  379,  403,  265,  266,  269,  270,  271,  272,  273,  274,
+  275,  276,  277,  278,  279,  280,  281,  282,  283,  284,
+  285,  286,  287,  288,  291,  292,  293,  294,  295,  296,
+  297,  298,  299,  300,  310,  321,  322,  323,  324,  325,
+  326,  327,  328,  329,  330,  331,  332,  333,  334,  335,
+  336,  337,  338,  339,  340,  341,  342,  343,  344,  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,   33,   45,
+   40,  380,  384,  385,  387,  388,  392,  393,  395,  398,
+  401,  402,  404,  405,  407,  408,  409,  410,  414,  415,
+  291,  291,  291,  291,  314,  314,  291,  291,  291,  314,
+  420,  314,  419,  398,  401,  398,  398,  398,  297,  314,
+  392,  395,  401,  375,  376,  399,  400,  314,  315,  316,
+  317,  318,  381,  382,  398,  401,  402,  257,  258,  259,
+  260,  261,  263,  264,  267,  268,  289,  290,  301,  302,
+  303,  304,  305,  306,  307,  308,  309,  389,  390,  391,
+  406,  311,  312,  313,  319,  320,  124,   38,   43,   45,
+   42,   47,   62,   61,   60,   37,   94,  396,  397,   91,
+  380,  393,  398,  384,  291,  396,  397,  401,  411,  412,
+  291,  396,  397,  401,  416,  417,  124,   38,   62,   61,
+   60,  394,  398,  392,  381,  384,  398,  401,  402,  381,
+  384,  262,   47,   47,  382,  383,  386,  398,  381,  375,
+  376,  375,  376,  291,  314,  421,  314,  423,  291,  314,
+  424,  390,  392,  392,  392,  392,  392,  392,  392,  392,
+  392,  392,  392,  392,  392,   41,   41,   41,  291,  291,
+  411,  413,  291,  291,  416,  418,  291,  398,  316,  291,
+  291,   41,  399,  400,  258,  258,  257,  257,  302,   93,
+   58,   41,  400,   41,  400,  381,  381,  291,  314,  422,
+  291,  411,  416,   93,
+};
+#endif /* YYDESTRUCT_CALL || YYSTYPE_TOSTRING */
 static const YYINT pcap_dgoto[] = {                       1,
   191,  229,  144,  226,   93,   94,  227,   95,   96,  168,
   169,  170,   97,   98,  212,  132,  188,  189,  100,  136,
@@ -702,6 +784,40 @@
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,
 };
+#if YYBTYACC
+static const YYINT pcap_cindex[] = {                      0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,
+};
+#endif
 static const YYINT pcap_gindex[] = {                      0,
   211,   10, -115,    0,  102,    0,    0,    0,    0,    0,
    46,    0, 1026,  -90,    0,  261,  -87,  -81, 1063,   -2,
@@ -984,6 +1100,145 @@
    -1,   -1,   -1,   -1,   -1,  273,  274,   -1,  301,  302,
   303,  304,  305,  306,  307,  308,  309,
 };
+#if YYBTYACC
+static const YYINT pcap_ctable[] = {                     -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,   -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,   -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,   -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,   -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,   -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,   -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,
+   -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,   -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,   -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,   -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,   -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,   -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,   -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,   -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,   -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,   -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,
+   -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,   -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,   -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,   -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,   -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,   -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,   -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,   -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,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,
+};
+#endif
 #define YYFINAL 1
 #ifndef YYDEBUG
 #define YYDEBUG 0
@@ -994,14 +1249,14 @@
 #if YYDEBUG
 static const char *const pcap_name[] = {
 
-"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-"'!'",0,0,0,"'%'","'&'",0,"'('","')'","'*'","'+'",0,"'-'",0,"'/'",0,0,0,0,0,0,0,
-0,0,0,"':'",0,"'<'","'='","'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,"'['",0,"']'","'^'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,"'|'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+"$end",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'!'",0,
+0,0,"'%'","'&'",0,"'('","')'","'*'","'+'",0,"'-'",0,"'/'",0,0,0,0,0,0,0,0,0,0,
+"':'",0,"'<'","'='","'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,"'['",0,"']'","'^'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+"'|'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"DST","SRC","HOST","GATEWAY","NET",
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,"error","DST","SRC","HOST","GATEWAY","NET",
 "NETMASK","PORT","PORTRANGE","LESS","GREATER","PROTO","PROTOCHAIN","CBYTE",
 "ARP","RARP","IP","SCTP","TCP","UDP","ICMP","IGMP","IGRP","PIM","VRRP","CARP",
 "ATALK","AARP","DECNET","LAT","SCA","MOPRC","MOPDL","TK_BROADCAST",
@@ -1013,9 +1268,13 @@
 "SNP","CSNP","PSNP","STP","IPX","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","LEX_ERROR","OR","AND","UMINUS",0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-"illegal-symbol",
+"SLS","HSIO","HOPC","HDPC","HSLS","LEX_ERROR","OR","AND","UMINUS","$accept",
+"prog","expr","id","nid","pid","term","rterm","qid","head","pqual","dqual",
+"aqual","ndaqual","arth","narth","byteop","pname","relop","irelop","pnum","and",
+"or","paren","not","null","other","pfvar","p80211","pllc","atmtype",
+"atmmultitype","atmfield","atmfieldvalue","atmvalue","atmlistvalue","mtp2type",
+"mtp3field","mtp3fieldvalue","mtp3value","mtp3listvalue","action","reason",
+"type","subtype","type_subtype","dir","illegal-symbol",
 };
 static const char *const pcap_rule[] = {
 "$accept : prog",
@@ -1243,8 +1502,38 @@
 };
 #endif
 
+#if YYDEBUG
 int      yydebug;
-int      yynerrs;
+#endif
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#ifndef YYLLOC_DEFAULT
+#define YYLLOC_DEFAULT(loc, rhs, n) \
+do \
+{ \
+    if (n == 0) \
+    { \
+        (loc).first_line   = YYRHSLOC(rhs, 0).last_line; \
+        (loc).first_column = YYRHSLOC(rhs, 0).last_column; \
+        (loc).last_line    = YYRHSLOC(rhs, 0).last_line; \
+        (loc).last_column  = YYRHSLOC(rhs, 0).last_column; \
+    } \
+    else \
+    { \
+        (loc).first_line   = YYRHSLOC(rhs, 1).first_line; \
+        (loc).first_column = YYRHSLOC(rhs, 1).first_column; \
+        (loc).last_line    = YYRHSLOC(rhs, n).last_line; \
+        (loc).last_column  = YYRHSLOC(rhs, n).last_column; \
+    } \
+} while (0)
+#endif /* YYLLOC_DEFAULT */
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#if YYBTYACC
+
+#ifndef YYLVQUEUEGROWTH
+#define YYLVQUEUEGROWTH 32
+#endif
+#endif /* YYBTYACC */
 
 /* define the initial stack-sizes */
 #ifdef YYSTACKSIZE
@@ -1259,7 +1548,9 @@
 #endif
 #endif
 
+#ifndef YYINITSTACKSIZE
 #define YYINITSTACKSIZE 200
+#endif
 
 typedef struct {
     unsigned stacksize;
@@ -1268,10 +1559,33 @@
     YYINT    *s_last;
     YYSTYPE  *l_base;
     YYSTYPE  *l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    YYLTYPE  *p_base;
+    YYLTYPE  *p_mark;
+#endif
 } YYSTACKDATA;
+#if YYBTYACC
+
+struct YYParseState_s
+{
+    struct YYParseState_s *save;    /* Previously saved parser state */
+    YYSTACKDATA            yystack; /* saved parser stack */
+    int                    state;   /* saved parser state */
+    int                    errflag; /* saved error recovery status */
+    int                    lexeme;  /* saved index of the conflict lexeme in the lexical queue */
+    YYINT                  ctry;    /* saved index in yyctable[] for this conflict */
+};
+typedef struct YYParseState_s YYParseState;
+#endif /* YYBTYACC */
+
+/* For use in generated program */
+#define yydepth (int)(yystack.s_mark - yystack.s_base)
+#if YYBTYACC
+#define yytrial (yyps->save)
+#endif /* YYBTYACC */
 
 #if YYDEBUG
-#include <stdio.h>		/* needed for printf */
+#include <stdio.h>	/* needed for printf */
 #endif
 
 #include <stdlib.h>	/* needed for malloc, etc */
@@ -1284,6 +1598,9 @@
     unsigned newsize;
     YYINT *newss;
     YYSTYPE *newvs;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    YYLTYPE *newps;
+#endif
 
     if ((newsize = data->stacksize) == 0)
         newsize = YYINITSTACKSIZE;
@@ -1307,8 +1624,22 @@
     data->l_base = newvs;
     data->l_mark = newvs + i;
 
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    newps = (YYLTYPE *)realloc(data->p_base, newsize * sizeof(*newps));
+    if (newps == 0)
+        return YYENOMEM;
+
+    data->p_base = newps;
+    data->p_mark = newps + i;
+#endif
+
     data->stacksize = newsize;
     data->s_last = data->s_base + newsize - 1;
+
+#if YYDEBUG
+    if (yydebug)
+        fprintf(stderr, "%sdebug: stack size increased to %d\n", YYPREFIX, newsize);
+#endif
     return 0;
 }
 
@@ -1317,16 +1648,63 @@
 {
     free(data->s_base);
     free(data->l_base);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    free(data->p_base);
+#endif
     memset(data, 0, sizeof(*data));
 }
 #else
 #define yyfreestack(data) /* nothing */
+#endif /* YYPURE || defined(YY_NO_LEAKS) */
+#if YYBTYACC
+
+static YYParseState *
+yyNewState(unsigned size)
+{
+    YYParseState *p = (YYParseState *) malloc(sizeof(YYParseState));
+    if (p == NULL) return NULL;
+
+    p->yystack.stacksize = size;
+    if (size == 0)
+    {
+        p->yystack.s_base = NULL;
+        p->yystack.l_base = NULL;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        p->yystack.p_base = NULL;
 #endif
+        return p;
+    }
+    p->yystack.s_base    = (YYINT *) malloc(size * sizeof(YYINT));
+    if (p->yystack.s_base == NULL) return NULL;
+    p->yystack.l_base    = (YYSTYPE *) malloc(size * sizeof(YYSTYPE));
+    if (p->yystack.l_base == NULL) return NULL;
+    memset(p->yystack.l_base, 0, size * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    p->yystack.p_base    = (YYLTYPE *) malloc(size * sizeof(YYLTYPE));
+    if (p->yystack.p_base == NULL) return NULL;
+    memset(p->yystack.p_base, 0, size * sizeof(YYLTYPE));
+#endif
+
+    return p;
+}
+
+static void
+yyFreeState(YYParseState *p)
+{
+    yyfreestack(&p->yystack);
+    free(p);
+}
+#endif /* YYBTYACC */
 
 #define YYABORT  goto yyabort
 #define YYREJECT goto yyabort
 #define YYACCEPT goto yyaccept
 #define YYERROR  goto yyerrlab
+#if YYBTYACC
+#define YYVALID        do { if (yyps->save)            goto yyvalid; } while(0)
+#define YYVALID_NESTED do { if (yyps->save && \
+                                yyps->save->save == 0) goto yyvalid; } while(0)
+#endif /* YYBTYACC */
 
 int
 YYPARSE_DECL()
@@ -1335,10 +1713,62 @@
     int      yychar;
     YYSTYPE  yyval;
     YYSTYPE  yylval;
+    int      yynerrs;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    YYLTYPE  yyloc; /* position returned by actions */
+    YYLTYPE  yylloc; /* position from the lexer */
+#endif
 
     /* variables for the parser stack */
     YYSTACKDATA yystack;
-    int yym, yyn, yystate;
+#if YYBTYACC
+
+    /* Current parser state */
+    static YYParseState *yyps = 0;
+
+    /* yypath != NULL: do the full parse, starting at *yypath parser state. */
+    static YYParseState *yypath = 0;
+
+    /* Base of the lexical value queue */
+    static YYSTYPE *yylvals = 0;
+
+    /* Current position at lexical value queue */
+    static YYSTYPE *yylvp = 0;
+
+    /* End position of lexical value queue */
+    static YYSTYPE *yylve = 0;
+
+    /* The last allocated position at the lexical value queue */
+    static YYSTYPE *yylvlim = 0;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    /* Base of the lexical position queue */
+    static YYLTYPE *yylpsns = 0;
+
+    /* Current position at lexical position queue */
+    static YYLTYPE *yylpp = 0;
+
+    /* End position of lexical position queue */
+    static YYLTYPE *yylpe = 0;
+
+    /* The last allocated position at the lexical position queue */
+    static YYLTYPE *yylplim = 0;
+#endif
+
+    /* Current position at lexical token queue */
+    static YYINT  *yylexp = 0;
+
+    static YYINT  *yylexemes = 0;
+#endif /* YYBTYACC */
+    int yym, yyn, yystate, yyresult;
+#if YYBTYACC
+    int yynewerrflag;
+    YYParseState *yyerrctx = NULL;
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    YYLTYPE  yyerror_loc_range[3]; /* position of error start/end (0 unused) */
+#endif
 #if YYDEBUG
     const char *yys;
 
@@ -1348,8 +1778,28 @@
         if (yyn >= '0' && yyn <= '9')
             yydebug = yyn - '0';
     }
+    if (yydebug)
+        fprintf(stderr, "%sdebug[<# of symbols on state stack>]\n", YYPREFIX);
+#endif
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    memset(yyerror_loc_range, 0, sizeof(yyerror_loc_range));
 #endif
 
+    yyerrflag = 0;
+    yychar = 0;
+    memset(&yyval,  0, sizeof(yyval));
+    memset(&yylval, 0, sizeof(yylval));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    memset(&yyloc,  0, sizeof(yyloc));
+    memset(&yylloc, 0, sizeof(yylloc));
+#endif
+
+#if YYBTYACC
+    yyps = yyNewState(0); if (yyps == 0) goto yyenomem;
+    yyps->save = 0;
+#endif /* YYBTYACC */
+    yym = 0;
+    /* yyn is set below */
     yynerrs = 0;
     yyerrflag = 0;
     yychar = YYEMPTY;
@@ -1362,6 +1812,9 @@
     if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
     yystack.s_mark = yystack.s_base;
     yystack.l_mark = yystack.l_base;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yystack.p_mark = yystack.p_base;
+#endif
     yystate = 0;
     *yystack.s_mark = 0;
 
@@ -1369,48 +1822,358 @@
     if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
     if (yychar < 0)
     {
-        if ((yychar = YYLEX) < 0) yychar = YYEOF;
+#if YYBTYACC
+        do {
+        if (yylvp < yylve)
+        {
+            /* we're currently re-reading tokens */
+            yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            yylloc = *yylpp++;
+#endif
+            yychar = *yylexp++;
+            break;
+        }
+        if (yyps->save)
+        {
+            /* in trial mode; save scanner results for future parse attempts */
+            if (yylvp == yylvlim)
+            {   /* Enlarge lexical value queue */
+                size_t p = (size_t) (yylvp - yylvals);
+                size_t s = (size_t) (yylvlim - yylvals);
+
+                s += YYLVQUEUEGROWTH;
+                if ((yylexemes = (YYINT *)realloc(yylexemes, s * sizeof(YYINT))) == NULL) goto yyenomem;
+                if ((yylvals   = (YYSTYPE *)realloc(yylvals, s * sizeof(YYSTYPE))) == NULL) goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                if ((yylpsns   = (YYLTYPE *)realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL) goto yyenomem;
+#endif
+                yylvp   = yylve = yylvals + p;
+                yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                yylpp   = yylpe = yylpsns + p;
+                yylplim = yylpsns + s;
+#endif
+                yylexp  = yylexemes + p;
+            }
+            *yylexp = (YYINT) YYLEX;
+            *yylvp++ = yylval;
+            yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            *yylpp++ = yylloc;
+            yylpe++;
+#endif
+            yychar = *yylexp++;
+            break;
+        }
+        /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+        yychar = YYLEX;
+#if YYBTYACC
+        } while (0);
+#endif /* YYBTYACC */
+        if (yychar < 0) yychar = YYEOF;
 #if YYDEBUG
         if (yydebug)
         {
-            yys = yyname[YYTRANSLATE(yychar)];
-            printf("%sdebug: state %d, reading %d (%s)\n",
-                    YYPREFIX, yystate, yychar, yys);
+            if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+            fprintf(stderr, "%s[%d]: state %d, reading token %d (%s)",
+                            YYDEBUGSTR, yydepth, yystate, yychar, yys);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+            if (!yytrial)
+#endif /* YYBTYACC */
+                fprintf(stderr, " <%s>", YYSTYPE_TOSTRING(yychar, yylval));
+#endif
+            fputc('\n', stderr);
         }
 #endif
     }
-    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+#if YYBTYACC
+
+    /* Do we have a conflict? */
+    if (((yyn = yycindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+        yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+    {
+        YYINT ctry;
+
+        if (yypath)
+        {
+            YYParseState *save;
+#if YYDEBUG
+            if (yydebug)
+                fprintf(stderr, "%s[%d]: CONFLICT in state %d: following successful trial parse\n",
+                                YYDEBUGSTR, yydepth, yystate);
+#endif
+            /* Switch to the next conflict context */
+            save = yypath;
+            yypath = save->save;
+            save->save = NULL;
+            ctry = save->ctry;
+            if (save->state != yystate) YYABORT;
+            yyFreeState(save);
+
+        }
+        else
+        {
+
+            /* Unresolved conflict - start/continue trial parse */
+            YYParseState *save;
+#if YYDEBUG
+            if (yydebug)
+            {
+                fprintf(stderr, "%s[%d]: CONFLICT in state %d. ", YYDEBUGSTR, yydepth, yystate);
+                if (yyps->save)
+                    fputs("ALREADY in conflict, continuing trial parse.\n", stderr);
+                else
+                    fputs("Starting trial parse.\n", stderr);
+            }
+#endif
+            save                  = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+            if (save == NULL) goto yyenomem;
+            save->save            = yyps->save;
+            save->state           = yystate;
+            save->errflag         = yyerrflag;
+            save->yystack.s_mark  = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
+            memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(YYINT));
+            save->yystack.l_mark  = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
+            memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            save->yystack.p_mark  = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
+            memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+            ctry                  = yytable[yyn];
+            if (yyctable[ctry] == -1)
+            {
+#if YYDEBUG
+                if (yydebug && yychar >= YYEOF)
+                    fprintf(stderr, "%s[%d]: backtracking 1 token\n", YYDEBUGSTR, yydepth);
+#endif
+                ctry++;
+            }
+            save->ctry = ctry;
+            if (yyps->save == NULL)
+            {
+                /* If this is a first conflict in the stack, start saving lexemes */
+                if (!yylexemes)
+                {
+                    yylexemes = (YYINT *) malloc((YYLVQUEUEGROWTH) * sizeof(YYINT));
+                    if (yylexemes == NULL) goto yyenomem;
+                    yylvals   = (YYSTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYSTYPE));
+                    if (yylvals == NULL) goto yyenomem;
+                    yylvlim   = yylvals + YYLVQUEUEGROWTH;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                    yylpsns   = (YYLTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYLTYPE));
+                    if (yylpsns == NULL) goto yyenomem;
+                    yylplim   = yylpsns + YYLVQUEUEGROWTH;
+#endif
+                }
+                if (yylvp == yylve)
+                {
+                    yylvp  = yylve = yylvals;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                    yylpp  = yylpe = yylpsns;
+#endif
+                    yylexp = yylexemes;
+                    if (yychar >= YYEOF)
+                    {
+                        *yylve++ = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                        *yylpe++ = yylloc;
+#endif
+                        *yylexp  = (YYINT) yychar;
+                        yychar   = YYEMPTY;
+                    }
+                }
+            }
+            if (yychar >= YYEOF)
+            {
+                yylvp--;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                yylpp--;
+#endif
+                yylexp--;
+                yychar = YYEMPTY;
+            }
+            save->lexeme = (int) (yylvp - yylvals);
+            yyps->save   = save;
+        }
+        if (yytable[yyn] == ctry)
+        {
+#if YYDEBUG
+            if (yydebug)
+                fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+                                YYDEBUGSTR, yydepth, yystate, yyctable[ctry]);
+#endif
+            if (yychar < 0)
+            {
+                yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                yylpp++;
+#endif
+                yylexp++;
+            }
+            if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+                goto yyoverflow;
+            yystate = yyctable[ctry];
+            *++yystack.s_mark = (YYINT) yystate;
+            *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            *++yystack.p_mark = yylloc;
+#endif
+            yychar  = YYEMPTY;
+            if (yyerrflag > 0) --yyerrflag;
+            goto yyloop;
+        }
+        else
+        {
+            yyn = yyctable[ctry];
+            goto yyreduce;
+        }
+    } /* End of code dealing with conflicts */
+#endif /* YYBTYACC */
+    if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
     {
 #if YYDEBUG
         if (yydebug)
-            printf("%sdebug: state %d, shifting to state %d\n",
-                    YYPREFIX, yystate, yytable[yyn]);
+            fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+                            YYDEBUGSTR, yydepth, yystate, yytable[yyn]);
 #endif
-        if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
-        {
-            goto yyoverflow;
-        }
+        if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
         yystate = yytable[yyn];
         *++yystack.s_mark = yytable[yyn];
         *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        *++yystack.p_mark = yylloc;
+#endif
         yychar = YYEMPTY;
         if (yyerrflag > 0)  --yyerrflag;
         goto yyloop;
     }
-    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
     {
         yyn = yytable[yyn];
         goto yyreduce;
     }
-    if (yyerrflag) goto yyinrecovery;
+    if (yyerrflag != 0) goto yyinrecovery;
+#if YYBTYACC
 
-    YYERROR_CALL("syntax error");
-
-    goto yyerrlab;
+    yynewerrflag = 1;
+    goto yyerrhandler;
+    goto yyerrlab; /* redundant goto avoids 'unused label' warning */
 
 yyerrlab:
+    /* explicit YYERROR from an action -- pop the rhs of the rule reduced
+     * before looking for error recovery */
+    yystack.s_mark -= yym;
+    yystate = *yystack.s_mark;
+    yystack.l_mark -= yym;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yystack.p_mark -= yym;
+#endif
+
+    yynewerrflag = 0;
+yyerrhandler:
+    while (yyps->save)
+    {
+        int ctry;
+        YYParseState *save = yyps->save;
+#if YYDEBUG
+        if (yydebug)
+            fprintf(stderr, "%s[%d]: ERROR in state %d, CONFLICT BACKTRACKING to state %d, %d tokens\n",
+                            YYDEBUGSTR, yydepth, yystate, yyps->save->state,
+                    (int)(yylvp - yylvals - yyps->save->lexeme));
+#endif
+        /* Memorize most forward-looking error state in case it's really an error. */
+        if (yyerrctx == NULL || yyerrctx->lexeme < yylvp - yylvals)
+        {
+            /* Free old saved error context state */
+            if (yyerrctx) yyFreeState(yyerrctx);
+            /* Create and fill out new saved error context state */
+            yyerrctx                 = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+            if (yyerrctx == NULL) goto yyenomem;
+            yyerrctx->save           = yyps->save;
+            yyerrctx->state          = yystate;
+            yyerrctx->errflag        = yyerrflag;
+            yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
+            memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(YYINT));
+            yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
+            memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
+            memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+            yyerrctx->lexeme         = (int) (yylvp - yylvals);
+        }
+        yylvp          = yylvals   + save->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        yylpp          = yylpsns   + save->lexeme;
+#endif
+        yylexp         = yylexemes + save->lexeme;
+        yychar         = YYEMPTY;
+        yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
+        memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(YYINT));
+        yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
+        memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
+        memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+        ctry           = ++save->ctry;
+        yystate        = save->state;
+        /* We tried shift, try reduce now */
+        if ((yyn = yyctable[ctry]) >= 0) goto yyreduce;
+        yyps->save     = save->save;
+        save->save     = NULL;
+        yyFreeState(save);
+
+        /* Nothing left on the stack -- error */
+        if (!yyps->save)
+        {
+#if YYDEBUG
+            if (yydebug)
+                fprintf(stderr, "%sdebug[%d,trial]: trial parse FAILED, entering ERROR mode\n",
+                                YYPREFIX, yydepth);
+#endif
+            /* Restore state as it was in the most forward-advanced error */
+            yylvp          = yylvals   + yyerrctx->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            yylpp          = yylpsns   + yyerrctx->lexeme;
+#endif
+            yylexp         = yylexemes + yyerrctx->lexeme;
+            yychar         = yylexp[-1];
+            yylval         = yylvp[-1];
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            yylloc         = yylpp[-1];
+#endif
+            yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
+            memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(YYINT));
+            yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
+            memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
+            memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+            yystate        = yyerrctx->state;
+            yyFreeState(yyerrctx);
+            yyerrctx       = NULL;
+        }
+        yynewerrflag = 1;
+    }
+    if (yynewerrflag == 0) goto yyinrecovery;
+#endif /* YYBTYACC */
+
+    YYERROR_CALL("syntax error");
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yyerror_loc_range[1] = yylloc; /* lookahead position is error start position */
+#endif
+
+#if !YYBTYACC
+    goto yyerrlab; /* redundant goto avoids 'unused label' warning */
+yyerrlab:
+#endif
     ++yynerrs;
 
 yyinrecovery:
@@ -1419,33 +2182,55 @@
         yyerrflag = 3;
         for (;;)
         {
-            if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
-                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
             {
 #if YYDEBUG
                 if (yydebug)
-                    printf("%sdebug: state %d, error recovery shifting\
- to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
+                    fprintf(stderr, "%s[%d]: state %d, error recovery shifting to state %d\n",
+                                    YYDEBUGSTR, yydepth, *yystack.s_mark, yytable[yyn]);
 #endif
-                if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
-                {
-                    goto yyoverflow;
-                }
+                if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
                 yystate = yytable[yyn];
                 *++yystack.s_mark = yytable[yyn];
                 *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                /* lookahead position is error end position */
+                yyerror_loc_range[2] = yylloc;
+                YYLLOC_DEFAULT(yyloc, yyerror_loc_range, 2); /* position of error span */
+                *++yystack.p_mark = yyloc;
+#endif
                 goto yyloop;
             }
             else
             {
 #if YYDEBUG
                 if (yydebug)
-                    printf("%sdebug: error recovery discarding state %d\n",
-                            YYPREFIX, *yystack.s_mark);
+                    fprintf(stderr, "%s[%d]: error recovery discarding state %d\n",
+                                    YYDEBUGSTR, yydepth, *yystack.s_mark);
 #endif
                 if (yystack.s_mark <= yystack.s_base) goto yyabort;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                /* the current TOS position is the error start position */
+                yyerror_loc_range[1] = *yystack.p_mark;
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+                if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                    YYDESTRUCT_CALL("error: discarding state",
+                                    yystos[*yystack.s_mark], yystack.l_mark, yystack.p_mark);
+#else
+                    YYDESTRUCT_CALL("error: discarding state",
+                                    yystos[*yystack.s_mark], yystack.l_mark);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
                 --yystack.s_mark;
                 --yystack.l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                --yystack.p_mark;
+#endif
             }
         }
     }
@@ -1455,87 +2240,145 @@
 #if YYDEBUG
         if (yydebug)
         {
-            yys = yyname[YYTRANSLATE(yychar)];
-            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
-                    YYPREFIX, yystate, yychar, yys);
+            if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+            fprintf(stderr, "%s[%d]: state %d, error recovery discarding token %d (%s)\n",
+                            YYDEBUGSTR, yydepth, yystate, yychar, yys);
         }
 #endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+        if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+            YYDESTRUCT_CALL("error: discarding token", yychar, &yylval, &yylloc);
+#else
+            YYDESTRUCT_CALL("error: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
         yychar = YYEMPTY;
         goto yyloop;
     }
 
 yyreduce:
+    yym = yylen[yyn];
 #if YYDEBUG
     if (yydebug)
-        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
-                YYPREFIX, yystate, yyn, yyrule[yyn]);
+    {
+        fprintf(stderr, "%s[%d]: state %d, reducing by rule %d (%s)",
+                        YYDEBUGSTR, yydepth, yystate, yyn, yyrule[yyn]);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+        if (!yytrial)
+#endif /* YYBTYACC */
+            if (yym > 0)
+            {
+                int i;
+                fputc('<', stderr);
+                for (i = yym; i > 0; i--)
+                {
+                    if (i != yym) fputs(", ", stderr);
+                    fputs(YYSTYPE_TOSTRING(yystos[yystack.s_mark[1-i]],
+                                           yystack.l_mark[1-i]), stderr);
+                }
+                fputc('>', stderr);
+            }
 #endif
-    yym = yylen[yyn];
-    if (yym)
+        fputc('\n', stderr);
+    }
+#endif
+    if (yym > 0)
         yyval = yystack.l_mark[1-yym];
     else
         memset(&yyval, 0, sizeof yyval);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+
+    /* Perform position reduction */
+    memset(&yyloc, 0, sizeof(yyloc));
+#if YYBTYACC
+    if (!yytrial)
+#endif /* YYBTYACC */
+    {
+        YYLLOC_DEFAULT(yyloc, &yystack.p_mark[-yym], yym);
+        /* just in case YYERROR is invoked within the action, save
+           the start of the rhs as the error start position */
+        yyerror_loc_range[1] = yystack.p_mark[1-yym];
+    }
+#endif
+
     switch (yyn)
     {
 case 1:
-#line 396 "grammar.y"
+#line 424 "grammar.y"
 	{
 	CHECK_INT_VAL(finish_parse(cstate, yystack.l_mark[0].blk.b));
 }
+#line 2316 "grammar.c"
 break;
 case 3:
-#line 401 "grammar.y"
+#line 429 "grammar.y"
 	{ yyval.blk.q = qerr; }
+#line 2321 "grammar.c"
 break;
 case 5:
-#line 404 "grammar.y"
+#line 432 "grammar.y"
 	{ gen_and(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2326 "grammar.c"
 break;
 case 6:
-#line 405 "grammar.y"
+#line 433 "grammar.y"
 	{ gen_and(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2331 "grammar.c"
 break;
 case 7:
-#line 406 "grammar.y"
+#line 434 "grammar.y"
 	{ gen_or(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2336 "grammar.c"
 break;
 case 8:
-#line 407 "grammar.y"
+#line 435 "grammar.y"
 	{ gen_or(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2341 "grammar.c"
 break;
 case 9:
-#line 409 "grammar.y"
+#line 437 "grammar.y"
 	{ yyval.blk = yystack.l_mark[-1].blk; }
+#line 2346 "grammar.c"
 break;
 case 10:
-#line 411 "grammar.y"
+#line 439 "grammar.y"
 	{ yyval.blk = yystack.l_mark[-1].blk; }
+#line 2351 "grammar.c"
 break;
 case 12:
-#line 414 "grammar.y"
+#line 442 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_ncode(cstate, NULL, yystack.l_mark[0].h,
 						   yyval.blk.q = yystack.l_mark[-1].blk.q))); }
+#line 2357 "grammar.c"
 break;
 case 13:
-#line 416 "grammar.y"
+#line 444 "grammar.y"
 	{ yyval.blk = yystack.l_mark[-1].blk; }
+#line 2362 "grammar.c"
 break;
 case 14:
-#line 418 "grammar.y"
+#line 446 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_PTR_VAL((yyval.blk.b = gen_scode(cstate, yystack.l_mark[0].s, yyval.blk.q = yystack.l_mark[-1].blk.q))); }
+#line 2367 "grammar.c"
 break;
 case 15:
-#line 419 "grammar.y"
+#line 447 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[-2].s); CHECK_PTR_VAL((yyval.blk.b = gen_mcode(cstate, yystack.l_mark[-2].s, NULL, yystack.l_mark[0].h,
 				    yyval.blk.q = yystack.l_mark[-3].blk.q))); }
+#line 2373 "grammar.c"
 break;
 case 16:
-#line 421 "grammar.y"
+#line 449 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[-2].s); CHECK_PTR_VAL((yyval.blk.b = gen_mcode(cstate, yystack.l_mark[-2].s, yystack.l_mark[0].s, 0,
 				    yyval.blk.q = yystack.l_mark[-3].blk.q))); }
+#line 2379 "grammar.c"
 break;
 case 17:
-#line 423 "grammar.y"
+#line 451 "grammar.y"
 	{
 				  CHECK_PTR_VAL(yystack.l_mark[0].s);
 				  /* Decide how to parse HID based on proto */
@@ -1555,9 +2398,10 @@
 				  }
 				  CHECK_PTR_VAL((yyval.blk.b = gen_ncode(cstate, yystack.l_mark[0].s, 0, yyval.blk.q)));
 				}
+#line 2402 "grammar.c"
 break;
 case 18:
-#line 442 "grammar.y"
+#line 470 "grammar.y"
 	{
 				  CHECK_PTR_VAL(yystack.l_mark[-2].s);
 #ifdef INET6
@@ -1569,9 +2413,10 @@
 				  YYABORT;
 #endif /*INET6*/
 				}
+#line 2417 "grammar.c"
 break;
 case 19:
-#line 453 "grammar.y"
+#line 481 "grammar.y"
 	{
 				  CHECK_PTR_VAL(yystack.l_mark[0].s);
 #ifdef INET6
@@ -1583,62 +2428,76 @@
 				  YYABORT;
 #endif /*INET6*/
 				}
+#line 2432 "grammar.c"
 break;
 case 20:
-#line 464 "grammar.y"
+#line 492 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_PTR_VAL((yyval.blk.b = gen_ecode(cstate, yystack.l_mark[0].s, yyval.blk.q = yystack.l_mark[-1].blk.q))); }
+#line 2437 "grammar.c"
 break;
 case 21:
-#line 465 "grammar.y"
+#line 493 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_PTR_VAL((yyval.blk.b = gen_acode(cstate, yystack.l_mark[0].s, yyval.blk.q = yystack.l_mark[-1].blk.q))); }
+#line 2442 "grammar.c"
 break;
 case 22:
-#line 466 "grammar.y"
+#line 494 "grammar.y"
 	{ gen_not(yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2447 "grammar.c"
 break;
 case 23:
-#line 468 "grammar.y"
+#line 496 "grammar.y"
 	{ yyval.blk = yystack.l_mark[-1].blk; }
+#line 2452 "grammar.c"
 break;
 case 24:
-#line 470 "grammar.y"
+#line 498 "grammar.y"
 	{ yyval.blk = yystack.l_mark[-1].blk; }
+#line 2457 "grammar.c"
 break;
 case 26:
-#line 473 "grammar.y"
+#line 501 "grammar.y"
 	{ gen_and(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2462 "grammar.c"
 break;
 case 27:
-#line 474 "grammar.y"
+#line 502 "grammar.y"
 	{ gen_or(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2467 "grammar.c"
 break;
 case 28:
-#line 476 "grammar.y"
+#line 504 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_ncode(cstate, NULL, yystack.l_mark[0].h,
 						   yyval.blk.q = yystack.l_mark[-1].blk.q))); }
+#line 2473 "grammar.c"
 break;
 case 31:
-#line 481 "grammar.y"
+#line 509 "grammar.y"
 	{ gen_not(yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 2478 "grammar.c"
 break;
 case 32:
-#line 483 "grammar.y"
+#line 511 "grammar.y"
 	{ QSET(yyval.blk.q, yystack.l_mark[-2].i, yystack.l_mark[-1].i, yystack.l_mark[0].i); }
+#line 2483 "grammar.c"
 break;
 case 33:
-#line 484 "grammar.y"
+#line 512 "grammar.y"
 	{ QSET(yyval.blk.q, yystack.l_mark[-1].i, yystack.l_mark[0].i, Q_DEFAULT); }
+#line 2488 "grammar.c"
 break;
 case 34:
-#line 485 "grammar.y"
+#line 513 "grammar.y"
 	{ QSET(yyval.blk.q, yystack.l_mark[-1].i, Q_DEFAULT, yystack.l_mark[0].i); }
+#line 2493 "grammar.c"
 break;
 case 35:
-#line 486 "grammar.y"
+#line 514 "grammar.y"
 	{ QSET(yyval.blk.q, yystack.l_mark[-1].i, Q_DEFAULT, Q_PROTO); }
+#line 2498 "grammar.c"
 break;
 case 36:
-#line 487 "grammar.y"
+#line 515 "grammar.y"
 	{
 #ifdef NO_PROTOCHAIN
 				  bpf_set_error(cstate, "protochain not supported");
@@ -1647,424 +2506,525 @@
 				  QSET(yyval.blk.q, yystack.l_mark[-1].i, Q_DEFAULT, Q_PROTOCHAIN);
 #endif
 				}
+#line 2510 "grammar.c"
 break;
 case 37:
-#line 495 "grammar.y"
+#line 523 "grammar.y"
 	{ QSET(yyval.blk.q, yystack.l_mark[-1].i, Q_DEFAULT, yystack.l_mark[0].i); }
+#line 2515 "grammar.c"
 break;
 case 38:
-#line 497 "grammar.y"
+#line 525 "grammar.y"
 	{ yyval.blk = yystack.l_mark[0].blk; }
+#line 2520 "grammar.c"
 break;
 case 39:
-#line 498 "grammar.y"
+#line 526 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[-1].blk.b; yyval.blk.q = yystack.l_mark[-2].blk.q; }
+#line 2525 "grammar.c"
 break;
 case 40:
-#line 499 "grammar.y"
+#line 527 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_proto_abbrev(cstate, yystack.l_mark[0].i))); yyval.blk.q = qerr; }
+#line 2530 "grammar.c"
 break;
 case 41:
-#line 500 "grammar.y"
+#line 528 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_relation(cstate, yystack.l_mark[-1].i, yystack.l_mark[-2].a, yystack.l_mark[0].a, 0)));
 				  yyval.blk.q = qerr; }
+#line 2536 "grammar.c"
 break;
 case 42:
-#line 502 "grammar.y"
+#line 530 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_relation(cstate, yystack.l_mark[-1].i, yystack.l_mark[-2].a, yystack.l_mark[0].a, 1)));
 				  yyval.blk.q = qerr; }
+#line 2542 "grammar.c"
 break;
 case 43:
-#line 504 "grammar.y"
+#line 532 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[0].rblk; yyval.blk.q = qerr; }
+#line 2547 "grammar.c"
 break;
 case 44:
-#line 505 "grammar.y"
+#line 533 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_atmtype_abbrev(cstate, yystack.l_mark[0].i))); yyval.blk.q = qerr; }
+#line 2552 "grammar.c"
 break;
 case 45:
-#line 506 "grammar.y"
+#line 534 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_atmmulti_abbrev(cstate, yystack.l_mark[0].i))); yyval.blk.q = qerr; }
+#line 2557 "grammar.c"
 break;
 case 46:
-#line 507 "grammar.y"
+#line 535 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[0].blk.b; yyval.blk.q = qerr; }
+#line 2562 "grammar.c"
 break;
 case 47:
-#line 508 "grammar.y"
+#line 536 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_mtp2type_abbrev(cstate, yystack.l_mark[0].i))); yyval.blk.q = qerr; }
+#line 2567 "grammar.c"
 break;
 case 48:
-#line 509 "grammar.y"
+#line 537 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[0].blk.b; yyval.blk.q = qerr; }
+#line 2572 "grammar.c"
 break;
 case 50:
-#line 513 "grammar.y"
+#line 541 "grammar.y"
 	{ yyval.i = Q_DEFAULT; }
+#line 2577 "grammar.c"
 break;
 case 51:
-#line 516 "grammar.y"
+#line 544 "grammar.y"
 	{ yyval.i = Q_SRC; }
+#line 2582 "grammar.c"
 break;
 case 52:
-#line 517 "grammar.y"
+#line 545 "grammar.y"
 	{ yyval.i = Q_DST; }
+#line 2587 "grammar.c"
 break;
 case 53:
-#line 518 "grammar.y"
+#line 546 "grammar.y"
 	{ yyval.i = Q_OR; }
+#line 2592 "grammar.c"
 break;
 case 54:
-#line 519 "grammar.y"
+#line 547 "grammar.y"
 	{ yyval.i = Q_OR; }
+#line 2597 "grammar.c"
 break;
 case 55:
-#line 520 "grammar.y"
+#line 548 "grammar.y"
 	{ yyval.i = Q_AND; }
+#line 2602 "grammar.c"
 break;
 case 56:
-#line 521 "grammar.y"
+#line 549 "grammar.y"
 	{ yyval.i = Q_AND; }
+#line 2607 "grammar.c"
 break;
 case 57:
-#line 522 "grammar.y"
+#line 550 "grammar.y"
 	{ yyval.i = Q_ADDR1; }
+#line 2612 "grammar.c"
 break;
 case 58:
-#line 523 "grammar.y"
+#line 551 "grammar.y"
 	{ yyval.i = Q_ADDR2; }
+#line 2617 "grammar.c"
 break;
 case 59:
-#line 524 "grammar.y"
+#line 552 "grammar.y"
 	{ yyval.i = Q_ADDR3; }
+#line 2622 "grammar.c"
 break;
 case 60:
-#line 525 "grammar.y"
+#line 553 "grammar.y"
 	{ yyval.i = Q_ADDR4; }
+#line 2627 "grammar.c"
 break;
 case 61:
-#line 526 "grammar.y"
+#line 554 "grammar.y"
 	{ yyval.i = Q_RA; }
+#line 2632 "grammar.c"
 break;
 case 62:
-#line 527 "grammar.y"
+#line 555 "grammar.y"
 	{ yyval.i = Q_TA; }
+#line 2637 "grammar.c"
 break;
 case 63:
-#line 530 "grammar.y"
+#line 558 "grammar.y"
 	{ yyval.i = Q_HOST; }
+#line 2642 "grammar.c"
 break;
 case 64:
-#line 531 "grammar.y"
+#line 559 "grammar.y"
 	{ yyval.i = Q_NET; }
+#line 2647 "grammar.c"
 break;
 case 65:
-#line 532 "grammar.y"
+#line 560 "grammar.y"
 	{ yyval.i = Q_PORT; }
+#line 2652 "grammar.c"
 break;
 case 66:
-#line 533 "grammar.y"
+#line 561 "grammar.y"
 	{ yyval.i = Q_PORTRANGE; }
+#line 2657 "grammar.c"
 break;
 case 67:
-#line 536 "grammar.y"
+#line 564 "grammar.y"
 	{ yyval.i = Q_GATEWAY; }
+#line 2662 "grammar.c"
 break;
 case 68:
-#line 538 "grammar.y"
+#line 566 "grammar.y"
 	{ yyval.i = Q_LINK; }
+#line 2667 "grammar.c"
 break;
 case 69:
-#line 539 "grammar.y"
+#line 567 "grammar.y"
 	{ yyval.i = Q_IP; }
+#line 2672 "grammar.c"
 break;
 case 70:
-#line 540 "grammar.y"
+#line 568 "grammar.y"
 	{ yyval.i = Q_ARP; }
+#line 2677 "grammar.c"
 break;
 case 71:
-#line 541 "grammar.y"
+#line 569 "grammar.y"
 	{ yyval.i = Q_RARP; }
+#line 2682 "grammar.c"
 break;
 case 72:
-#line 542 "grammar.y"
+#line 570 "grammar.y"
 	{ yyval.i = Q_SCTP; }
+#line 2687 "grammar.c"
 break;
 case 73:
-#line 543 "grammar.y"
+#line 571 "grammar.y"
 	{ yyval.i = Q_TCP; }
+#line 2692 "grammar.c"
 break;
 case 74:
-#line 544 "grammar.y"
+#line 572 "grammar.y"
 	{ yyval.i = Q_UDP; }
+#line 2697 "grammar.c"
 break;
 case 75:
-#line 545 "grammar.y"
+#line 573 "grammar.y"
 	{ yyval.i = Q_ICMP; }
+#line 2702 "grammar.c"
 break;
 case 76:
-#line 546 "grammar.y"
+#line 574 "grammar.y"
 	{ yyval.i = Q_IGMP; }
+#line 2707 "grammar.c"
 break;
 case 77:
-#line 547 "grammar.y"
+#line 575 "grammar.y"
 	{ yyval.i = Q_IGRP; }
+#line 2712 "grammar.c"
 break;
 case 78:
-#line 548 "grammar.y"
+#line 576 "grammar.y"
 	{ yyval.i = Q_PIM; }
+#line 2717 "grammar.c"
 break;
 case 79:
-#line 549 "grammar.y"
+#line 577 "grammar.y"
 	{ yyval.i = Q_VRRP; }
+#line 2722 "grammar.c"
 break;
 case 80:
-#line 550 "grammar.y"
+#line 578 "grammar.y"
 	{ yyval.i = Q_CARP; }
+#line 2727 "grammar.c"
 break;
 case 81:
-#line 551 "grammar.y"
+#line 579 "grammar.y"
 	{ yyval.i = Q_ATALK; }
+#line 2732 "grammar.c"
 break;
 case 82:
-#line 552 "grammar.y"
+#line 580 "grammar.y"
 	{ yyval.i = Q_AARP; }
+#line 2737 "grammar.c"
 break;
 case 83:
-#line 553 "grammar.y"
+#line 581 "grammar.y"
 	{ yyval.i = Q_DECNET; }
+#line 2742 "grammar.c"
 break;
 case 84:
-#line 554 "grammar.y"
+#line 582 "grammar.y"
 	{ yyval.i = Q_LAT; }
+#line 2747 "grammar.c"
 break;
 case 85:
-#line 555 "grammar.y"
+#line 583 "grammar.y"
 	{ yyval.i = Q_SCA; }
+#line 2752 "grammar.c"
 break;
 case 86:
-#line 556 "grammar.y"
+#line 584 "grammar.y"
 	{ yyval.i = Q_MOPDL; }
+#line 2757 "grammar.c"
 break;
 case 87:
-#line 557 "grammar.y"
+#line 585 "grammar.y"
 	{ yyval.i = Q_MOPRC; }
+#line 2762 "grammar.c"
 break;
 case 88:
-#line 558 "grammar.y"
+#line 586 "grammar.y"
 	{ yyval.i = Q_IPV6; }
+#line 2767 "grammar.c"
 break;
 case 89:
-#line 559 "grammar.y"
+#line 587 "grammar.y"
 	{ yyval.i = Q_ICMPV6; }
+#line 2772 "grammar.c"
 break;
 case 90:
-#line 560 "grammar.y"
+#line 588 "grammar.y"
 	{ yyval.i = Q_AH; }
+#line 2777 "grammar.c"
 break;
 case 91:
-#line 561 "grammar.y"
+#line 589 "grammar.y"
 	{ yyval.i = Q_ESP; }
+#line 2782 "grammar.c"
 break;
 case 92:
-#line 562 "grammar.y"
+#line 590 "grammar.y"
 	{ yyval.i = Q_ISO; }
+#line 2787 "grammar.c"
 break;
 case 93:
-#line 563 "grammar.y"
+#line 591 "grammar.y"
 	{ yyval.i = Q_ESIS; }
+#line 2792 "grammar.c"
 break;
 case 94:
-#line 564 "grammar.y"
+#line 592 "grammar.y"
 	{ yyval.i = Q_ISIS; }
+#line 2797 "grammar.c"
 break;
 case 95:
-#line 565 "grammar.y"
+#line 593 "grammar.y"
 	{ yyval.i = Q_ISIS_L1; }
+#line 2802 "grammar.c"
 break;
 case 96:
-#line 566 "grammar.y"
+#line 594 "grammar.y"
 	{ yyval.i = Q_ISIS_L2; }
+#line 2807 "grammar.c"
 break;
 case 97:
-#line 567 "grammar.y"
+#line 595 "grammar.y"
 	{ yyval.i = Q_ISIS_IIH; }
+#line 2812 "grammar.c"
 break;
 case 98:
-#line 568 "grammar.y"
+#line 596 "grammar.y"
 	{ yyval.i = Q_ISIS_LSP; }
+#line 2817 "grammar.c"
 break;
 case 99:
-#line 569 "grammar.y"
+#line 597 "grammar.y"
 	{ yyval.i = Q_ISIS_SNP; }
+#line 2822 "grammar.c"
 break;
 case 100:
-#line 570 "grammar.y"
+#line 598 "grammar.y"
 	{ yyval.i = Q_ISIS_PSNP; }
+#line 2827 "grammar.c"
 break;
 case 101:
-#line 571 "grammar.y"
+#line 599 "grammar.y"
 	{ yyval.i = Q_ISIS_CSNP; }
+#line 2832 "grammar.c"
 break;
 case 102:
-#line 572 "grammar.y"
+#line 600 "grammar.y"
 	{ yyval.i = Q_CLNP; }
+#line 2837 "grammar.c"
 break;
 case 103:
-#line 573 "grammar.y"
+#line 601 "grammar.y"
 	{ yyval.i = Q_STP; }
+#line 2842 "grammar.c"
 break;
 case 104:
-#line 574 "grammar.y"
+#line 602 "grammar.y"
 	{ yyval.i = Q_IPX; }
+#line 2847 "grammar.c"
 break;
 case 105:
-#line 575 "grammar.y"
+#line 603 "grammar.y"
 	{ yyval.i = Q_NETBEUI; }
+#line 2852 "grammar.c"
 break;
 case 106:
-#line 576 "grammar.y"
+#line 604 "grammar.y"
 	{ yyval.i = Q_RADIO; }
+#line 2857 "grammar.c"
 break;
 case 107:
-#line 578 "grammar.y"
+#line 606 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_broadcast(cstate, yystack.l_mark[-1].i))); }
+#line 2862 "grammar.c"
 break;
 case 108:
-#line 579 "grammar.y"
+#line 607 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_multicast(cstate, yystack.l_mark[-1].i))); }
+#line 2867 "grammar.c"
 break;
 case 109:
-#line 580 "grammar.y"
+#line 608 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_less(cstate, yystack.l_mark[0].h))); }
+#line 2872 "grammar.c"
 break;
 case 110:
-#line 581 "grammar.y"
+#line 609 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_greater(cstate, yystack.l_mark[0].h))); }
+#line 2877 "grammar.c"
 break;
 case 111:
-#line 582 "grammar.y"
+#line 610 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_byteop(cstate, yystack.l_mark[-1].i, yystack.l_mark[-2].h, yystack.l_mark[0].h))); }
+#line 2882 "grammar.c"
 break;
 case 112:
-#line 583 "grammar.y"
+#line 611 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_inbound(cstate, 0))); }
+#line 2887 "grammar.c"
 break;
 case 113:
-#line 584 "grammar.y"
+#line 612 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_inbound(cstate, 1))); }
+#line 2892 "grammar.c"
 break;
 case 114:
-#line 585 "grammar.y"
+#line 613 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_ifindex(cstate, yystack.l_mark[0].h))); }
+#line 2897 "grammar.c"
 break;
 case 115:
-#line 586 "grammar.y"
+#line 614 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_vlan(cstate, yystack.l_mark[0].h, 1))); }
+#line 2902 "grammar.c"
 break;
 case 116:
-#line 587 "grammar.y"
+#line 615 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_vlan(cstate, 0, 0))); }
+#line 2907 "grammar.c"
 break;
 case 117:
-#line 588 "grammar.y"
+#line 616 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_mpls(cstate, yystack.l_mark[0].h, 1))); }
+#line 2912 "grammar.c"
 break;
 case 118:
-#line 589 "grammar.y"
+#line 617 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_mpls(cstate, 0, 0))); }
+#line 2917 "grammar.c"
 break;
 case 119:
-#line 590 "grammar.y"
+#line 618 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pppoed(cstate))); }
+#line 2922 "grammar.c"
 break;
 case 120:
-#line 591 "grammar.y"
+#line 619 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pppoes(cstate, yystack.l_mark[0].h, 1))); }
+#line 2927 "grammar.c"
 break;
 case 121:
-#line 592 "grammar.y"
+#line 620 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pppoes(cstate, 0, 0))); }
+#line 2932 "grammar.c"
 break;
 case 122:
-#line 593 "grammar.y"
+#line 621 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_geneve(cstate, yystack.l_mark[0].h, 1))); }
+#line 2937 "grammar.c"
 break;
 case 123:
-#line 594 "grammar.y"
+#line 622 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_geneve(cstate, 0, 0))); }
+#line 2942 "grammar.c"
 break;
 case 124:
-#line 595 "grammar.y"
+#line 623 "grammar.y"
 	{ yyval.rblk = yystack.l_mark[0].rblk; }
+#line 2947 "grammar.c"
 break;
 case 125:
-#line 596 "grammar.y"
+#line 624 "grammar.y"
 	{ yyval.rblk = yystack.l_mark[0].rblk; }
+#line 2952 "grammar.c"
 break;
 case 126:
-#line 597 "grammar.y"
+#line 625 "grammar.y"
 	{ yyval.rblk = yystack.l_mark[0].rblk; }
+#line 2957 "grammar.c"
 break;
 case 127:
-#line 600 "grammar.y"
+#line 628 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_PTR_VAL((yyval.rblk = gen_pf_ifname(cstate, yystack.l_mark[0].s))); }
+#line 2962 "grammar.c"
 break;
 case 128:
-#line 601 "grammar.y"
+#line 629 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_PTR_VAL((yyval.rblk = gen_pf_ruleset(cstate, yystack.l_mark[0].s))); }
+#line 2967 "grammar.c"
 break;
 case 129:
-#line 602 "grammar.y"
+#line 630 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pf_rnr(cstate, yystack.l_mark[0].h))); }
+#line 2972 "grammar.c"
 break;
 case 130:
-#line 603 "grammar.y"
+#line 631 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pf_srnr(cstate, yystack.l_mark[0].h))); }
+#line 2977 "grammar.c"
 break;
 case 131:
-#line 604 "grammar.y"
+#line 632 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pf_reason(cstate, yystack.l_mark[0].i))); }
+#line 2982 "grammar.c"
 break;
 case 132:
-#line 605 "grammar.y"
+#line 633 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_pf_action(cstate, yystack.l_mark[0].i))); }
+#line 2987 "grammar.c"
 break;
 case 133:
-#line 609 "grammar.y"
+#line 637 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_p80211_type(cstate, yystack.l_mark[-2].i | yystack.l_mark[0].i,
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
+#line 2995 "grammar.c"
 break;
 case 134:
-#line 613 "grammar.y"
+#line 641 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_p80211_type(cstate, yystack.l_mark[0].i,
 					IEEE80211_FC0_TYPE_MASK)));
 				}
+#line 3002 "grammar.c"
 break;
 case 135:
-#line 616 "grammar.y"
+#line 644 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_p80211_type(cstate, yystack.l_mark[0].i,
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK)));
 				}
+#line 3010 "grammar.c"
 break;
 case 136:
-#line 620 "grammar.y"
+#line 648 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_p80211_fcdir(cstate, yystack.l_mark[0].i))); }
+#line 3015 "grammar.c"
 break;
 case 137:
-#line 623 "grammar.y"
+#line 651 "grammar.y"
 	{ if ((yystack.l_mark[0].h & (~IEEE80211_FC0_TYPE_MASK)) != 0) {
 					bpf_set_error(cstate, "invalid 802.11 type value 0x%02x", yystack.l_mark[0].h);
 					YYABORT;
 				  }
 				  yyval.i = (int)yystack.l_mark[0].h;
 				}
+#line 3025 "grammar.c"
 break;
 case 138:
-#line 629 "grammar.y"
+#line 657 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s);
 				  yyval.i = str2tok(yystack.l_mark[0].s, ieee80211_types);
 				  if (yyval.i == -1) {
@@ -2072,18 +3032,20 @@
 					YYABORT;
 				  }
 				}
+#line 3036 "grammar.c"
 break;
 case 139:
-#line 638 "grammar.y"
+#line 666 "grammar.y"
 	{ if ((yystack.l_mark[0].h & (~IEEE80211_FC0_SUBTYPE_MASK)) != 0) {
 					bpf_set_error(cstate, "invalid 802.11 subtype value 0x%02x", yystack.l_mark[0].h);
 					YYABORT;
 				  }
 				  yyval.i = (int)yystack.l_mark[0].h;
 				}
+#line 3046 "grammar.c"
 break;
 case 140:
-#line 644 "grammar.y"
+#line 672 "grammar.y"
 	{ const struct tok *types = NULL;
 				  int i;
 				  CHECK_PTR_VAL(yystack.l_mark[0].s);
@@ -2105,9 +3067,10 @@
 					YYABORT;
 				  }
 				}
+#line 3071 "grammar.c"
 break;
 case 141:
-#line 667 "grammar.y"
+#line 695 "grammar.y"
 	{ int i;
 				  CHECK_PTR_VAL(yystack.l_mark[0].s);
 				  for (i = 0;; i++) {
@@ -2123,13 +3086,15 @@
 					}
 				  }
 				}
+#line 3090 "grammar.c"
 break;
 case 142:
-#line 684 "grammar.y"
+#line 712 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_llc(cstate))); }
+#line 3095 "grammar.c"
 break;
 case 143:
-#line 685 "grammar.y"
+#line 713 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s);
 				  if (pcap_strcasecmp(yystack.l_mark[0].s, "i") == 0) {
 					CHECK_PTR_VAL((yyval.rblk = gen_llc_i(cstate)));
@@ -2153,17 +3118,20 @@
 					}
 				  }
 				}
+#line 3122 "grammar.c"
 break;
 case 144:
-#line 709 "grammar.y"
+#line 737 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.rblk = gen_llc_s_subtype(cstate, LLC_RNR))); }
+#line 3127 "grammar.c"
 break;
 case 145:
-#line 712 "grammar.y"
+#line 740 "grammar.y"
 	{ yyval.i = (int)yystack.l_mark[0].h; }
+#line 3132 "grammar.c"
 break;
 case 146:
-#line 713 "grammar.y"
+#line 741 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s);
 				  if (pcap_strcasecmp(yystack.l_mark[0].s, "nods") == 0)
 					yyval.i = IEEE80211_FC1_DIR_NODS;
@@ -2178,278 +3146,345 @@
 					YYABORT;
 				  }
 				}
+#line 3150 "grammar.c"
 break;
 case 147:
-#line 729 "grammar.y"
+#line 757 "grammar.y"
 	{ yyval.i = yystack.l_mark[0].h; }
+#line 3155 "grammar.c"
 break;
 case 148:
-#line 730 "grammar.y"
+#line 758 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_INT_VAL((yyval.i = pfreason_to_num(cstate, yystack.l_mark[0].s))); }
+#line 3160 "grammar.c"
 break;
 case 149:
-#line 733 "grammar.y"
+#line 761 "grammar.y"
 	{ CHECK_PTR_VAL(yystack.l_mark[0].s); CHECK_INT_VAL((yyval.i = pfaction_to_num(cstate, yystack.l_mark[0].s))); }
+#line 3165 "grammar.c"
 break;
 case 150:
-#line 736 "grammar.y"
+#line 764 "grammar.y"
 	{ yyval.i = BPF_JGT; }
+#line 3170 "grammar.c"
 break;
 case 151:
-#line 737 "grammar.y"
+#line 765 "grammar.y"
 	{ yyval.i = BPF_JGE; }
+#line 3175 "grammar.c"
 break;
 case 152:
-#line 738 "grammar.y"
+#line 766 "grammar.y"
 	{ yyval.i = BPF_JEQ; }
+#line 3180 "grammar.c"
 break;
 case 153:
-#line 740 "grammar.y"
+#line 768 "grammar.y"
 	{ yyval.i = BPF_JGT; }
+#line 3185 "grammar.c"
 break;
 case 154:
-#line 741 "grammar.y"
+#line 769 "grammar.y"
 	{ yyval.i = BPF_JGE; }
+#line 3190 "grammar.c"
 break;
 case 155:
-#line 742 "grammar.y"
+#line 770 "grammar.y"
 	{ yyval.i = BPF_JEQ; }
+#line 3195 "grammar.c"
 break;
 case 156:
-#line 744 "grammar.y"
+#line 772 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_loadi(cstate, yystack.l_mark[0].h))); }
+#line 3200 "grammar.c"
 break;
 case 158:
-#line 747 "grammar.y"
+#line 775 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_load(cstate, yystack.l_mark[-3].i, yystack.l_mark[-1].a, 1))); }
+#line 3205 "grammar.c"
 break;
 case 159:
-#line 748 "grammar.y"
+#line 776 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_load(cstate, yystack.l_mark[-5].i, yystack.l_mark[-3].a, yystack.l_mark[-1].h))); }
+#line 3210 "grammar.c"
 break;
 case 160:
-#line 749 "grammar.y"
+#line 777 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_ADD, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3215 "grammar.c"
 break;
 case 161:
-#line 750 "grammar.y"
+#line 778 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_SUB, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3220 "grammar.c"
 break;
 case 162:
-#line 751 "grammar.y"
+#line 779 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_MUL, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3225 "grammar.c"
 break;
 case 163:
-#line 752 "grammar.y"
+#line 780 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_DIV, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3230 "grammar.c"
 break;
 case 164:
-#line 753 "grammar.y"
+#line 781 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_MOD, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3235 "grammar.c"
 break;
 case 165:
-#line 754 "grammar.y"
+#line 782 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_AND, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3240 "grammar.c"
 break;
 case 166:
-#line 755 "grammar.y"
+#line 783 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_OR, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3245 "grammar.c"
 break;
 case 167:
-#line 756 "grammar.y"
+#line 784 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_XOR, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3250 "grammar.c"
 break;
 case 168:
-#line 757 "grammar.y"
+#line 785 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_LSH, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3255 "grammar.c"
 break;
 case 169:
-#line 758 "grammar.y"
+#line 786 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_arth(cstate, BPF_RSH, yystack.l_mark[-2].a, yystack.l_mark[0].a))); }
+#line 3260 "grammar.c"
 break;
 case 170:
-#line 759 "grammar.y"
+#line 787 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_neg(cstate, yystack.l_mark[0].a))); }
+#line 3265 "grammar.c"
 break;
 case 171:
-#line 760 "grammar.y"
+#line 788 "grammar.y"
 	{ yyval.a = yystack.l_mark[-1].a; }
+#line 3270 "grammar.c"
 break;
 case 172:
-#line 761 "grammar.y"
+#line 789 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.a = gen_loadlen(cstate))); }
+#line 3275 "grammar.c"
 break;
 case 173:
-#line 763 "grammar.y"
+#line 791 "grammar.y"
 	{ yyval.i = '&'; }
+#line 3280 "grammar.c"
 break;
 case 174:
-#line 764 "grammar.y"
+#line 792 "grammar.y"
 	{ yyval.i = '|'; }
+#line 3285 "grammar.c"
 break;
 case 175:
-#line 765 "grammar.y"
+#line 793 "grammar.y"
 	{ yyval.i = '<'; }
+#line 3290 "grammar.c"
 break;
 case 176:
-#line 766 "grammar.y"
+#line 794 "grammar.y"
 	{ yyval.i = '>'; }
+#line 3295 "grammar.c"
 break;
 case 177:
-#line 767 "grammar.y"
+#line 795 "grammar.y"
 	{ yyval.i = '='; }
+#line 3300 "grammar.c"
 break;
 case 179:
-#line 770 "grammar.y"
+#line 798 "grammar.y"
 	{ yyval.h = yystack.l_mark[-1].h; }
+#line 3305 "grammar.c"
 break;
 case 180:
-#line 772 "grammar.y"
+#line 800 "grammar.y"
 	{ yyval.i = A_LANE; }
+#line 3310 "grammar.c"
 break;
 case 181:
-#line 773 "grammar.y"
+#line 801 "grammar.y"
 	{ yyval.i = A_METAC;	}
+#line 3315 "grammar.c"
 break;
 case 182:
-#line 774 "grammar.y"
+#line 802 "grammar.y"
 	{ yyval.i = A_BCC; }
+#line 3320 "grammar.c"
 break;
 case 183:
-#line 775 "grammar.y"
+#line 803 "grammar.y"
 	{ yyval.i = A_OAMF4EC; }
+#line 3325 "grammar.c"
 break;
 case 184:
-#line 776 "grammar.y"
+#line 804 "grammar.y"
 	{ yyval.i = A_OAMF4SC; }
+#line 3330 "grammar.c"
 break;
 case 185:
-#line 777 "grammar.y"
+#line 805 "grammar.y"
 	{ yyval.i = A_SC; }
+#line 3335 "grammar.c"
 break;
 case 186:
-#line 778 "grammar.y"
+#line 806 "grammar.y"
 	{ yyval.i = A_ILMIC; }
+#line 3340 "grammar.c"
 break;
 case 187:
-#line 780 "grammar.y"
+#line 808 "grammar.y"
 	{ yyval.i = A_OAM; }
+#line 3345 "grammar.c"
 break;
 case 188:
-#line 781 "grammar.y"
+#line 809 "grammar.y"
 	{ yyval.i = A_OAMF4; }
+#line 3350 "grammar.c"
 break;
 case 189:
-#line 782 "grammar.y"
+#line 810 "grammar.y"
 	{ yyval.i = A_CONNECTMSG; }
+#line 3355 "grammar.c"
 break;
 case 190:
-#line 783 "grammar.y"
+#line 811 "grammar.y"
 	{ yyval.i = A_METACONNECT; }
+#line 3360 "grammar.c"
 break;
 case 191:
-#line 786 "grammar.y"
+#line 814 "grammar.y"
 	{ yyval.blk.atmfieldtype = A_VPI; }
+#line 3365 "grammar.c"
 break;
 case 192:
-#line 787 "grammar.y"
+#line 815 "grammar.y"
 	{ yyval.blk.atmfieldtype = A_VCI; }
+#line 3370 "grammar.c"
 break;
 case 194:
-#line 790 "grammar.y"
+#line 818 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_atmfield_code(cstate, yystack.l_mark[-2].blk.atmfieldtype, yystack.l_mark[0].h, yystack.l_mark[-1].i, 0))); }
+#line 3375 "grammar.c"
 break;
 case 195:
-#line 791 "grammar.y"
+#line 819 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_atmfield_code(cstate, yystack.l_mark[-2].blk.atmfieldtype, yystack.l_mark[0].h, yystack.l_mark[-1].i, 1))); }
+#line 3380 "grammar.c"
 break;
 case 196:
-#line 792 "grammar.y"
+#line 820 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[-1].blk.b; yyval.blk.q = qerr; }
+#line 3385 "grammar.c"
 break;
 case 197:
-#line 794 "grammar.y"
+#line 822 "grammar.y"
 	{
 	yyval.blk.atmfieldtype = yystack.l_mark[-1].blk.atmfieldtype;
 	if (yyval.blk.atmfieldtype == A_VPI ||
 	    yyval.blk.atmfieldtype == A_VCI)
 		CHECK_PTR_VAL((yyval.blk.b = gen_atmfield_code(cstate, yyval.blk.atmfieldtype, yystack.l_mark[0].h, BPF_JEQ, 0)));
 	}
+#line 3395 "grammar.c"
 break;
 case 199:
-#line 802 "grammar.y"
+#line 830 "grammar.y"
 	{ gen_or(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 3400 "grammar.c"
 break;
 case 200:
-#line 805 "grammar.y"
+#line 833 "grammar.y"
 	{ yyval.i = M_FISU; }
+#line 3405 "grammar.c"
 break;
 case 201:
-#line 806 "grammar.y"
+#line 834 "grammar.y"
 	{ yyval.i = M_LSSU; }
+#line 3410 "grammar.c"
 break;
 case 202:
-#line 807 "grammar.y"
+#line 835 "grammar.y"
 	{ yyval.i = M_MSU; }
+#line 3415 "grammar.c"
 break;
 case 203:
-#line 808 "grammar.y"
+#line 836 "grammar.y"
 	{ yyval.i = MH_FISU; }
+#line 3420 "grammar.c"
 break;
 case 204:
-#line 809 "grammar.y"
+#line 837 "grammar.y"
 	{ yyval.i = MH_LSSU; }
+#line 3425 "grammar.c"
 break;
 case 205:
-#line 810 "grammar.y"
+#line 838 "grammar.y"
 	{ yyval.i = MH_MSU; }
+#line 3430 "grammar.c"
 break;
 case 206:
-#line 813 "grammar.y"
+#line 841 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = M_SIO; }
+#line 3435 "grammar.c"
 break;
 case 207:
-#line 814 "grammar.y"
+#line 842 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = M_OPC; }
+#line 3440 "grammar.c"
 break;
 case 208:
-#line 815 "grammar.y"
+#line 843 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = M_DPC; }
+#line 3445 "grammar.c"
 break;
 case 209:
-#line 816 "grammar.y"
+#line 844 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = M_SLS; }
+#line 3450 "grammar.c"
 break;
 case 210:
-#line 817 "grammar.y"
+#line 845 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = MH_SIO; }
+#line 3455 "grammar.c"
 break;
 case 211:
-#line 818 "grammar.y"
+#line 846 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = MH_OPC; }
+#line 3460 "grammar.c"
 break;
 case 212:
-#line 819 "grammar.y"
+#line 847 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = MH_DPC; }
+#line 3465 "grammar.c"
 break;
 case 213:
-#line 820 "grammar.y"
+#line 848 "grammar.y"
 	{ yyval.blk.mtp3fieldtype = MH_SLS; }
+#line 3470 "grammar.c"
 break;
 case 215:
-#line 823 "grammar.y"
+#line 851 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_mtp3field_code(cstate, yystack.l_mark[-2].blk.mtp3fieldtype, yystack.l_mark[0].h, yystack.l_mark[-1].i, 0))); }
+#line 3475 "grammar.c"
 break;
 case 216:
-#line 824 "grammar.y"
+#line 852 "grammar.y"
 	{ CHECK_PTR_VAL((yyval.blk.b = gen_mtp3field_code(cstate, yystack.l_mark[-2].blk.mtp3fieldtype, yystack.l_mark[0].h, yystack.l_mark[-1].i, 1))); }
+#line 3480 "grammar.c"
 break;
 case 217:
-#line 825 "grammar.y"
+#line 853 "grammar.y"
 	{ yyval.blk.b = yystack.l_mark[-1].blk.b; yyval.blk.q = qerr; }
+#line 3485 "grammar.c"
 break;
 case 218:
-#line 827 "grammar.y"
+#line 855 "grammar.y"
 	{
 	yyval.blk.mtp3fieldtype = yystack.l_mark[-1].blk.mtp3fieldtype;
 	if (yyval.blk.mtp3fieldtype == M_SIO ||
@@ -2462,68 +3497,245 @@
 	    yyval.blk.mtp3fieldtype == MH_SLS)
 		CHECK_PTR_VAL((yyval.blk.b = gen_mtp3field_code(cstate, yyval.blk.mtp3fieldtype, yystack.l_mark[0].h, BPF_JEQ, 0)));
 	}
+#line 3501 "grammar.c"
 break;
 case 220:
-#line 841 "grammar.y"
+#line 869 "grammar.y"
 	{ gen_or(yystack.l_mark[-2].blk.b, yystack.l_mark[0].blk.b); yyval.blk = yystack.l_mark[0].blk; }
+#line 3506 "grammar.c"
 break;
-#line 2471 "grammar.c"
+#line 3508 "grammar.c"
+    default:
+        break;
     }
     yystack.s_mark -= yym;
     yystate = *yystack.s_mark;
     yystack.l_mark -= yym;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yystack.p_mark -= yym;
+#endif
     yym = yylhs[yyn];
     if (yystate == 0 && yym == 0)
     {
 #if YYDEBUG
         if (yydebug)
-            printf("%sdebug: after reduction, shifting from state 0 to\
- state %d\n", YYPREFIX, YYFINAL);
+        {
+            fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+            if (!yytrial)
+#endif /* YYBTYACC */
+                fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[YYFINAL], yyval));
+#endif
+            fprintf(stderr, "shifting from state 0 to final state %d\n", YYFINAL);
+        }
 #endif
         yystate = YYFINAL;
         *++yystack.s_mark = YYFINAL;
         *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        *++yystack.p_mark = yyloc;
+#endif
         if (yychar < 0)
         {
-            if ((yychar = YYLEX) < 0) yychar = YYEOF;
+#if YYBTYACC
+            do {
+            if (yylvp < yylve)
+            {
+                /* we're currently re-reading tokens */
+                yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                yylloc = *yylpp++;
+#endif
+                yychar = *yylexp++;
+                break;
+            }
+            if (yyps->save)
+            {
+                /* in trial mode; save scanner results for future parse attempts */
+                if (yylvp == yylvlim)
+                {   /* Enlarge lexical value queue */
+                    size_t p = (size_t) (yylvp - yylvals);
+                    size_t s = (size_t) (yylvlim - yylvals);
+
+                    s += YYLVQUEUEGROWTH;
+                    if ((yylexemes = (YYINT *)realloc(yylexemes, s * sizeof(YYINT))) == NULL)
+                        goto yyenomem;
+                    if ((yylvals   = (YYSTYPE *)realloc(yylvals, s * sizeof(YYSTYPE))) == NULL)
+                        goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                    if ((yylpsns   = (YYLTYPE *)realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL)
+                        goto yyenomem;
+#endif
+                    yylvp   = yylve = yylvals + p;
+                    yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                    yylpp   = yylpe = yylpsns + p;
+                    yylplim = yylpsns + s;
+#endif
+                    yylexp  = yylexemes + p;
+                }
+                *yylexp = (YYINT) YYLEX;
+                *yylvp++ = yylval;
+                yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+                *yylpp++ = yylloc;
+                yylpe++;
+#endif
+                yychar = *yylexp++;
+                break;
+            }
+            /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+            yychar = YYLEX;
+#if YYBTYACC
+            } while (0);
+#endif /* YYBTYACC */
+            if (yychar < 0) yychar = YYEOF;
 #if YYDEBUG
             if (yydebug)
             {
-                yys = yyname[YYTRANSLATE(yychar)];
-                printf("%sdebug: state %d, reading %d (%s)\n",
-                        YYPREFIX, YYFINAL, yychar, yys);
+                if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+                fprintf(stderr, "%s[%d]: state %d, reading token %d (%s)\n",
+                                YYDEBUGSTR, yydepth, YYFINAL, yychar, yys);
             }
 #endif
         }
         if (yychar == YYEOF) goto yyaccept;
         goto yyloop;
     }
-    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+    if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
         yystate = yytable[yyn];
     else
         yystate = yydgoto[yym];
 #if YYDEBUG
     if (yydebug)
-        printf("%sdebug: after reduction, shifting from state %d \
-to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
-#endif
-    if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
     {
-        goto yyoverflow;
+        fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+        if (!yytrial)
+#endif /* YYBTYACC */
+            fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[yystate], yyval));
+#endif
+        fprintf(stderr, "shifting from state %d to state %d\n", *yystack.s_mark, yystate);
     }
+#endif
+    if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
     *++yystack.s_mark = (YYINT) yystate;
     *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    *++yystack.p_mark = yyloc;
+#endif
     goto yyloop;
+#if YYBTYACC
+
+    /* Reduction declares that this path is valid. Set yypath and do a full parse */
+yyvalid:
+    if (yypath) YYABORT;
+    while (yyps->save)
+    {
+        YYParseState *save = yyps->save;
+        yyps->save = save->save;
+        save->save = yypath;
+        yypath = save;
+    }
+#if YYDEBUG
+    if (yydebug)
+        fprintf(stderr, "%s[%d]: state %d, CONFLICT trial successful, backtracking to state %d, %d tokens\n",
+                        YYDEBUGSTR, yydepth, yystate, yypath->state, (int)(yylvp - yylvals - yypath->lexeme));
+#endif
+    if (yyerrctx)
+    {
+        yyFreeState(yyerrctx);
+        yyerrctx = NULL;
+    }
+    yylvp          = yylvals + yypath->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yylpp          = yylpsns + yypath->lexeme;
+#endif
+    yylexp         = yylexemes + yypath->lexeme;
+    yychar         = YYEMPTY;
+    yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
+    memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(YYINT));
+    yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
+    memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+    yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
+    memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+    yystate        = yypath->state;
+    goto yyloop;
+#endif /* YYBTYACC */
 
 yyoverflow:
     YYERROR_CALL("yacc stack overflow");
+#if YYBTYACC
+    goto yyabort_nomem;
+yyenomem:
+    YYERROR_CALL("memory exhausted");
+yyabort_nomem:
+#endif /* YYBTYACC */
+    yyresult = 2;
+    goto yyreturn;
 
 yyabort:
-    yyfreestack(&yystack);
-    return (1);
+    yyresult = 1;
+    goto yyreturn;
 
 yyaccept:
+#if YYBTYACC
+    if (yyps->save) goto yyvalid;
+#endif /* YYBTYACC */
+    yyresult = 0;
+
+yyreturn:
+#if defined(YYDESTRUCT_CALL)
+    if (yychar != YYEOF && yychar != YYEMPTY)
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval, &yylloc);
+#else
+        YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+
+    {
+        YYSTYPE *pv;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+        YYLTYPE *pp;
+
+        for (pv = yystack.l_base, pp = yystack.p_base; pv <= yystack.l_mark; ++pv, ++pp)
+             YYDESTRUCT_CALL("cleanup: discarding state",
+                             yystos[*(yystack.s_base + (pv - yystack.l_base))], pv, pp);
+#else
+        for (pv = yystack.l_base; pv <= yystack.l_mark; ++pv)
+             YYDESTRUCT_CALL("cleanup: discarding state",
+                             yystos[*(yystack.s_base + (pv - yystack.l_base))], pv);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+    }
+#endif /* defined(YYDESTRUCT_CALL) */
+
+#if YYBTYACC
+    if (yyerrctx)
+    {
+        yyFreeState(yyerrctx);
+        yyerrctx = NULL;
+    }
+    while (yyps)
+    {
+        YYParseState *save = yyps;
+        yyps = save->save;
+        save->save = NULL;
+        yyFreeState(save);
+    }
+    while (yypath)
+    {
+        YYParseState *save = yypath;
+        yypath = save->save;
+        save->save = NULL;
+        yyFreeState(save);
+    }
+#endif /* YYBTYACC */
     yyfreestack(&yystack);
-    return (0);
+    return (yyresult);
 }
diff --git a/grammar.h b/grammar.h
index 77af815..3326637 100644
--- a/grammar.h
+++ b/grammar.h
@@ -1,3 +1,6 @@
+#ifndef _pcap__defines_h_
+#define _pcap__defines_h_
+
 #define DST 257
 #define SRC 258
 #define HOST 259
@@ -125,7 +128,7 @@
 #endif
 #ifndef YYSTYPE_IS_DECLARED
 #define YYSTYPE_IS_DECLARED 1
-typedef union {
+typedef union YYSTYPE {
 	int i;
 	bpf_u_int32 h;
 	char *s;
@@ -140,4 +143,5 @@
 	struct block *rblk;
 } YYSTYPE;
 #endif /* !YYSTYPE_IS_DECLARED */
-extern YYSTYPE pcap_lval;
+
+#endif /* _pcap__defines_h_ */
diff --git a/grammar.y.in b/grammar.y.in
index 2fbd861..b6a3d18 100644
--- a/grammar.y.in
+++ b/grammar.y.in
@@ -71,6 +71,13 @@
 #include <config.h>
 #endif
 
+/*
+ * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
+ * (see ftmacros.h), so include it early.
+ */
+#include "gencode.h"
+#include "grammar.h"
+
 #include <stdlib.h>
 
 #ifndef _WIN32
@@ -92,17 +99,11 @@
 
 #include "pcap-int.h"
 
-#include "gencode.h"
-#include "grammar.h"
 #include "scanner.h"
 
-#ifdef HAVE_NET_PFVAR_H
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif
 #include "llc.h"
 #include "ieee80211.h"
+#include "pflog.h"
 #include <pcap/namedb.h>
 
 #ifdef HAVE_OS_PROTO_H
@@ -254,60 +255,87 @@
 	bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
-#ifdef HAVE_NET_PFVAR_H
+static const struct tok pflog_reasons[] = {
+	{ PFRES_MATCH,		"match" },
+	{ PFRES_BADOFF,		"bad-offset" },
+	{ PFRES_FRAG,		"fragment" },
+	{ PFRES_SHORT,		"short" },
+	{ PFRES_NORM,		"normalize" },
+	{ PFRES_MEMORY,		"memory" },
+	{ PFRES_TS,		"bad-timestamp" },
+	{ PFRES_CONGEST,	"congestion" },
+	{ PFRES_IPOPTIONS,	"ip-option" },
+	{ PFRES_PROTCKSUM,	"proto-cksum" },
+	{ PFRES_BADSTATE,	"state-mismatch" },
+	{ PFRES_STATEINS,	"state-insert" },
+	{ PFRES_MAXSTATES,	"state-limit" },
+	{ PFRES_SRCLIMIT,	"src-limit" },
+	{ PFRES_SYNPROXY,	"synproxy" },
+#if defined(__FreeBSD__)
+	{ PFRES_MAPFAILED,	"map-failed" },
+#elif defined(__NetBSD__)
+	{ PFRES_STATELOCKED,	"state-locked" },
+#elif defined(__OpenBSD__)
+	{ PFRES_TRANSLATE,	"translate" },
+	{ PFRES_NOROUTE,	"no-route" },
+#elif defined(__APPLE__)
+	{ PFRES_DUMMYNET,	"dummynet" },
+#endif
+	{ 0, NULL }
+};
+
 static int
 pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
-	const char *reasons[] = PFRES_NAMES;
 	int i;
 
-	for (i = 0; reasons[i]; i++) {
-		if (pcap_strcasecmp(reason, reasons[i]) == 0)
-			return (i);
-	}
-	bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
-	return (-1);
+	i = str2tok(reason, pflog_reasons);
+	if (i == -1)
+		bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
+	return (i);
 }
 
+static const struct tok pflog_actions[] = {
+	{ PF_PASS,		"pass" },
+	{ PF_PASS,		"accept" },	/* alias for "pass" */
+	{ PF_DROP,		"drop" },
+	{ PF_DROP,		"block" },	/* alias for "drop" */
+	{ PF_SCRUB,		"scrub" },
+	{ PF_NOSCRUB,		"noscrub" },
+	{ PF_NAT,		"nat" },
+	{ PF_NONAT,		"nonat" },
+	{ PF_BINAT,		"binat" },
+	{ PF_NOBINAT,		"nobinat" },
+	{ PF_RDR,		"rdr" },
+	{ PF_NORDR,		"nordr" },
+	{ PF_SYNPROXY_DROP,	"synproxy-drop" },
+#if defined(__FreeBSD__)
+	{ PF_DEFER,		"defer" },
+#elif defined(__OpenBSD__)
+	{ PF_DEFER,		"defer" },
+	{ PF_MATCH,		"match" },
+	{ PF_DIVERT,		"divert" },
+	{ PF_RT,		"rt" },
+	{ PF_AFRT,		"afrt" },
+#elif defined(__APPLE__)
+	{ PF_DUMMYNET,		"dummynet" },
+	{ PF_NODUMMYNET,	"nodummynet" },
+	{ PF_NAT64,		"nat64" },
+	{ PF_NONAT64,		"nonat64" },
+#endif
+	{ 0, NULL },
+};
+
 static int
 pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
-	if (pcap_strcasecmp(action, "pass") == 0 ||
-	    pcap_strcasecmp(action, "accept") == 0)
-		return (PF_PASS);
-	else if (pcap_strcasecmp(action, "drop") == 0 ||
-		pcap_strcasecmp(action, "block") == 0)
-		return (PF_DROP);
-#if HAVE_PF_NAT_THROUGH_PF_NORDR
-	else if (pcap_strcasecmp(action, "rdr") == 0)
-		return (PF_RDR);
-	else if (pcap_strcasecmp(action, "nat") == 0)
-		return (PF_NAT);
-	else if (pcap_strcasecmp(action, "binat") == 0)
-		return (PF_BINAT);
-	else if (pcap_strcasecmp(action, "nordr") == 0)
-		return (PF_NORDR);
-#endif
-	else {
-		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
-		return (-1);
-	}
-}
-#else /* !HAVE_NET_PFVAR_H */
-static int
-pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
-{
-	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-	return (-1);
-}
+	int i;
 
-static int
-pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
-{
-	bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-	return (-1);
+	i = str2tok(action, pflog_actions);
+	if (i == -1)
+		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
+	return (i);
 }
-#endif /* HAVE_NET_PFVAR_H */
 
 /*
  * For calls that might return an "an error occurred" value.
diff --git a/nametoaddr.c b/nametoaddr.c
index c944ad3..7a04a61 100644
--- a/nametoaddr.c
+++ b/nametoaddr.c
@@ -267,7 +267,7 @@
 	 * *not* always get set if getnetbyname_r() succeeds.
 	 */
 	np = NULL;
- 	err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
+	err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
 	    &h_errnoval);
 	if (err != 0) {
 		/*
@@ -296,16 +296,16 @@
 	else
 		np = &result_buf;
   #else
- 	/*
- 	 * We don't have any getnetbyname_r(); either we have a
- 	 * getnetbyname() that uses thread-specific data, in which
- 	 * case we're thread-safe (sufficiently recent FreeBSD,
- 	 * sufficiently recent Darwin-based OS, sufficiently recent
- 	 * HP-UX, sufficiently recent Tru64 UNIX), or we have the
- 	 * traditional getnetbyname() (everything else, including
- 	 * current NetBSD and OpenBSD), in which case we're not
- 	 * thread-safe.
- 	 */
+	/*
+	 * We don't have any getnetbyname_r(); either we have a
+	 * getnetbyname() that uses thread-specific data, in which
+	 * case we're thread-safe (sufficiently recent FreeBSD,
+	 * sufficiently recent Darwin-based OS, sufficiently recent
+	 * HP-UX, sufficiently recent Tru64 UNIX), or we have the
+	 * traditional getnetbyname() (everything else, including
+	 * current NetBSD and OpenBSD), in which case we're not
+	 * thread-safe.
+	 */
 	np = getnetbyname(name);
   #endif
 	if (np != NULL)
@@ -552,16 +552,16 @@
 	else
 		p = &result_buf;
   #else
- 	/*
- 	 * We don't have any getprotobyname_r(); either we have a
- 	 * getprotobyname() that uses thread-specific data, in which
- 	 * case we're thread-safe (sufficiently recent FreeBSD,
- 	 * sufficiently recent Darwin-based OS, sufficiently recent
- 	 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
+	/*
+	 * We don't have any getprotobyname_r(); either we have a
+	 * getprotobyname() that uses thread-specific data, in which
+	 * case we're thread-safe (sufficiently recent FreeBSD,
+	 * sufficiently recent Darwin-based OS, sufficiently recent
+	 * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
 	 * the traditional getprotobyname() (everything else, including
- 	 * current NetBSD and OpenBSD), in which case we're not
- 	 * thread-safe.
- 	 */
+	 * current NetBSD and OpenBSD), in which case we're not
+	 * thread-safe.
+	 */
 	p = getprotobyname(str);
   #endif
 	if (p != 0)
@@ -785,9 +785,14 @@
 {
 	register u_char *ap;
 	u_char a[6];
+	char namebuf[1024];
 
+	/*
+	 * In AIX 7.1 and 7.2: int ether_hostton(char *, struct ether_addr *);
+	 */
+	pcap_strlcpy(namebuf, name, sizeof(namebuf));
 	ap = NULL;
-	if (ether_hostton(name, (struct ether_addr *)a) == 0) {
+	if (ether_hostton(namebuf, (struct ether_addr *)a) == 0) {
 		ap = (u_char *)malloc(6);
 		if (ap != NULL)
 			memcpy((char *)ap, (char *)a, 6);
diff --git a/optimize.c b/optimize.c
index 610a030..9af4c15 100644
--- a/optimize.c
+++ b/optimize.c
@@ -32,13 +32,14 @@
 #include <memory.h>
 #include <setjmp.h>
 #include <string.h>
-
+#include <limits.h> /* for SIZE_MAX */
 #include <errno.h>
 
 #include "pcap-int.h"
 
 #include "gencode.h"
 #include "optimize.h"
+#include "diag-control.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -2098,7 +2099,7 @@
 		 * 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
+		 * passes in a row where we do nothing but
 		 * move branches.)
 		 */
 		return;
@@ -2421,6 +2422,9 @@
 	}
 	longjmp(opt_state->top_ctx, 1);
 	/* NOTREACHED */
+#ifdef _AIX
+	PCAP_UNREACHABLE
+#endif /* _AIX */
 }
 
 /*
@@ -2606,7 +2610,7 @@
 	}
 
 	/*
-	 * Make sure the total memory required for both of them dosn't
+	 * Make sure the total memory required for both of them doesn't
 	 * overflow.
 	 */
 	if (block_memsize > SIZE_MAX - edge_memsize) {
@@ -2895,7 +2899,6 @@
 	    if (fp == NULL) {
 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "malloc");
-		free(fp);
 		return NULL;
 	    }
 	    memset((char *)fp, 0, sizeof(*fp) * n);
@@ -2925,6 +2928,9 @@
 	va_end(ap);
 	longjmp(conv_state->top_ctx, 1);
 	/* NOTREACHED */
+#ifdef _AIX
+	PCAP_UNREACHABLE
+#endif /* _AIX */
 }
 
 /*
@@ -3023,14 +3029,14 @@
  *
  * example DOT for BPF `ip src host 1.1.1.1' is:
     digraph BPF {
-    	block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh      [12]\n(001) jeq      #0x800           jt 2	jf 5" tooltip="val[A]=0 val[X]=0"];
-    	block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld       [26]\n(003) jeq      #0x1010101       jt 4	jf 5" tooltip="val[A]=0 val[X]=0"];
-    	block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret      #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
-    	block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret      #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
-    	"block0":se -> "block1":n [label="T"];
-    	"block0":sw -> "block3":n [label="F"];
-    	"block1":se -> "block2":n [label="T"];
-    	"block1":sw -> "block3":n [label="F"];
+	block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh      [12]\n(001) jeq      #0x800           jt 2	jf 5" tooltip="val[A]=0 val[X]=0"];
+	block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld       [26]\n(003) jeq      #0x1010101       jt 4	jf 5" tooltip="val[A]=0 val[X]=0"];
+	block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret      #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
+	block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret      #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
+	"block0":se -> "block1":n [label="T"];
+	"block0":sw -> "block3":n [label="F"];
+	"block1":se -> "block2":n [label="T"];
+	"block1":sw -> "block3":n [label="F"];
     }
  *
  *  After install graphviz on https://www.graphviz.org/, save it as bpf.dot
diff --git a/pcap-common.c b/pcap-common.c
index 51d0666..75461b1 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -28,11 +28,6 @@
 #include <pcap-types.h>
 
 #include "pcap-int.h"
-#include "extract.h"
-#include "pcap/sll.h"
-#include "pcap/usb.h"
-#include "pcap/nflog.h"
-#include "pcap/can_socketcan.h"
 
 #include "pcap-common.h"
 
@@ -168,11 +163,20 @@
 #define LINKTYPE_ENC		109		/* OpenBSD IPSEC enc */
 
 /*
- * These three types are reserved for future use.
+ * These two types are reserved for future use.
  */
 #define LINKTYPE_LANE8023	110		/* ATM LANE + 802.3 */
 #define LINKTYPE_HIPPI		111		/* NetBSD HIPPI */
-#define LINKTYPE_HDLC		112		/* NetBSD HDLC framing */
+
+/*
+ * Used for NetBSD DLT_HDLC; from looking at the one driver in NetBSD
+ * that uses it, it's Cisco HDLC, so it's the same as DLT_C_HDLC/
+ * LINKTYPE_C_HDLC, but we define a separate value to avoid some
+ * compatibility issues with programs on NetBSD.
+ *
+ * All code should treat LINKTYPE_NETBSD_HDLC and LINKTYPE_C_HDLC the same.
+ */
+#define LINKTYPE_NETBSD_HDLC	112		/* NetBSD HDLC framing */
 
 #define LINKTYPE_LINUX_SLL	113		/* Linux cooked socket capture */
 #define LINKTYPE_LTALK		114		/* Apple LocalTalk hardware */
@@ -405,7 +409,7 @@
  * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
  * Every frame contains a 32bit A429 label.
  * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ * https://web.archive.org/web/20040616233302/https://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
  */
 #define LINKTYPE_A429           184
 
@@ -956,13 +960,15 @@
 /*
  * Link-layer header type for upper-protocol layer PDU saves from wireshark.
  *
- * the actual contents are determined by two TAGs stored with each
- * packet:
- *   EXP_PDU_TAG_LINKTYPE          the link type (LINKTYPE_ value) of the
- *				   original packet.
+ * the actual contents are determined by two TAGs, one or more of
+ * which is stored with each packet:
  *
- *   EXP_PDU_TAG_PROTO_NAME        the name of the wireshark dissector
- * 				   that can make sense of the data stored.
+ *   EXP_PDU_TAG_DISSECTOR_NAME      the name of the Wireshark dissector
+ *				     that can make sense of the data stored.
+ *
+ *   EXP_PDU_TAG_HEUR_DISSECTOR_NAME the name of the Wireshark heuristic
+ *				     dissector that can make sense of the
+ *				     data stored.
  */
 #define LINKTYPE_WIRESHARK_UPPER_PDU	252
 
@@ -1234,10 +1240,11 @@
 	{ DLT_FR,		LINKTYPE_FRELAY },
 #endif
 
-	{ DLT_ATM_RFC1483, 	LINKTYPE_ATM_RFC1483 },
+	{ DLT_ATM_RFC1483,	LINKTYPE_ATM_RFC1483 },
 	{ DLT_RAW,		LINKTYPE_RAW },
 	{ DLT_SLIP_BSDOS,	LINKTYPE_SLIP_BSDOS },
 	{ DLT_PPP_BSDOS,	LINKTYPE_PPP_BSDOS },
+	{ DLT_HDLC,		LINKTYPE_NETBSD_HDLC },
 
 	/* BSD/OS Cisco HDLC */
 	{ DLT_C_HDLC,		LINKTYPE_C_HDLC },
@@ -1391,286 +1398,3 @@
 		return MAXIMUM_SNAPLEN;
 	}
 }
-
-/*
- * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
- * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
- * with the CAN ID being in host byte order.
- *
- * When reading a DLT_LINUX_SLL capture file, we need to check for those
- * packets and convert the CAN ID from the byte order of the host that
- * wrote the file to this host's byte order.
- */
-static void
-swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
-{
-	u_int caplen = hdr->caplen;
-	u_int length = hdr->len;
-	struct sll_header *shdr = (struct sll_header *)buf;
-	uint16_t protocol;
-	pcap_can_socketcan_hdr *chdr;
-
-	if (caplen < (u_int) sizeof(struct sll_header) ||
-	    length < (u_int) sizeof(struct sll_header)) {
-		/* Not enough data to have the protocol field */
-		return;
-	}
-
-	protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
-	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
-		return;
-
-	/*
-	 * SocketCAN packet; fix up the packet's header.
-	 */
-	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
-	if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
-	    length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
-		/* Not enough data to have the CAN ID */
-		return;
-	}
-	chdr->can_id = SWAPLONG(chdr->can_id);
-}
-
-/*
- * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
- * byte order when capturing (it's supplied directly from a
- * memory-mapped buffer shared by the kernel).
- *
- * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED capture file,
- * we need to convert it from the byte order of the host that wrote
- * the file to this host's byte order.
- */
-static void
-swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
-    int header_len_64_bytes)
-{
-	pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
-	bpf_u_int32 offset = 0;
-
-	/*
-	 * "offset" is the offset *past* the field we're swapping;
-	 * we skip the field *before* checking to make sure
-	 * the captured data length includes the entire field.
-	 */
-
-	/*
-	 * The URB id is a totally opaque value; do we really need to
-	 * convert it to the reading host's byte order???
-	 */
-	offset += 8;			/* skip past id */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->id = SWAPLL(uhdr->id);
-
-	offset += 4;			/* skip past various 1-byte fields */
-
-	offset += 2;			/* skip past bus_id */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
-
-	offset += 2;			/* skip past various 1-byte fields */
-
-	offset += 8;			/* skip past ts_sec */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
-
-	offset += 4;			/* skip past ts_usec */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
-
-	offset += 4;			/* skip past status */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->status = SWAPLONG(uhdr->status);
-
-	offset += 4;			/* skip past urb_len */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->urb_len = SWAPLONG(uhdr->urb_len);
-
-	offset += 4;			/* skip past data_len */
-	if (hdr->caplen < offset)
-		return;
-	uhdr->data_len = SWAPLONG(uhdr->data_len);
-
-	if (uhdr->transfer_type == URB_ISOCHRONOUS) {
-		offset += 4;			/* skip past s.iso.error_count */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
-
-		offset += 4;			/* skip past s.iso.numdesc */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
-	} else
-		offset += 8;			/* skip USB setup header */
-
-	/*
-	 * With the old header, there are no isochronous descriptors
-	 * after the header.
-	 *
-	 * With the new header, the actual number of descriptors in
-	 * the header is not s.iso.numdesc, it's ndesc - only the
-	 * first N descriptors, for some value of N, are put into
-	 * the header, and ndesc is set to the actual number copied.
-	 * In addition, if s.iso.numdesc is negative, no descriptors
-	 * are captured, and ndesc is set to 0.
-	 */
-	if (header_len_64_bytes) {
-		/*
-		 * This is either the "version 1" header, with
-		 * 16 bytes of additional fields at the end, or
-		 * a "version 0" header from a memory-mapped
-		 * capture, with 16 bytes of zeroed-out padding
-		 * at the end.  Byte swap them as if this were
-		 * a "version 1" header.
-		 */
-		offset += 4;			/* skip past interval */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->interval = SWAPLONG(uhdr->interval);
-
-		offset += 4;			/* skip past start_frame */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->start_frame = SWAPLONG(uhdr->start_frame);
-
-		offset += 4;			/* skip past xfer_flags */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
-
-		offset += 4;			/* skip past ndesc */
-		if (hdr->caplen < offset)
-			return;
-		uhdr->ndesc = SWAPLONG(uhdr->ndesc);
-
-		if (uhdr->transfer_type == URB_ISOCHRONOUS) {
-			/* swap the values in struct linux_usb_isodesc */
-			usb_isodesc *pisodesc;
-			uint32_t i;
-
-			pisodesc = (usb_isodesc *)(void *)(buf+offset);
-			for (i = 0; i < uhdr->ndesc; i++) {
-				offset += 4;		/* skip past status */
-				if (hdr->caplen < offset)
-					return;
-				pisodesc->status = SWAPLONG(pisodesc->status);
-
-				offset += 4;		/* skip past offset */
-				if (hdr->caplen < offset)
-					return;
-				pisodesc->offset = SWAPLONG(pisodesc->offset);
-
-				offset += 4;		/* skip past len */
-				if (hdr->caplen < offset)
-					return;
-				pisodesc->len = SWAPLONG(pisodesc->len);
-
-				offset += 4;		/* skip past padding */
-
-				pisodesc++;
-			}
-		}
-	}
-}
-
-/*
- * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order
- * data.  They begin with a fixed-length header with big-endian fields,
- * followed by a set of TLVs, where the type and length are in host
- * byte order but the values are either big-endian or are a raw byte
- * sequence that's the same regardless of the host's byte order.
- *
- * When reading a DLT_NFLOG capture file, we need to convert the type
- * and length values from the byte order of the host that wrote the
- * file to the byte order of this host.
- */
-static void
-swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
-{
-	u_char *p = buf;
-	nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf;
-	nflog_tlv_t *tlv;
-	u_int caplen = hdr->caplen;
-	u_int length = hdr->len;
-	uint16_t size;
-
-	if (caplen < (u_int) sizeof(nflog_hdr_t) ||
-	    length < (u_int) sizeof(nflog_hdr_t)) {
-		/* Not enough data to have any TLVs. */
-		return;
-	}
-
-	if (nfhdr->nflog_version != 0) {
-		/* Unknown NFLOG version */
-		return;
-	}
-
-	length -= sizeof(nflog_hdr_t);
-	caplen -= sizeof(nflog_hdr_t);
-	p += sizeof(nflog_hdr_t);
-
-	while (caplen >= sizeof(nflog_tlv_t)) {
-		tlv = (nflog_tlv_t *) p;
-
-		/* Swap the type and length. */
-		tlv->tlv_type = SWAPSHORT(tlv->tlv_type);
-		tlv->tlv_length = SWAPSHORT(tlv->tlv_length);
-
-		/* Get the length of the TLV. */
-		size = tlv->tlv_length;
-		if (size % 4 != 0)
-			size += 4 - size % 4;
-
-		/* Is the TLV's length less than the minimum? */
-		if (size < sizeof(nflog_tlv_t)) {
-			/* Yes. Give up now. */
-			return;
-		}
-
-		/* Do we have enough data for the full TLV? */
-		if (caplen < size || length < size) {
-			/* No. */
-			return;
-		}
-
-		/* Skip over the TLV. */
-		length -= size;
-		caplen -= size;
-		p += size;
-	}
-}
-
-void
-swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
-{
-	/*
-	 * Convert pseudo-headers from the byte order of
-	 * the host on which the file was saved to our
-	 * byte order, as necessary.
-	 */
-	switch (linktype) {
-
-	case DLT_LINUX_SLL:
-		swap_linux_sll_header(hdr, data);
-		break;
-
-	case DLT_USB_LINUX:
-		swap_linux_usb_header(hdr, data, 0);
-		break;
-
-	case DLT_USB_LINUX_MMAPPED:
-		swap_linux_usb_header(hdr, data, 1);
-		break;
-
-	case DLT_NFLOG:
-		swap_nflog_header(hdr, data);
-		break;
-	}
-}
diff --git a/pcap-common.h b/pcap-common.h
index 8795a82..d765c94 100644
--- a/pcap-common.h
+++ b/pcap-common.h
@@ -21,33 +21,8 @@
  * pcap-common.h - common code for pcap and pcapng files
  */
 
-/*
- * We use the "receiver-makes-right" approach to byte order,
- * because time is at a premium when we are writing the file.
- * In other words, the pcap_file_header and pcap_pkthdr,
- * records are written in host byte order.
- * Note that the bytes of packet data are written out in the order in
- * which they were received, so multi-byte fields in packets are not
- * written in host byte order, they're written in whatever order the
- * sending machine put them in.
- *
- * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
- * machine (if the file was written in little-end order).
- */
-#define	SWAPLONG(y) \
-    (((((u_int)(y))&0xff)<<24) | \
-     ((((u_int)(y))&0xff00)<<8) | \
-     ((((u_int)(y))&0xff0000)>>8) | \
-     ((((u_int)(y))>>24)&0xff))
-#define	SWAPSHORT(y) \
-     ((u_short)(((((u_int)(y))&0xff)<<8) | \
-                ((((u_int)(y))&0xff00)>>8)))
-
 extern int dlt_to_linktype(int dlt);
 
 extern int linktype_to_dlt(int linktype);
 
-extern void swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr,
-    u_char *data);
-
 extern u_int max_snaplen_for_dlt(int dlt);
diff --git a/pcap-int.h b/pcap-int.h
index dc18d50..894e74a 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -53,6 +53,24 @@
 #include "portability.h"
 
 /*
+ * 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.  Make sure we have VS 2015 or later.
+   */
+  #if _MSC_VER < 1900
+    #error "Building libpcap requires VS 2015 or later"
+  #endif
+#endif
+
+/*
  * Version string.
  * Uses PACKAGE_VERSION from config.h.
  */
@@ -467,7 +485,7 @@
 /*
  * 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
+ * buffer pointer, the size for the private data type, in bytes, and the
  * offset of the private data from the beginning of the structure, in
  * bytes.
  */
@@ -551,7 +569,7 @@
 /*
  * 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
+ * buffer pointer, the size for the private data type, in bytes, and the
  * offset of the private data from the beginning of the structure, in
  * bytes.
  */
diff --git a/pcap-usb-linux-common.c b/pcap-usb-linux-common.c
new file mode 100644
index 0000000..fb4a8c1
--- /dev/null
+++ b/pcap-usb-linux-common.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-usb-linux-common.c - common code for everything that needs to
+ * deal with Linux USB captures.
+ */
+
+#include "pcap/pcap.h"
+#include "pcap/usb.h"
+
+#include "pcap-usb-linux-common.h"
+
+/*
+ * Compute, from the data provided by the Linux USB memory-mapped capture
+ * mechanism, the amount of packet data that would have been provided
+ * had the capture mechanism not chopped off any data at the end, if, in
+ * fact, it did so.
+ *
+ * Set the "unsliced length" field of the packet header to that value.
+ */
+void
+fix_linux_usb_mmapped_length(struct pcap_pkthdr *pkth, const u_char *bp)
+{
+	const pcap_usb_header_mmapped *hdr;
+	u_int bytes_left;
+
+	/*
+	 * All callers of this routine must ensure that pkth->caplen is
+	 * >= sizeof (pcap_usb_header_mmapped).
+	 */
+	bytes_left = pkth->caplen;
+	bytes_left -= sizeof (pcap_usb_header_mmapped);
+
+	hdr = (const pcap_usb_header_mmapped *) bp;
+	if (!hdr->data_flag && hdr->transfer_type == URB_ISOCHRONOUS &&
+	    hdr->event_type == URB_COMPLETE &&
+	    (hdr->endpoint_number & URB_TRANSFER_IN) &&
+	    pkth->len == sizeof(pcap_usb_header_mmapped) +
+	                 (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len) {
+		usb_isodesc *descs;
+		u_int pre_truncation_data_len, pre_truncation_len;
+
+		descs = (usb_isodesc *) (bp + sizeof(pcap_usb_header_mmapped));
+
+		/*
+		 * We have data (yes, data_flag is 0 if we *do* have data),
+		 * and this is a "this is complete" incoming isochronous
+		 * transfer event, and the length was calculated based
+		 * on the URB length.
+		 *
+		 * That's not correct, because the data isn't contiguous,
+		 * and the isochronous descriptos show how it's scattered.
+		 *
+		 * Find the end of the last chunk of data in the buffer
+		 * referred to by the isochronous descriptors; that indicates
+		 * how far into the buffer the data would have gone.
+		 *
+		 * Make sure we don't run past the end of the captured data
+		 * while processing the isochronous descriptors.
+		 */
+		pre_truncation_data_len = 0;
+		for (uint32_t desc = 0;
+		    desc < hdr->ndesc && bytes_left >= sizeof (usb_isodesc);
+		    desc++, bytes_left -= sizeof (usb_isodesc)) {
+			u_int desc_end;
+
+			if (descs[desc].len != 0) {
+				desc_end = descs[desc].offset + descs[desc].len;
+				if (desc_end > pre_truncation_data_len)
+					pre_truncation_data_len = desc_end;
+			}
+		}
+
+		/*
+		 * Now calculate the total length based on that data
+		 * length.
+		 */
+		pre_truncation_len = sizeof(pcap_usb_header_mmapped) +
+		    (hdr->ndesc * sizeof (usb_isodesc)) +
+		    pre_truncation_data_len;
+
+		/*
+		 * If that's greater than or equal to the captured length,
+		 * use that as the length.
+		 */
+		if (pre_truncation_len >= pkth->caplen)
+			pkth->len = pre_truncation_len;
+
+		/*
+		 * If the captured length is greater than the length,
+		 * use the captured length.
+		 *
+		 * For completion events for incoming isochronous transfers,
+		 * it's based on data_len, which is calculated the same way
+		 * we calculated pre_truncation_data_len above, except that
+		 * it has access to all the isochronous descriptors, not
+		 * just the ones that the kernel were able to provide us or,
+		 * for a capture file, that weren't sliced off by a snapshot
+		 * length.
+		 *
+		 * However, it might have been reduced by the USB capture
+		 * mechanism arbitrarily limiting the amount of data it
+		 * provides to userland, or by the libpcap capture code
+		 * limiting it to being no more than the snapshot, so
+		 * we don't want to just use it all the time; we only
+		 * do so to try to get a better estimate of the actual
+		 * length - and to make sure the on-the-network length
+		 * is always >= the captured length.
+		 */
+		if (pkth->caplen > pkth->len)
+			pkth->len = pkth->caplen;
+	}
+}
diff --git a/pcap-usb-linux-common.h b/pcap-usb-linux-common.h
new file mode 100644
index 0000000..8cff7ba
--- /dev/null
+++ b/pcap-usb-linux-common.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-usb-linux-common.h - common code for everything that needs to
+ * deal with Linux USB captures.
+ */
+
+extern void fix_linux_usb_mmapped_length(struct pcap_pkthdr *pkth,
+    const u_char *bp);
diff --git a/pcap-util.c b/pcap-util.c
new file mode 100644
index 0000000..8b5669e
--- /dev/null
+++ b/pcap-util.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-common.c - common code for pcap and pcapng files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+
+#include "pcap-int.h"
+#include "extract.h"
+#include "pcap-usb-linux-common.h"
+
+#include "pcap-util.h"
+
+#include "pflog.h"
+#include "pcap/can_socketcan.h"
+#include "pcap/sll.h"
+#include "pcap/usb.h"
+#include "pcap/nflog.h"
+
+/*
+ * Most versions of the DLT_PFLOG pseudo-header have UID and PID fields
+ * that are saved in host byte order.
+ *
+ * When reading a DLT_PFLOG packet, we need to convert those fields from
+ * the byte order of the host that wrote the file to this host's byte
+ * order.
+ */
+static void
+swap_pflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+	u_int caplen = hdr->caplen;
+	u_int length = hdr->len;
+	u_int pfloghdr_length;
+	struct pfloghdr *pflhdr = (struct pfloghdr *)buf;
+
+	if (caplen < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid) ||
+	    length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
+		/* Not enough data to have the uid field */
+		return;
+	}
+
+	pfloghdr_length = pflhdr->length;
+
+	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) {
+		/* Header doesn't include uid field */
+		return;
+	}
+	pflhdr->uid = SWAPLONG(pflhdr->uid);
+
+	if (caplen < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid) ||
+	    length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
+		/* Not enough data to have the pid field */
+		return;
+	}
+	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) {
+		/* Header doesn't include pid field */
+		return;
+	}
+	pflhdr->pid = SWAPLONG(pflhdr->pid);
+
+	if (caplen < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid) ||
+	    length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
+		/* Not enough data to have the rule_uid field */
+		return;
+	}
+	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) {
+		/* Header doesn't include rule_uid field */
+		return;
+	}
+	pflhdr->rule_uid = SWAPLONG(pflhdr->rule_uid);
+
+	if (caplen < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid) ||
+	    length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
+		/* Not enough data to have the rule_pid field */
+		return;
+	}
+	if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) {
+		/* Header doesn't include rule_pid field */
+		return;
+	}
+	pflhdr->rule_pid = SWAPLONG(pflhdr->rule_pid);
+}
+
+/*
+ * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
+ * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
+ * with the CAN ID being in host byte order.
+ *
+ * When reading a DLT_LINUX_SLL packet, we need to check for those
+ * packets and convert the CAN ID from the byte order of the host that
+ * wrote the file to this host's byte order.
+ */
+static void
+swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+	u_int caplen = hdr->caplen;
+	u_int length = hdr->len;
+	struct sll_header *shdr = (struct sll_header *)buf;
+	uint16_t protocol;
+	pcap_can_socketcan_hdr *chdr;
+
+	if (caplen < (u_int) sizeof(struct sll_header) ||
+	    length < (u_int) sizeof(struct sll_header)) {
+		/* Not enough data to have the protocol field */
+		return;
+	}
+
+	protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
+	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
+		return;
+
+	/*
+	 * SocketCAN packet; fix up the packet's header.
+	 */
+	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
+	if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
+	    length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
+		/* Not enough data to have the CAN ID */
+		return;
+	}
+	chdr->can_id = SWAPLONG(chdr->can_id);
+}
+
+/*
+ * The same applies for DLT_LINUX_SLL2.
+ */
+static void
+swap_linux_sll2_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+	u_int caplen = hdr->caplen;
+	u_int length = hdr->len;
+	struct sll2_header *shdr = (struct sll2_header *)buf;
+	uint16_t protocol;
+	pcap_can_socketcan_hdr *chdr;
+
+	if (caplen < (u_int) sizeof(struct sll2_header) ||
+	    length < (u_int) sizeof(struct sll2_header)) {
+		/* Not enough data to have the protocol field */
+		return;
+	}
+
+	protocol = EXTRACT_BE_U_2(&shdr->sll2_protocol);
+	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
+		return;
+
+	/*
+	 * SocketCAN packet; fix up the packet's header.
+	 */
+	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll2_header));
+	if (caplen < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id) ||
+	    length < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id)) {
+		/* Not enough data to have the CAN ID */
+		return;
+	}
+	chdr->can_id = SWAPLONG(chdr->can_id);
+}
+
+/*
+ * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
+ * byte order when capturing (it's supplied directly from a
+ * memory-mapped buffer shared by the kernel).
+ *
+ * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED packet, we
+ * need to convert it from the byte order of the host that wrote the
+ * file to this host's byte order.
+ */
+static void
+swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+    int header_len_64_bytes)
+{
+	pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
+	bpf_u_int32 offset = 0;
+
+	/*
+	 * "offset" is the offset *past* the field we're swapping;
+	 * we skip the field *before* checking to make sure
+	 * the captured data length includes the entire field.
+	 */
+
+	/*
+	 * The URB id is a totally opaque value; do we really need to
+	 * convert it to the reading host's byte order???
+	 */
+	offset += 8;			/* skip past id */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->id = SWAPLL(uhdr->id);
+
+	offset += 4;			/* skip past various 1-byte fields */
+
+	offset += 2;			/* skip past bus_id */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
+
+	offset += 2;			/* skip past various 1-byte fields */
+
+	offset += 8;			/* skip past ts_sec */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
+
+	offset += 4;			/* skip past ts_usec */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
+
+	offset += 4;			/* skip past status */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->status = SWAPLONG(uhdr->status);
+
+	offset += 4;			/* skip past urb_len */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->urb_len = SWAPLONG(uhdr->urb_len);
+
+	offset += 4;			/* skip past data_len */
+	if (hdr->caplen < offset)
+		return;
+	uhdr->data_len = SWAPLONG(uhdr->data_len);
+
+	if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+		offset += 4;			/* skip past s.iso.error_count */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
+
+		offset += 4;			/* skip past s.iso.numdesc */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
+	} else
+		offset += 8;			/* skip USB setup header */
+
+	/*
+	 * With the old header, there are no isochronous descriptors
+	 * after the header.
+	 *
+	 * With the new header, the actual number of descriptors in
+	 * the header is not s.iso.numdesc, it's ndesc - only the
+	 * first N descriptors, for some value of N, are put into
+	 * the header, and ndesc is set to the actual number copied.
+	 * In addition, if s.iso.numdesc is negative, no descriptors
+	 * are captured, and ndesc is set to 0.
+	 */
+	if (header_len_64_bytes) {
+		/*
+		 * This is either the "version 1" header, with
+		 * 16 bytes of additional fields at the end, or
+		 * a "version 0" header from a memory-mapped
+		 * capture, with 16 bytes of zeroed-out padding
+		 * at the end.  Byte swap them as if this were
+		 * a "version 1" header.
+		 */
+		offset += 4;			/* skip past interval */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->interval = SWAPLONG(uhdr->interval);
+
+		offset += 4;			/* skip past start_frame */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->start_frame = SWAPLONG(uhdr->start_frame);
+
+		offset += 4;			/* skip past xfer_flags */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
+
+		offset += 4;			/* skip past ndesc */
+		if (hdr->caplen < offset)
+			return;
+		uhdr->ndesc = SWAPLONG(uhdr->ndesc);
+
+		if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+			/* swap the values in struct linux_usb_isodesc */
+			usb_isodesc *pisodesc;
+			uint32_t i;
+
+			pisodesc = (usb_isodesc *)(void *)(buf+offset);
+			for (i = 0; i < uhdr->ndesc; i++) {
+				offset += 4;		/* skip past status */
+				if (hdr->caplen < offset)
+					return;
+				pisodesc->status = SWAPLONG(pisodesc->status);
+
+				offset += 4;		/* skip past offset */
+				if (hdr->caplen < offset)
+					return;
+				pisodesc->offset = SWAPLONG(pisodesc->offset);
+
+				offset += 4;		/* skip past len */
+				if (hdr->caplen < offset)
+					return;
+				pisodesc->len = SWAPLONG(pisodesc->len);
+
+				offset += 4;		/* skip past padding */
+
+				pisodesc++;
+			}
+		}
+	}
+}
+
+/*
+ * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order
+ * data.  They begin with a fixed-length header with big-endian fields,
+ * followed by a set of TLVs, where the type and length are in host
+ * byte order but the values are either big-endian or are a raw byte
+ * sequence that's the same regardless of the host's byte order.
+ *
+ * When reading a DLT_NFLOG packet, we need to convert the type and
+ * length values from the byte order of the host that wrote the file
+ * to the byte order of this host.
+ */
+static void
+swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+	u_char *p = buf;
+	nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf;
+	nflog_tlv_t *tlv;
+	u_int caplen = hdr->caplen;
+	u_int length = hdr->len;
+	uint16_t size;
+
+	if (caplen < (u_int) sizeof(nflog_hdr_t) ||
+	    length < (u_int) sizeof(nflog_hdr_t)) {
+		/* Not enough data to have any TLVs. */
+		return;
+	}
+
+	if (nfhdr->nflog_version != 0) {
+		/* Unknown NFLOG version */
+		return;
+	}
+
+	length -= sizeof(nflog_hdr_t);
+	caplen -= sizeof(nflog_hdr_t);
+	p += sizeof(nflog_hdr_t);
+
+	while (caplen >= sizeof(nflog_tlv_t)) {
+		tlv = (nflog_tlv_t *) p;
+
+		/* Swap the type and length. */
+		tlv->tlv_type = SWAPSHORT(tlv->tlv_type);
+		tlv->tlv_length = SWAPSHORT(tlv->tlv_length);
+
+		/* Get the length of the TLV. */
+		size = tlv->tlv_length;
+		if (size % 4 != 0)
+			size += 4 - size % 4;
+
+		/* Is the TLV's length less than the minimum? */
+		if (size < sizeof(nflog_tlv_t)) {
+			/* Yes. Give up now. */
+			return;
+		}
+
+		/* Do we have enough data for the full TLV? */
+		if (caplen < size || length < size) {
+			/* No. */
+			return;
+		}
+
+		/* Skip over the TLV. */
+		length -= size;
+		caplen -= size;
+		p += size;
+	}
+}
+
+static void
+swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
+{
+	/*
+	 * Convert pseudo-headers from the byte order of
+	 * the host on which the file was saved to our
+	 * byte order, as necessary.
+	 */
+	switch (linktype) {
+
+	case DLT_PFLOG:
+		swap_pflog_header(hdr, data);
+		break;
+
+	case DLT_LINUX_SLL:
+		swap_linux_sll_header(hdr, data);
+		break;
+
+	case DLT_LINUX_SLL2:
+		swap_linux_sll2_header(hdr, data);
+		break;
+
+	case DLT_USB_LINUX:
+		swap_linux_usb_header(hdr, data, 0);
+		break;
+
+	case DLT_USB_LINUX_MMAPPED:
+		swap_linux_usb_header(hdr, data, 1);
+		break;
+
+	case DLT_NFLOG:
+		swap_nflog_header(hdr, data);
+		break;
+	}
+}
+
+void
+pcap_post_process(int linktype, int swapped, struct pcap_pkthdr *hdr,
+    u_char *data)
+{
+	if (swapped)
+		swap_pseudo_headers(linktype, hdr, data);
+
+	fixup_pcap_pkthdr(linktype, hdr, data);
+}
+
+void
+fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr, const u_char *data)
+{
+	const pcap_usb_header_mmapped *usb_hdr;
+
+	usb_hdr = (const pcap_usb_header_mmapped *) data;
+	if (linktype == DLT_USB_LINUX_MMAPPED &&
+	    hdr->caplen >= sizeof (pcap_usb_header_mmapped)) {
+		/*
+		 * In older versions of libpcap, in memory-mapped captures,
+		 * the "on-the-bus length" for completion events for
+		 * incoming isochronous transfers was miscalculated; it
+		 * needed to be calculated based on the* offsets and lengths
+		 * in the descriptors, not on the raw URB length, but it
+		 * wasn't.
+		 *
+		 * If this packet contains transferred data (yes, data_flag
+		 * is 0 if we *do* have data), and the total on-the-network
+		 * length is equal to the value calculated from the raw URB
+		 * length, then it might be one of those transfers.
+		 *
+		 * We only do this if we have the full USB pseudo-header.
+		 */
+		if (!usb_hdr->data_flag &&
+		    hdr->len == sizeof(pcap_usb_header_mmapped) +
+		      (usb_hdr->ndesc * sizeof (usb_isodesc)) + usb_hdr->urb_len) {
+			/*
+			 * It might need fixing; fix it if it's a completion
+			 * event for an incoming isochronous transfer.
+			 */
+			fix_linux_usb_mmapped_length(hdr, data);
+		}
+	}
+}
diff --git a/pcap-util.h b/pcap-util.h
new file mode 100644
index 0000000..de95819
--- /dev/null
+++ b/pcap-util.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-util.h - common code for various files
+ */
+
+/*
+ * We use the "receiver-makes-right" approach to byte order;
+ * because time is at a premium when we are writing the file.
+ * In other words, the pcap_file_header and pcap_pkthdr,
+ * records are written in host byte order.
+ * Note that the bytes of packet data are written out in the order in
+ * which they were received, so multi-byte fields in packets are not
+ * written in host byte order, they're written in whatever order the
+ * sending machine put them in.
+ *
+ * We also use this for fixing up packet data headers from a remote
+ * capture, where the server may have a different byte order from the
+ * client.
+ *
+ * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
+ * machine (if the file was written in little-end order).
+ */
+#define	SWAPLONG(y) \
+    (((((u_int)(y))&0xff)<<24) | \
+     ((((u_int)(y))&0xff00)<<8) | \
+     ((((u_int)(y))&0xff0000)>>8) | \
+     ((((u_int)(y))>>24)&0xff))
+#define	SWAPSHORT(y) \
+     ((u_short)(((((u_int)(y))&0xff)<<8) | \
+                ((((u_int)(y))&0xff00)>>8)))
+
+extern void pcap_post_process(int linktype, int swapped,
+    struct pcap_pkthdr *hdr, u_char *data);
+
+extern void fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr,
+    const u_char *data);
+
diff --git a/pcap.c b/pcap.c
index ed8570a..ef1bbb7 100644
--- a/pcap.c
+++ b/pcap.c
@@ -131,8 +131,6 @@
 
 #ifdef _WIN32
 /*
- * DllMain(), required when built as a Windows DLL.
- *
  * To quote the WSAStartup() documentation:
  *
  *   The WSAStartup function typically leads to protocol-specific helper
@@ -147,19 +145,12 @@
  *   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.)
+ * So we don't initialize Winsock in a DllMain() routine.
+ *
+ * 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 _U_,
-  DWORD dwReason _U_,
-  LPVOID lpvReserved _U_
-)
-{
-	return (TRUE);
-}
 
 /*
  * Start Winsock.
@@ -259,7 +250,7 @@
 			if (pcap_utf_8_mode) {
 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Multiple pcap_init calls with different character encodings");
-				return (-1);
+				return (PCAP_ERROR);
 			}
 		}
 		break;
@@ -270,7 +261,7 @@
 			if (!pcap_utf_8_mode) {
 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Multiple pcap_init calls with different character encodings");
-				return (-1);
+				return (PCAP_ERROR);
 			}
 		}
 		pcap_utf_8_mode = 1;
@@ -278,7 +269,7 @@
 
 	default:
 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
-		return (-1);
+		return (PCAP_ERROR);
 	}
 
 	/*
@@ -303,7 +294,7 @@
 	 */
 	if (internal_wsockinit(errbuf) == -1) {
 		/* Failed. */
-		return (-1);
+		return (PCAP_ERROR);
 	}
 #endif
 
@@ -622,7 +613,9 @@
 		 * Return codes for pcap_offline_read() are:
 		 *   -  0: EOF
 		 *   - -1: error
-		 *   - >1: OK
+		 *   - >0: OK - result is number of packets read, so
+		 *         it will be 1 in this case, as we've passed
+		 *         a maximum packet count of 1
 		 * The first one ('0') conflicts with the return code of
 		 * 0 from pcap_read() meaning "no packets arrived before
 		 * the timeout expired", so we map it to -2 so you can
@@ -641,7 +634,9 @@
 	 *   -  0: timeout
 	 *   - -1: error
 	 *   - -2: loop was broken out of with pcap_breakloop()
-	 *   - >1: OK
+	 *   - >0: OK, result is number of packets captured, so
+	 *         it will be 1 in this case, as we've passed
+	 *         a maximum packet count of 1
 	 * The first one ('0') conflicts with the return code of 0 from
 	 * pcap_offline_read() meaning "end of file".
 	*/
@@ -2849,17 +2844,41 @@
 		goto fail;
 	return (p);
 fail:
-	if (status == PCAP_ERROR)
+	if (status == PCAP_ERROR) {
+		/*
+		 * Another buffer is a bit cumbersome, but it avoids
+		 * -Wformat-truncation.
+		 */
+		char trimbuf[PCAP_ERRBUF_SIZE - 5]; /* 2 bytes shorter */
+
+		pcap_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
-		    PCAP_ERRBUF_SIZE - 3, p->errbuf);
-	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+		    PCAP_ERRBUF_SIZE - 3, trimbuf);
+	} else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
 	    status == PCAP_ERROR_PERM_DENIED ||
-	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
-		    pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
-	else
+	    status == PCAP_ERROR_PROMISC_PERM_DENIED) {
+		/*
+		 * Only show the additional message if it's not
+		 * empty.
+		 */
+		if (p->errbuf[0] != '\0') {
+			/*
+			 * Idem.
+			 */
+			char trimbuf[PCAP_ERRBUF_SIZE - 8]; /* 2 bytes shorter */
+
+			pcap_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)",
+			    device, pcap_statustostr(status),
+			    PCAP_ERRBUF_SIZE - 6, trimbuf);
+		} else {
+			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+			    device, pcap_statustostr(status));
+		}
+	} else {
 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
 		    pcap_statustostr(status));
+	}
 	pcap_close(p);
 	return (NULL);
 }
@@ -3350,7 +3369,7 @@
         if (description != NULL) {
                 return description;
         } else {
-                (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
+                (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %d", dlt);
                 return unkbuf;
         }
 }
@@ -3461,14 +3480,14 @@
 		/*
 		 * This is a bogus and now-deprecated API; we
 		 * squelch the narrowing warning for the cast
-		 * from HANDLE to DWORD.  If Windows programmmers
+		 * from HANDLE to intptr_t.  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);
+		return ((int)(intptr_t)p->handle);
 DIAG_ON_NARROWING
 	} else
 		return (PCAP_ERROR);
@@ -3644,7 +3663,7 @@
 		return ("That operation is supported only in monitor mode");
 
 	case PCAP_ERROR_PERM_DENIED:
-		return ("You don't have permission to capture on that device");
+		return ("You don't have permission to perform this capture on that device");
 
 	case PCAP_ERROR_IFACE_NOT_UP:
 		return ("That device is not up");
@@ -3986,6 +4005,10 @@
 void
 pcap_cleanup_live_common(pcap_t *p)
 {
+	if (p->opt.device != NULL) {
+		free(p->opt.device);
+		p->opt.device = NULL;
+	}
 	if (p->buffer != NULL) {
 		free(p->buffer);
 		p->buffer = NULL;
@@ -4064,14 +4087,12 @@
 void
 pcap_close(pcap_t *p)
 {
-	if (p->opt.device != NULL)
-		free(p->opt.device);
 	p->cleanup_op(p);
 	free(p);
 }
 
 /*
- * Helpers for safely loding code at run time.
+ * Helpers for safely loading code at run time.
  * Currently Windows-only.
  */
 #ifdef _WIN32
@@ -4180,6 +4201,20 @@
 	return (-1);
 }
 
+static void
+pcap_breakloop_dead(pcap_t *p _U_)
+{
+	/*
+	 * A "dead" pcap_t is just a placeholder to use in order to
+	 * compile a filter to BPF code or to open a savefile for
+	 * writing.  It doesn't support any operations, including
+	 * capturing or reading packets, so there will never be a
+	 * get-packets loop in progress to break out *of*.
+	 *
+	 * As such, this routine doesn't need to do anything.
+	 */
+}
+
 static int
 pcap_inject_dead(pcap_t *p, const void *buf _U_, int size _U_)
 {
@@ -4393,6 +4428,7 @@
 	p->live_dump_ended_op = pcap_live_dump_ended_dead;
 	p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
 #endif
+	p->breakloop_op = pcap_breakloop_dead;
 	p->cleanup_op = pcap_cleanup_dead;
 
 	/*
diff --git a/pcap/bpf.h b/pcap/bpf.h
index 54373af..3970d0a 100644
--- a/pcap/bpf.h
+++ b/pcap/bpf.h
@@ -80,7 +80,6 @@
 #define lib_pcap_bpf_h
 
 #include <pcap/funcattrs.h>
-
 #include <pcap/dlt.h>
 
 #ifdef __cplusplus
@@ -150,7 +149,7 @@
 #define		BPF_B		0x10
 /*				0x18	reserved; used by BSD/OS */
 #define BPF_MODE(code)	((code) & 0xe0)
-#define		BPF_IMM 	0x00
+#define		BPF_IMM	0x00
 #define		BPF_ABS		0x20
 #define		BPF_IND		0x40
 #define		BPF_MEM		0x60
@@ -244,8 +243,8 @@
  */
 struct bpf_insn {
 	u_short	code;
-	u_char 	jt;
-	u_char 	jf;
+	u_char	jt;
+	u_char	jf;
 	bpf_u_int32 k;
 };
 
diff --git a/pcap/can_socketcan.h b/pcap/can_socketcan.h
index 332d9ff..0cb3584 100644
--- a/pcap/can_socketcan.h
+++ b/pcap/can_socketcan.h
@@ -48,9 +48,14 @@
 typedef struct {
 	uint32_t can_id;
 	uint8_t payload_length;
-	uint8_t pad;
+	uint8_t fd_flags;
 	uint8_t reserved1;
 	uint8_t reserved2;
 } pcap_can_socketcan_hdr;
 
+/* Bits in the fd_flags field */
+#define CANFD_BRS   0x01 /* bit rate switch (second bitrate for payload data) */
+#define CANFD_ESI   0x02 /* error state indicator of the transmitting node */
+#define CANFD_FDF   0x04 /* mark CAN FD for dual use of CAN format */
+
 #endif
diff --git a/pcap/compiler-tests.h b/pcap/compiler-tests.h
index a69c2b0..2d98a70 100644
--- a/pcap/compiler-tests.h
+++ b/pcap/compiler-tests.h
@@ -80,9 +80,11 @@
  */
 
 #if ! defined(__GNUC__)
-#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) 0
+  /* Not GCC and not "just like GCC" */
+  #define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) 0
 #else
-#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) \
+  /* GCC or "just like GCC" */
+  #define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) \
 	(__GNUC__ > (major) || \
 	 (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
 #endif
@@ -92,9 +94,11 @@
  */
 
 #if !defined(__clang__)
-#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) 0
+  /* Not Clang */
+  #define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) 0
 #else
-#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) \
+  /* Clang */
+  #define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) \
 	(__clang_major__ > (major) || \
 	 (__clang_major__ == (major) && __clang_minor__ >= (minor)))
 #endif
@@ -118,13 +122,15 @@
  */
 
 #if ! defined(__SUNPRO_C)
-#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) 0
+  /* Not Sun/Oracle C */
+  #define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) 0
 #else
-#define PCAP_SUNPRO_VERSION_TO_BCD(major, minor) \
+  /* Sun/Oracle C */
+  #define PCAP_SUNPRO_VERSION_TO_BCD(major, minor) \
 	(((minor) >= 10) ? \
 	    (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \
 	    (((major) << 8) | ((minor) << 4)))
-#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) \
+  #define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) \
 	(__SUNPRO_C >= PCAP_SUNPRO_VERSION_TO_BCD((major), (minor)))
 #endif
 
@@ -133,13 +139,31 @@
  *
  * The version number in __xlC__ has the major version in the
  * upper 8 bits and the minor version in the lower 8 bits.
+ * On AIX __xlC__ is always defined, __ibmxl__ becomes defined in XL C 16.1.
+ * On Linux since XL C 13.1.6 __xlC__ is not defined by default anymore, but
+ * __ibmxl__ is defined since at least XL C 13.1.1.
  */
 
-#if ! defined(__xlC__)
-#define PCAP_IS_AT_LEAST_XL_C_VERSION(major,minor) 0
+#if ! defined(__xlC__) && ! defined(__ibmxl__)
+  /* Not XL C */
+  #define PCAP_IS_AT_LEAST_XL_C_VERSION(major,minor) 0
 #else
-#define PCAP_IS_AT_LEAST_XL_C_VERSION(major, minor) \
+  /* XL C */
+  #if defined(__ibmxl__)
+    /*
+     * Later Linux version of XL C; use __ibmxl_version__ to test
+     * the version.
+     */
+    #define PCAP_IS_AT_LEAST_XL_C_VERSION(major, minor) \
+	(__ibmxl_version__ > (major) || \
+	 (__ibmxl_version__ == (major) && __ibmxl_release__ >= (minor)))
+  #else /* __ibmxl__ */
+    /*
+     * __ibmxl__ not defined; use __xlC__ to test the version.
+     */
+    #define PCAP_IS_AT_LEAST_XL_C_VERSION(major, minor) \
 	(__xlC__ >= (((major) << 8) | (minor)))
+  #endif /* __ibmxl__ */
 #endif
 
 /*
@@ -154,9 +178,11 @@
  */
 
 #if ! defined(__HP_aCC)
-#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) 0
+  /* Not HP C */
+  #define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) 0
 #else
-#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) \
+  /* HP C */
+  #define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) \
 	(__HP_aCC >= ((major)*10000 + (minor)*100))
 #endif
 
diff --git a/pcap/dlt.h b/pcap/dlt.h
index eaba34f..0da6de2 100644
--- a/pcap/dlt.h
+++ b/pcap/dlt.h
@@ -105,6 +105,67 @@
 #endif
 
 /*
+ * NetBSD uses 15 for HIPPI.
+ *
+ * From a quick look at sys/net/if_hippi.h and sys/net/if_hippisubr.c
+ * in an older version of NetBSD , the header appears to be:
+ *
+ *	a 1-byte ULP field (ULP-id)?
+ *
+ *	a 1-byte flags field;
+ *
+ *	a 2-byte "offsets" field;
+ *
+ *	a 4-byte "D2 length" field (D2_Size?);
+ *
+ *	a 4-byte "destination switch" field (or a 1-byte field
+ *	containing the Forwarding Class, Double_Wide, and Message_Type
+ *	sub fields, followed by a 3-byte Destination_Switch_Address
+ *	field?, HIPPI-LE 3.4-style?);
+ *
+ *	a 4-byte "source switch" field (or a 1-byte field containing the
+ *	Destination_Address_type and Source_Address_Type fields, followed
+ *	by a 3-byte Source_Switch_Address field, HIPPI-LE 3.4-style?);
+ *
+ *	a 2-byte reserved field;
+ *
+ *	a 6-byte destination address field;
+ *
+ *	a 2-byte "local admin" field;
+ *
+ *	a 6-byte source address field;
+ *
+ * followed by an 802.2 LLC header.
+ *
+ * This looks somewhat like something derived from the HIPPI-FP 4.4
+ * Header_Area, followed an HIPPI-FP 4.4 D1_Area containing a D1 data set
+ * with the header in HIPPI-LE 3.4 (ANSI X3.218-1993), followed by an
+ * HIPPI-FP 4.4 D2_Area (with no Offset) containing the 802.2 LLC header
+ * and payload?  Or does the "offsets" field contain the D2_Offset,
+ * with that many bytes of offset before the payload?
+ *
+ * See http://wotug.org/parallel/standards/hippi/ for an archive of
+ * HIPPI specifications.
+ *
+ * RFC 2067 imposes some additional restrictions.  It says that the
+ * Offset is always zero
+ *
+ * HIPPI is long-gone, and the source files found in an older version
+ * of NetBSD don't appear to be in the main CVS branch, so we may never
+ * see a capture with this link-layer type.
+ */
+#if defined(__NetBSD__)
+#define DLT_HIPPI	15	/* HIPPI */
+#endif
+
+/*
+ * NetBSD uses 16 for DLT_HDLC; see below.
+ * BSD/OS uses it for PPP; see above.
+ * As far as I know, no other OS uses it for anything; don't use it
+ * for anything else.
+ */
+
+/*
  * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
  *
  * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
@@ -219,7 +280,8 @@
  * that the AF_ type in the link-layer header is in network byte order.
  *
  * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
- * we don't use 12 for it in OSes other than OpenBSD.
+ * we don't use 12 for it in OSes other than OpenBSD; instead, we
+ * use the same value as LINKTYPE_LOOP.
  */
 #ifdef __OpenBSD__
 #define DLT_LOOP	12
@@ -230,7 +292,7 @@
 /*
  * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
  * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
- * than OpenBSD.
+ * than OpenBSD; instead, we use the same value as LINKTYPE_ENC.
  */
 #ifdef __OpenBSD__
 #define DLT_ENC		13
@@ -239,13 +301,23 @@
 #endif
 
 /*
- * Values between 110 and 112 are reserved for use in capture file headers
+ * Values 110 and 111 are reserved for use in capture file headers
  * as link-layer types corresponding to DLT_ types that might differ
  * between platforms; don't use those values for new DLT_ types
  * other than the corresponding DLT_ types.
  */
 
 /*
+ * NetBSD uses 16 for (Cisco) "HDLC framing".  For other platforms,
+ * we define it to have the same value as LINKTYPE_NETBSD_HDLC.
+ */
+#if defined(__NetBSD__)
+#define DLT_HDLC	16	/* Cisco HDLC */
+#else
+#define DLT_HDLC	112
+#endif
+
+/*
  * Linux cooked sockets.
  */
 #define DLT_LINUX_SLL	113
@@ -651,7 +723,7 @@
  * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
  * Every frame contains a 32bit A429 label.
  * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ * https://web.archive.org/web/20040616233302/https://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
  */
 #define DLT_A429                184
 
@@ -1214,15 +1286,17 @@
 #define DLT_BLUETOOTH_LE_LL	251
 
 /*
- * DLT type for upper-protocol layer PDU saves from wireshark.
+ * DLT type for upper-protocol layer PDU saves from Wireshark.
  *
- * the actual contents are determined by two TAGs stored with each
- * packet:
- *   EXP_PDU_TAG_LINKTYPE          the link type (LINKTYPE_ value) of the
- *				   original packet.
+ * the actual contents are determined by two TAGs, one or more of
+ * which is stored with each packet:
  *
- *   EXP_PDU_TAG_PROTO_NAME        the name of the wireshark dissector
- * 				   that can make sense of the data stored.
+ *   EXP_PDU_TAG_DISSECTOR_NAME      the name of the Wireshark dissector
+ *				     that can make sense of the data stored.
+ *
+ *   EXP_PDU_TAG_HEUR_DISSECTOR_NAME the name of the Wireshark heuristic
+ *				     dissector that can make sense of the
+ *				     data stored.
  */
 #define DLT_WIRESHARK_UPPER_PDU	252
 
diff --git a/pcap/funcattrs.h b/pcap/funcattrs.h
index a2ca542..3740949 100644
--- a/pcap/funcattrs.h
+++ b/pcap/funcattrs.h
@@ -118,14 +118,14 @@
     #if PCAP_IS_AT_LEAST_GNUC_VERSION(3,4) \
         || PCAP_IS_AT_LEAST_XL_C_VERSION(12,0)
       /*
-       * GCC 3.4 or later, or some compiler asserting compatibility with
-       * GCC 3.4 or later, or XL C 13.0 or later, so we have
+       * GCC 3.4 and later, or some compiler asserting compatibility with
+       * GCC 3.4 and later, or XL C 13.0 and later, so we have
        * __attribute__((visibility()).
        */
       #define PCAP_API_DEF	__attribute__((visibility("default")))
     #elif PCAP_IS_AT_LEAST_SUNC_VERSION(5,5)
       /*
-       * Sun C 5.5 or later, so we have __global.
+       * Sun C 5.5 and later, so we have __global.
        * (Sun C 5.9 and later also have __attribute__((visibility()),
        * but there's no reason to prefer it with Sun C.)
        */
@@ -161,6 +161,15 @@
  * provided by Apple, so each release can come with a version compiled
  * to use the APIs present in that release.)
  *
+ * The non-macOS versioning is based on
+ *
+ *    https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
+ *
+ * If there are any corrections, please submit it upstream to the
+ * libpcap maintainers, preferably as a pull request on
+ *
+ *    https://github.com/the-tcpdump-group/libpcap
+ *
  * 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.
@@ -172,25 +181,32 @@
  * 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)
+#include <Availability.h>
+/*
+ * When building as part of macOS, define this as __API_AVAILABLE(__VA_ARGS__).
+ *
+ * XXX - if there's some #define to indicate that this is being built
+ * as part of the macOS build process, we could make that Just Work.
+ */
+#define PCAP_AVAILABLE(...)
+#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), ios(1.0))
+#define PCAP_AVAILABLE_1_0	PCAP_AVAILABLE(macos(10.6), ios(4.0))
 /* #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_2	PCAP_AVAILABLE(macos(10.9), ios(6.0))
 /* #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_5	PCAP_AVAILABLE(macos(10.10), ios(7.0), watchos(1.0))
 /* #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_7	PCAP_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+#define PCAP_AVAILABLE_1_8	PCAP_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0)) /* only Windows adds routines to the API; XXX - what version first had it? */
+#define PCAP_AVAILABLE_1_9	PCAP_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
 #define PCAP_AVAILABLE_1_10	/* not in macOS yet */
-#define PCAP_AVAILABLE_1_11	/* not released yet, so not in macOS yet */ 
+#define PCAP_AVAILABLE_1_11	/* not released yet, so not in macOS yet */
 #else /* __APPLE__ */
 #define PCAP_AVAILABLE_0_4
 #define PCAP_AVAILABLE_0_5
@@ -230,11 +246,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 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.
+   * Compiler with support for __attribute((noreturn)), or GCC 2.5 and
+   * later, or some compiler asserting compatibility with GCC 2.5 and
+   * later, or Solaris Studio 12 (Sun C 5.9) and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?), or HP aCC
+   * A.06.10 and later.
    */
   #define PCAP_NORETURN __attribute((noreturn))
   #define PCAP_NORETURN_DEF __attribute((noreturn))
@@ -260,8 +276,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 or later, or some compiler
-   * asserting compatibility with GCC 2.3 or later, or IBM XL C 10.1
+   * Compiler with support for it, or GCC 2.3 and later, or some compiler
+   * asserting compatibility with GCC 2.3 and later, or IBM XL C 10.1
    * and later (do any earlier versions of XL C support this?),
    * or HP aCC A.06.10 and later.
    */
@@ -274,23 +290,21 @@
  * PCAP_DEPRECATED(func, msg), after a function declaration, marks the
  * function as deprecated.
  *
- * The first argument is the name of the function; the second argument is
- * a string giving the warning message to use if the compiler supports that.
- *
- * (Thank you, Microsoft, for requiring the function name.)
+ * The argument is a string giving the warning message to use if the
+ * compiler supports that.
  */
 #if __has_attribute(deprecated) \
     || PCAP_IS_AT_LEAST_GNUC_VERSION(4,5) \
     || PCAP_IS_AT_LEAST_SUNC_VERSION(5,13)
   /*
    * Compiler that supports __has_attribute and __attribute__((deprecated)),
-   * or GCC 4.5 or later, or Sun/Oracle C 12.4 (Sun C 5.13) or later.
+   * or GCC 4.5 and later, or Sun/Oracle C 12.4 (Sun C 5.13) and later.
    *
    * Those support __attribute__((deprecated(msg))) (we assume, perhaps
    * incorrectly, that anything that supports __has_attribute() is
    * recent enough to support __attribute__((deprecated(msg)))).
    */
-  #define PCAP_DEPRECATED(func, msg)	__attribute__((deprecated(msg)))
+  #define PCAP_DEPRECATED(msg)	__attribute__((deprecated(msg)))
 #elif PCAP_IS_AT_LEAST_GNUC_VERSION(3,1)
   /*
    * GCC 3.1 through 4.4.
@@ -298,18 +312,18 @@
    * Those support __attribute__((deprecated)) but not
    * __attribute__((deprecated(msg))).
    */
-  #define PCAP_DEPRECATED(func, msg)	__attribute__((deprecated))
+  #define PCAP_DEPRECATED(msg)	__attribute__((deprecated))
 #elif defined(_MSC_VER) && !defined(BUILDING_PCAP)
   /*
    * MSVC, and we're not building libpcap itself; it's VS 2015
-   * or later, so we have the deprecated pragma.
+   * and later, so we have __declspec(deprecated(...)).
    *
    * If we *are* building libpcap, we don't want this, as it'll warn
    * us even if we *define* the function.
    */
-  #define PCAP_DEPRECATED(func, msg)	__pragma(deprecated(func))
+  #define PCAP_DEPRECATED(msg)	_declspec(deprecated(msg))
 #else
-  #define PCAP_DEPRECATED(func, msg)
+  #define PCAP_DEPRECATED(msg)
 #endif
 
 /*
diff --git a/pcap/namedb.h b/pcap/namedb.h
index 34a0ae7..51d1e31 100644
--- a/pcap/namedb.h
+++ b/pcap/namedb.h
@@ -59,8 +59,9 @@
 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_DEPRECATED(pcap_nametoaddr, "this is not reentrant; use 'pcap_nametoaddrinfo' instead");
+PCAP_API
+PCAP_DEPRECATED("this is not reentrant; use 'pcap_nametoaddrinfo' instead")
+bpf_u_int32 **pcap_nametoaddr(const char *);
 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 1cfa0bf..8c7b4f6 100644
--- a/pcap/pcap-inttypes.h
+++ b/pcap/pcap-inttypes.h
@@ -32,8 +32,8 @@
 #define pcap_pcap_inttypes_h
 
 /*
- * If we're compiling with Visual Studio, make sure we have at least
- * VS 2015 or later, so we have sufficient C99 support.
+ * If we're compiling with Visual Studio, make sure the C99 integer
+ * types are defined, by hook or by crook.
  *
  * XXX - verify that we have at least C99 support on UN*Xes?
  *
@@ -42,39 +42,60 @@
  */
 #if defined(_MSC_VER)
   /*
-   * Compiler is MSVC.  Make sure we have VS 2015 or later.
+   * Compiler is MSVC.
    */
-  #if _MSC_VER < 1900
-    #error "Building libpcap requires 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.
+     * We don't support building libpcap with earlier versions of VS,
+     * but SDKs for Npcap have to support building applications using
+     * earlier versions of VS, so we work around this by defining
+     * those types ourselves, as some files use them.
+     */
+    typedef unsigned char uint8_t;
+    typedef signed char int8_t;
+    typedef unsigned short uint16_t;
+    typedef signed short int16_t;
+    typedef unsigned int uint32_t;
+    typedef signed int int32_t;
+    #ifdef _MSC_EXTENSIONS
+      typedef unsigned _int64 uint64_t;
+      typedef _int64 int64_t;
+    #else /* _MSC_EXTENSIONS */
+      typedef unsigned long long uint64_t;
+      typedef long long int64_t;
+    #endif
   #endif
-#endif
+#else /* defined(_MSC_VER) */
+  /*
+   * Not Visual Studio.
+   * Include <inttypes.h> to get the integer types and PRi[doux]64 values
+   * defined.
+   *
+   * 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.
+   */
 
-/*
- * 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?
+   */
 
-/*
- * XXX - somehow make sure we have enough C99 support with other
- * compilers and support libraries?
- */
-
-#include <inttypes.h>
+  #include <inttypes.h>
+#endif /* defined(_MSC_VER) */
 
 #endif /* pcap/pcap-inttypes.h */
diff --git a/pcap/pcap.h b/pcap/pcap.h
index 8182bef..6894b3c 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -71,7 +71,7 @@
 
 /*
  * 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.
+ * including 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*
@@ -391,8 +391,8 @@
  * 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_DEPRECATED("use 'pcap_findalldevs' and use the first device")
+PCAP_API char	*pcap_lookupdev(char *);
 
 PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
@@ -571,7 +571,7 @@
 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_API int	pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
 
 PCAP_AVAILABLE_0_8
 PCAP_API void	pcap_breakloop(pcap_t *);
@@ -583,7 +583,7 @@
 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_API int	pcap_setdirection(pcap_t *, pcap_direction_t);
 
 PCAP_AVAILABLE_0_7
 PCAP_API int	pcap_getnonblock(pcap_t *, char *);
@@ -614,6 +614,7 @@
 	    bpf_u_int32);
 
 PCAP_AVAILABLE_0_5
+PCAP_DEPRECATED("use pcap_open_dead(), pcap_compile() and pcap_close()")
 PCAP_API int	pcap_compile_nopcap(int, int, struct bpf_program *,
 	    const char *, int, bpf_u_int32);
 
@@ -680,8 +681,8 @@
  * 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'");
+PCAP_DEPRECATED("request a 'pcap_handle' that returns a HANDLE if you need it")
+PCAP_API int	pcap_fileno(pcap_t *);
 #else /* _WIN32 */
 PCAP_AVAILABLE_0_4
 PCAP_API int	pcap_fileno(pcap_t *);
@@ -878,7 +879,7 @@
 /*
  * The formats allowed by pcap_open() are the following:
  * - file://path_and_filename [opens a local file]
- * - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
+ * - rpcap://devicename [opens the selected device 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 compatibility, but it is strongly discouraged]
@@ -1013,10 +1014,11 @@
  * authentication is successful (and the user has the right to open network
  * devices) the RPCAP connection will continue; otherwise it will be dropped.
  *
- * *******NOTE********: the username and password are sent over the network
- * to the capture server *IN CLEAR TEXT*.  Don't use this on a network
- * that you don't completely control!  (And be *really* careful in your
- * definition of "completely"!)
+ * *******NOTE********: unless TLS is being used, the username and password
+ * are sent over the network to the capture server *IN CLEAR TEXT*.  Don't
+ * use this, without TLS (i.e., with rpcap:// rather than rpcaps://) on
+ * a network that you don't completely control!  (And be *really* careful
+ * in your definition of "completely"!)
  */
 #define RPCAP_RMTAUTH_PWD 1
 
diff --git a/pflog.h b/pflog.h
new file mode 100644
index 0000000..b49d04f
--- /dev/null
+++ b/pflog.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * pflog headers, at least as they exist now.
+ */
+#define PFLOG_IFNAMSIZ		16
+#define PFLOG_RULESET_NAME_SIZE	16
+
+/*
+ * Direction values.
+ */
+#define PF_INOUT	0
+#define PF_IN		1
+#define PF_OUT		2
+#if defined(__OpenBSD__)
+#define PF_FWD		3
+#endif
+
+/*
+ * Reason values.
+ */
+#define PFRES_MATCH	0
+#define PFRES_BADOFF	1
+#define PFRES_FRAG	2
+#define PFRES_SHORT	3
+#define PFRES_NORM	4
+#define PFRES_MEMORY	5
+#define PFRES_TS	6
+#define PFRES_CONGEST	7
+#define PFRES_IPOPTIONS 8
+#define PFRES_PROTCKSUM 9
+#define PFRES_BADSTATE	10
+#define PFRES_STATEINS	11
+#define PFRES_MAXSTATES	12
+#define PFRES_SRCLIMIT	13
+#define PFRES_SYNPROXY	14
+#if defined(__FreeBSD__)
+#define PFRES_MAPFAILED	15
+#elif defined(__NetBSD__)
+#define PFRES_STATELOCKED 15
+#elif defined(__OpenBSD__)
+#define PFRES_TRANSLATE	15
+#define PFRES_NOROUTE	16
+#elif defined(__APPLE__)
+#define PFRES_DUMMYNET  15
+#endif
+
+/*
+ * Action values.
+ */
+#define PF_PASS			0
+#define PF_DROP			1
+#define PF_SCRUB		2
+#define PF_NOSCRUB		3
+#define PF_NAT			4
+#define PF_NONAT		5
+#define PF_BINAT		6
+#define PF_NOBINAT		7
+#define PF_RDR			8
+#define PF_NORDR		9
+#define PF_SYNPROXY_DROP	10
+#if defined(__FreeBSD__)
+#define PF_DEFER		11
+#elif defined(__OpenBSD__)
+#define PF_DEFER		11
+#define PF_MATCH		12
+#define PF_DIVERT		13
+#define PF_RT			14
+#define PF_AFRT			15
+#elif defined(__APPLE__)
+#define PF_DUMMYNET		11
+#define PF_NODUMMYNET		12
+#define PF_NAT64		13
+#define PF_NONAT64		14
+#endif
+
+struct pf_addr {
+	union {
+		struct in_addr		v4;
+		struct in6_addr		v6;
+		uint8_t			addr8[16];
+		uint16_t		addr16[8];
+		uint32_t		addr32[4];
+	} pfa;		    /* 128-bit address */
+#define v4	pfa.v4
+#define v6	pfa.v6
+#define addr8	pfa.addr8
+#define addr16	pfa.addr16
+#define addr32	pfa.addr32
+};
+
+struct pfloghdr {
+	uint8_t		length;
+	uint8_t		af;
+	uint8_t		action;
+	uint8_t		reason;
+	char		ifname[PFLOG_IFNAMSIZ];
+	char		ruleset[PFLOG_RULESET_NAME_SIZE];
+	uint32_t	rulenr;
+	uint32_t	subrulenr;
+	uint32_t	uid;
+	int32_t		pid;
+	uint32_t	rule_uid;
+	int32_t		rule_pid;
+	uint8_t		dir;
+#if defined(__OpenBSD__)
+	uint8_t		rewritten;
+	uint8_t		naf;
+	uint8_t		pad[1];
+#else
+	uint8_t		pad[3];
+#endif
+#if defined(__FreeBSD__)
+	uint32_t	ridentifier;
+	uint8_t		reserve;
+	uint8_t		pad2[3];
+#elif defined(__OpenBSD__)
+	struct pf_addr	saddr;
+	struct pf_addr	daddr;
+	uint16_t	sport;
+	uint16_t	dport;
+#endif
+};
+
+
+
diff --git a/savefile.c b/savefile.c
index d04b917..db8a3aa 100644
--- a/savefile.c
+++ b/savefile.c
@@ -112,6 +112,16 @@
 }
 
 static int
+sf_cant_set_rfmon(pcap_t *p _U_)
+{
+	/*
+	 * This is a savefile, not a device on which you can capture,
+	 * so never say it supports being put into monitor mode.
+	 */
+	return (0);
+}
+
+static int
 sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
 {
 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
@@ -350,7 +360,7 @@
 	if (fname[0] == '-' && fname[1] == '\0')
 	{
 		fp = stdin;
-		if (stdin == NULL) {
+		if (fp == NULL) {
 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "The standard input is not open");
 			return (NULL);
@@ -551,6 +561,7 @@
 	p->selectable_fd = fileno(fp);
 #endif
 
+	p->can_set_rfmon_op = sf_cant_set_rfmon;
 	p->read_op = pcap_offline_read;
 	p->inject_op = sf_inject;
 	p->setfilter_op = install_bpf_program;
@@ -618,12 +629,27 @@
 pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
 	struct bpf_insn *fcode;
-	int status = 0;
 	int n = 0;
 	u_char *data;
 
-	while (status == 0) {
+	/*
+	 * This can conceivably process more than INT_MAX packets,
+	 * which would overflow the packet count, causing it either
+	 * to look like a negative number, and thus cause us to
+	 * return a value that looks like an error, or overflow
+	 * back into positive territory, and thus cause us to
+	 * return a too-low count.
+	 *
+	 * Therefore, if the packet count is unlimited, we clip
+	 * it at INT_MAX; this routine is not expected to
+	 * process packets indefinitely, so that's not an issue.
+	 */
+	if (PACKET_COUNT_IS_UNLIMITED(cnt))
+		cnt = INT_MAX;
+
+	for (;;) {
 		struct pcap_pkthdr h;
+		int status;
 
 		/*
 		 * Has "pcap_breakloop()" been called?
@@ -643,16 +669,28 @@
 		}
 
 		status = p->next_packet_op(p, &h, &data);
-		if (status) {
-			if (status == 1)
-				return (0);
+		if (status < 0) {
+			/*
+			 * Error.  Pass it back to the caller.
+			 */
 			return (status);
 		}
+		if (status == 0) {
+			/*
+			 * EOF.  Nothing more to process;
+			 */
+			break;
+		}
 
+		/*
+		 * OK, we've read a packet; run it through the filter
+		 * and, if it passes, process it.
+		 */
 		if ((fcode = p->fcode.bf_insns) == NULL ||
 		    pcap_filter(fcode, data, h.len, h.caplen)) {
 			(*callback)(user, &h, data);
-			if (++n >= cnt && cnt > 0)
+			n++;	/* count the packet */
+			if (n >= cnt)
 				break;
 		}
 	}
diff --git a/scanner.c b/scanner.c
index 4c12a2d..bbb2b46 100644
--- a/scanner.c
+++ b/scanner.c
@@ -24,9 +24,16 @@
  */
 #include <pcap/pcap-inttypes.h>
 
+/*
+ * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
+ * (see ftmacros.h), so include it early.
+ */
+#include "gencode.h"
+#include "grammar.h"
+
 #include "diag-control.h"
 
-#line 30 "scanner.c"
+#line 37 "scanner.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -3092,7 +3099,7 @@
  * We want to generate code that can be used by a reentrant parser
  * generated by Bison or Berkeley YACC.
  */
-#line 67 "scanner.l"
+#line 74 "scanner.l"
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  *	The Regents of the University of California.  All rights reserved.
@@ -3118,10 +3125,6 @@
 
 #include "pcap-int.h"
 
-#include "gencode.h"
-
-#include "grammar.h"
-
 /*
  * Earlier versions of Flex don't declare these, so we declare them
  * ourselves to squelch warnings.
@@ -3182,8 +3185,8 @@
  */
 DIAG_OFF_FLEX
 
-#line 3186 "scanner.c"
-#line 3187 "scanner.c"
+#line 3189 "scanner.c"
+#line 3190 "scanner.c"
 
 #define INITIAL 0
 
@@ -3453,9 +3456,9 @@
 		}
 
 	{
-#line 252 "scanner.l"
+#line 255 "scanner.l"
 
-#line 3459 "scanner.c"
+#line 3462 "scanner.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -3510,634 +3513,634 @@
 
 case 1:
 YY_RULE_SETUP
-#line 253 "scanner.l"
+#line 256 "scanner.l"
 return DST;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 254 "scanner.l"
+#line 257 "scanner.l"
 return SRC;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 256 "scanner.l"
+#line 259 "scanner.l"
 return LINK;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 257 "scanner.l"
+#line 260 "scanner.l"
 return LINK;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 258 "scanner.l"
+#line 261 "scanner.l"
 return ARP;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 259 "scanner.l"
+#line 262 "scanner.l"
 return RARP;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 260 "scanner.l"
+#line 263 "scanner.l"
 return IP;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 261 "scanner.l"
+#line 264 "scanner.l"
 return SCTP;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 262 "scanner.l"
+#line 265 "scanner.l"
 return TCP;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 263 "scanner.l"
+#line 266 "scanner.l"
 return UDP;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 264 "scanner.l"
+#line 267 "scanner.l"
 return ICMP;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 265 "scanner.l"
+#line 268 "scanner.l"
 return IGMP;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 266 "scanner.l"
+#line 269 "scanner.l"
 return IGRP;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 267 "scanner.l"
+#line 270 "scanner.l"
 return PIM;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 268 "scanner.l"
+#line 271 "scanner.l"
 return VRRP;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 269 "scanner.l"
+#line 272 "scanner.l"
 return CARP;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 270 "scanner.l"
+#line 273 "scanner.l"
 return RADIO;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 272 "scanner.l"
+#line 275 "scanner.l"
 return IPV6;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 273 "scanner.l"
+#line 276 "scanner.l"
 return ICMPV6;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 274 "scanner.l"
+#line 277 "scanner.l"
 return AH;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 275 "scanner.l"
+#line 278 "scanner.l"
 return ESP;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 277 "scanner.l"
+#line 280 "scanner.l"
 return ATALK;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 278 "scanner.l"
+#line 281 "scanner.l"
 return AARP;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 279 "scanner.l"
+#line 282 "scanner.l"
 return DECNET;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 280 "scanner.l"
+#line 283 "scanner.l"
 return LAT;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 281 "scanner.l"
+#line 284 "scanner.l"
 return SCA;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 282 "scanner.l"
+#line 285 "scanner.l"
 return MOPRC;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 283 "scanner.l"
+#line 286 "scanner.l"
 return MOPDL;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 285 "scanner.l"
+#line 288 "scanner.l"
 return ISO;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 286 "scanner.l"
+#line 289 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 287 "scanner.l"
+#line 290 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 288 "scanner.l"
+#line 291 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 289 "scanner.l"
+#line 292 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 290 "scanner.l"
+#line 293 "scanner.l"
 return L1;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 291 "scanner.l"
+#line 294 "scanner.l"
 return L2;
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 292 "scanner.l"
+#line 295 "scanner.l"
 return IIH;
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 293 "scanner.l"
+#line 296 "scanner.l"
 return LSP;
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 294 "scanner.l"
+#line 297 "scanner.l"
 return SNP;
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 295 "scanner.l"
+#line 298 "scanner.l"
 return CSNP;
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 296 "scanner.l"
+#line 299 "scanner.l"
 return PSNP;
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 298 "scanner.l"
+#line 301 "scanner.l"
 return CLNP;
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 300 "scanner.l"
+#line 303 "scanner.l"
 return STP;
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 302 "scanner.l"
+#line 305 "scanner.l"
 return IPX;
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 304 "scanner.l"
+#line 307 "scanner.l"
 return NETBEUI;
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 306 "scanner.l"
+#line 309 "scanner.l"
 return HOST;
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 307 "scanner.l"
+#line 310 "scanner.l"
 return NET;
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 308 "scanner.l"
+#line 311 "scanner.l"
 return NETMASK;
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 309 "scanner.l"
+#line 312 "scanner.l"
 return PORT;
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 310 "scanner.l"
+#line 313 "scanner.l"
 return PORTRANGE;
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 311 "scanner.l"
+#line 314 "scanner.l"
 return PROTO;
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 312 "scanner.l"
+#line 315 "scanner.l"
 return PROTOCHAIN;
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 314 "scanner.l"
+#line 317 "scanner.l"
 return GATEWAY;
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 316 "scanner.l"
+#line 319 "scanner.l"
 return TYPE;
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 317 "scanner.l"
+#line 320 "scanner.l"
 return SUBTYPE;
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 318 "scanner.l"
+#line 321 "scanner.l"
 return DIR;
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 319 "scanner.l"
+#line 322 "scanner.l"
 return ADDR1;
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 320 "scanner.l"
+#line 323 "scanner.l"
 return ADDR2;
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 321 "scanner.l"
+#line 324 "scanner.l"
 return ADDR3;
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 322 "scanner.l"
+#line 325 "scanner.l"
 return ADDR4;
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 323 "scanner.l"
+#line 326 "scanner.l"
 return RA;
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 324 "scanner.l"
+#line 327 "scanner.l"
 return TA;
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 326 "scanner.l"
+#line 329 "scanner.l"
 return LESS;
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 327 "scanner.l"
+#line 330 "scanner.l"
 return GREATER;
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 328 "scanner.l"
+#line 331 "scanner.l"
 return CBYTE;
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 329 "scanner.l"
+#line 332 "scanner.l"
 return TK_BROADCAST;
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 330 "scanner.l"
+#line 333 "scanner.l"
 return TK_MULTICAST;
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 332 "scanner.l"
+#line 335 "scanner.l"
 return AND;
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 333 "scanner.l"
+#line 336 "scanner.l"
 return OR;
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 334 "scanner.l"
+#line 337 "scanner.l"
 return '!';
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 336 "scanner.l"
+#line 339 "scanner.l"
 return LEN;
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 337 "scanner.l"
+#line 340 "scanner.l"
 return INBOUND;
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 338 "scanner.l"
+#line 341 "scanner.l"
 return OUTBOUND;
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 340 "scanner.l"
+#line 343 "scanner.l"
 return IFINDEX;
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 342 "scanner.l"
+#line 345 "scanner.l"
 return VLAN;
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 343 "scanner.l"
+#line 346 "scanner.l"
 return MPLS;
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 344 "scanner.l"
+#line 347 "scanner.l"
 return PPPOED;
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 345 "scanner.l"
+#line 348 "scanner.l"
 return PPPOES;
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 346 "scanner.l"
+#line 349 "scanner.l"
 return GENEVE;
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 348 "scanner.l"
+#line 351 "scanner.l"
 return LANE;
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 349 "scanner.l"
+#line 352 "scanner.l"
 return LLC;
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 350 "scanner.l"
+#line 353 "scanner.l"
 return METAC;
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 351 "scanner.l"
+#line 354 "scanner.l"
 return BCC;
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 352 "scanner.l"
+#line 355 "scanner.l"
 return OAM;
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 353 "scanner.l"
+#line 356 "scanner.l"
 return OAMF4;
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 354 "scanner.l"
+#line 357 "scanner.l"
 return OAMF4EC;
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 355 "scanner.l"
+#line 358 "scanner.l"
 return OAMF4SC;
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 356 "scanner.l"
+#line 359 "scanner.l"
 return SC;
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 357 "scanner.l"
+#line 360 "scanner.l"
 return ILMIC;
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 358 "scanner.l"
+#line 361 "scanner.l"
 return VPI;
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 359 "scanner.l"
+#line 362 "scanner.l"
 return VCI;
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 360 "scanner.l"
+#line 363 "scanner.l"
 return CONNECTMSG;
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 361 "scanner.l"
+#line 364 "scanner.l"
 return METACONNECT;
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 363 "scanner.l"
+#line 366 "scanner.l"
 return PF_IFNAME;
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 364 "scanner.l"
+#line 367 "scanner.l"
 return PF_RSET;
 	YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 365 "scanner.l"
+#line 368 "scanner.l"
 return PF_RNR;
 	YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 366 "scanner.l"
+#line 369 "scanner.l"
 return PF_SRNR;
 	YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 367 "scanner.l"
+#line 370 "scanner.l"
 return PF_REASON;
 	YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 368 "scanner.l"
+#line 371 "scanner.l"
 return PF_ACTION;
 	YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 370 "scanner.l"
+#line 373 "scanner.l"
 return FISU;
 	YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 371 "scanner.l"
+#line 374 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 372 "scanner.l"
+#line 375 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 373 "scanner.l"
+#line 376 "scanner.l"
 return MSU;
 	YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 374 "scanner.l"
+#line 377 "scanner.l"
 return HFISU;
 	YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 375 "scanner.l"
+#line 378 "scanner.l"
 return HLSSU;
 	YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 376 "scanner.l"
+#line 379 "scanner.l"
 return HMSU;
 	YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 377 "scanner.l"
+#line 380 "scanner.l"
 return SIO;
 	YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 378 "scanner.l"
+#line 381 "scanner.l"
 return OPC;
 	YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 379 "scanner.l"
+#line 382 "scanner.l"
 return DPC;
 	YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 380 "scanner.l"
+#line 383 "scanner.l"
 return SLS;
 	YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 381 "scanner.l"
+#line 384 "scanner.l"
 return HSIO;
 	YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 382 "scanner.l"
+#line 385 "scanner.l"
 return HOPC;
 	YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 383 "scanner.l"
+#line 386 "scanner.l"
 return HDPC;
 	YY_BREAK
 case 113:
 YY_RULE_SETUP
-#line 384 "scanner.l"
+#line 387 "scanner.l"
 return HSLS;
 	YY_BREAK
 case 114:
 /* rule 114 can match eol */
 YY_RULE_SETUP
-#line 386 "scanner.l"
+#line 389 "scanner.l"
 ;
 	YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 387 "scanner.l"
+#line 390 "scanner.l"
 return yytext[0];
 	YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 388 "scanner.l"
+#line 391 "scanner.l"
 return GEQ;
 	YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 389 "scanner.l"
+#line 392 "scanner.l"
 return LEQ;
 	YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 390 "scanner.l"
+#line 393 "scanner.l"
 return NEQ;
 	YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 391 "scanner.l"
+#line 394 "scanner.l"
 return '=';
 	YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 392 "scanner.l"
+#line 395 "scanner.l"
 return LSH;
 	YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 393 "scanner.l"
+#line 396 "scanner.l"
 return RSH;
 	YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 394 "scanner.l"
+#line 397 "scanner.l"
 { yylval->s = sdup(yyextra, yytext); return AID; }
 	YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 395 "scanner.l"
+#line 398 "scanner.l"
 { yylval->s = sdup(yyextra, yytext); return EID; }
 	YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 396 "scanner.l"
+#line 399 "scanner.l"
 { return stou(yytext, yylval, yyextra); }
 	YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 397 "scanner.l"
+#line 400 "scanner.l"
 {
 			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 	YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 399 "scanner.l"
+#line 402 "scanner.l"
 {
 #ifdef INET6
 			  struct addrinfo hints, *res;
@@ -4160,316 +4163,316 @@
 	YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 418 "scanner.l"
+#line 421 "scanner.l"
 { bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; }
 	YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 419 "scanner.l"
+#line 422 "scanner.l"
 { yylval->h = 0; return NUM; }
 	YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 420 "scanner.l"
+#line 423 "scanner.l"
 { yylval->h = 1; return NUM; }
 	YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 421 "scanner.l"
+#line 424 "scanner.l"
 { yylval->h = 0; return NUM; }
 	YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 422 "scanner.l"
+#line 425 "scanner.l"
 { yylval->h = 3; return NUM; }
 	YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 423 "scanner.l"
+#line 426 "scanner.l"
 { yylval->h = 4; return NUM; }
 	YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 424 "scanner.l"
+#line 427 "scanner.l"
 { yylval->h = 5; return NUM; }
 	YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 425 "scanner.l"
+#line 428 "scanner.l"
 { yylval->h = 8; return NUM; }
 	YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 426 "scanner.l"
+#line 429 "scanner.l"
 { yylval->h = 9; return NUM; }
 	YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 427 "scanner.l"
+#line 430 "scanner.l"
 { yylval->h = 10; return NUM; }
 	YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 428 "scanner.l"
+#line 431 "scanner.l"
 { yylval->h = 11; return NUM; }
 	YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 429 "scanner.l"
+#line 432 "scanner.l"
 { yylval->h = 12; return NUM; }
 	YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 430 "scanner.l"
+#line 433 "scanner.l"
 { yylval->h = 13; return NUM; }
 	YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 431 "scanner.l"
+#line 434 "scanner.l"
 { yylval->h = 14; return NUM; }
 	YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 432 "scanner.l"
+#line 435 "scanner.l"
 { yylval->h = 15; return NUM; }
 	YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 433 "scanner.l"
+#line 436 "scanner.l"
 { yylval->h = 16; return NUM; }
 	YY_BREAK
 case 143:
 YY_RULE_SETUP
-#line 434 "scanner.l"
+#line 437 "scanner.l"
 { yylval->h = 17; return NUM; }
 	YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 435 "scanner.l"
+#line 438 "scanner.l"
 { yylval->h = 18; return NUM; }
 	YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 437 "scanner.l"
+#line 440 "scanner.l"
 { yylval->h = 0; return NUM; }
 	YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 438 "scanner.l"
+#line 441 "scanner.l"
 { yylval->h = 1; return NUM; }
 	YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 440 "scanner.l"
+#line 443 "scanner.l"
 { yylval->h = 1; return NUM; }
 	YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 441 "scanner.l"
+#line 444 "scanner.l"
 { yylval->h = 2; return NUM; }
 	YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 442 "scanner.l"
+#line 445 "scanner.l"
 { yylval->h = 3; return NUM; }
 	YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 443 "scanner.l"
+#line 446 "scanner.l"
 { yylval->h = 4; return NUM; }
 	YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 444 "scanner.l"
+#line 447 "scanner.l"
 { yylval->h = 128; return NUM; }
 	YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 445 "scanner.l"
+#line 448 "scanner.l"
 { yylval->h = 129; return NUM; }
 	YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 446 "scanner.l"
+#line 449 "scanner.l"
 { yylval->h = 130; return NUM; }
 	YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 447 "scanner.l"
+#line 450 "scanner.l"
 { yylval->h = 131; return NUM; }
 	YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 448 "scanner.l"
+#line 451 "scanner.l"
 { yylval->h = 132; return NUM; }
 	YY_BREAK
 case 156:
 YY_RULE_SETUP
-#line 449 "scanner.l"
+#line 452 "scanner.l"
 { yylval->h = 133; return NUM; }
 	YY_BREAK
 case 157:
 YY_RULE_SETUP
-#line 450 "scanner.l"
+#line 453 "scanner.l"
 { yylval->h = 134; return NUM; }
 	YY_BREAK
 case 158:
 YY_RULE_SETUP
-#line 451 "scanner.l"
+#line 454 "scanner.l"
 { yylval->h = 135; return NUM; }
 	YY_BREAK
 case 159:
 YY_RULE_SETUP
-#line 452 "scanner.l"
+#line 455 "scanner.l"
 { yylval->h = 136; return NUM; }
 	YY_BREAK
 case 160:
 YY_RULE_SETUP
-#line 453 "scanner.l"
+#line 456 "scanner.l"
 { yylval->h = 137; return NUM; }
 	YY_BREAK
 case 161:
 YY_RULE_SETUP
-#line 454 "scanner.l"
+#line 457 "scanner.l"
 { yylval->h = 138; return NUM; }
 	YY_BREAK
 case 162:
 YY_RULE_SETUP
-#line 455 "scanner.l"
+#line 458 "scanner.l"
 { yylval->h = 139; return NUM; }
 	YY_BREAK
 case 163:
 YY_RULE_SETUP
-#line 456 "scanner.l"
+#line 459 "scanner.l"
 { yylval->h = 140; return NUM; }
 	YY_BREAK
 case 164:
 YY_RULE_SETUP
-#line 457 "scanner.l"
+#line 460 "scanner.l"
 { yylval->h = 141; return NUM; }
 	YY_BREAK
 case 165:
 YY_RULE_SETUP
-#line 458 "scanner.l"
+#line 461 "scanner.l"
 { yylval->h = 142; return NUM; }
 	YY_BREAK
 case 166:
 YY_RULE_SETUP
-#line 459 "scanner.l"
+#line 462 "scanner.l"
 { yylval->h = 143; return NUM; }
 	YY_BREAK
 case 167:
 YY_RULE_SETUP
-#line 460 "scanner.l"
+#line 463 "scanner.l"
 { yylval->h = 144; return NUM; }
 	YY_BREAK
 case 168:
 YY_RULE_SETUP
-#line 461 "scanner.l"
+#line 464 "scanner.l"
 { yylval->h = 145; return NUM; }
 	YY_BREAK
 case 169:
 YY_RULE_SETUP
-#line 462 "scanner.l"
+#line 465 "scanner.l"
 { yylval->h = 146; return NUM; }
 	YY_BREAK
 case 170:
 YY_RULE_SETUP
-#line 463 "scanner.l"
+#line 466 "scanner.l"
 { yylval->h = 147; return NUM; }
 	YY_BREAK
 case 171:
 YY_RULE_SETUP
-#line 464 "scanner.l"
+#line 467 "scanner.l"
 { yylval->h = 148; return NUM; }
 	YY_BREAK
 case 172:
 YY_RULE_SETUP
-#line 465 "scanner.l"
+#line 468 "scanner.l"
 { yylval->h = 149; return NUM; }
 	YY_BREAK
 case 173:
 YY_RULE_SETUP
-#line 466 "scanner.l"
+#line 469 "scanner.l"
 { yylval->h = 151; return NUM; }
 	YY_BREAK
 case 174:
 YY_RULE_SETUP
-#line 467 "scanner.l"
+#line 470 "scanner.l"
 { yylval->h = 152; return NUM; }
 	YY_BREAK
 case 175:
 YY_RULE_SETUP
-#line 468 "scanner.l"
+#line 471 "scanner.l"
 { yylval->h = 153; return NUM; }
 	YY_BREAK
 case 176:
 YY_RULE_SETUP
-#line 470 "scanner.l"
+#line 473 "scanner.l"
 { yylval->h = 13; return NUM; }
 	YY_BREAK
 case 177:
 YY_RULE_SETUP
-#line 471 "scanner.l"
+#line 474 "scanner.l"
 { yylval->h = 0x01; return NUM; }
 	YY_BREAK
 case 178:
 YY_RULE_SETUP
-#line 472 "scanner.l"
+#line 475 "scanner.l"
 { yylval->h = 0x02; return NUM; }
 	YY_BREAK
 case 179:
 YY_RULE_SETUP
-#line 473 "scanner.l"
+#line 476 "scanner.l"
 { yylval->h = 0x04; return NUM; }
 	YY_BREAK
 case 180:
 YY_RULE_SETUP
-#line 474 "scanner.l"
+#line 477 "scanner.l"
 { yylval->h = 0x08; return NUM; }
 	YY_BREAK
 case 181:
 YY_RULE_SETUP
-#line 475 "scanner.l"
+#line 478 "scanner.l"
 { yylval->h = 0x10; return NUM; }
 	YY_BREAK
 case 182:
 YY_RULE_SETUP
-#line 476 "scanner.l"
+#line 479 "scanner.l"
 { yylval->h = 0x20; return NUM; }
 	YY_BREAK
 case 183:
 YY_RULE_SETUP
-#line 477 "scanner.l"
+#line 480 "scanner.l"
 { yylval->h = 0x40; return NUM; }
 	YY_BREAK
 case 184:
 YY_RULE_SETUP
-#line 478 "scanner.l"
+#line 481 "scanner.l"
 { yylval->h = 0x80; return NUM; }
 	YY_BREAK
 case 185:
 YY_RULE_SETUP
-#line 479 "scanner.l"
+#line 482 "scanner.l"
 {
 			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
 	YY_BREAK
 case 186:
 YY_RULE_SETUP
-#line 481 "scanner.l"
+#line 484 "scanner.l"
 { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
 	YY_BREAK
 case 187:
 YY_RULE_SETUP
-#line 482 "scanner.l"
+#line 485 "scanner.l"
 { return LEX_ERROR; }
 	YY_BREAK
 case 188:
 YY_RULE_SETUP
-#line 483 "scanner.l"
+#line 486 "scanner.l"
 ECHO;
 	YY_BREAK
-#line 4473 "scanner.c"
+#line 4476 "scanner.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -5613,7 +5616,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 483 "scanner.l"
+#line 486 "scanner.l"
 
 
 /*
diff --git a/scanner.h b/scanner.h
index fce23fa..9f406ed 100644
--- a/scanner.h
+++ b/scanner.h
@@ -28,9 +28,16 @@
  */
 #include <pcap/pcap-inttypes.h>
 
+/*
+ * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
+ * (see ftmacros.h), so include it early.
+ */
+#include "gencode.h"
+#include "grammar.h"
+
 #include "diag-control.h"
 
-#line 34 "scanner.h"
+#line 41 "scanner.h"
 
 #define  YY_INT_ALIGNED short int
 
@@ -736,9 +743,9 @@
 #undef yyTABLES_NAME
 #endif
 
-#line 483 "scanner.l"
+#line 486 "scanner.l"
 
 
-#line 743 "scanner.h"
+#line 750 "scanner.h"
 #undef pcap_IN_HEADER
 #endif /* pcap_HEADER_H */
diff --git a/scanner.l b/scanner.l
index 06b9acc..85fe395 100644
--- a/scanner.l
+++ b/scanner.l
@@ -24,6 +24,13 @@
  */
 #include <pcap/pcap-inttypes.h>
 
+/*
+ * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
+ * (see ftmacros.h), so include it early.
+ */
+#include "gencode.h"
+#include "grammar.h"
+
 #include "diag-control.h"
 }
 
@@ -89,10 +96,6 @@
 
 #include "pcap-int.h"
 
-#include "gencode.h"
-
-#include "grammar.h"
-
 /*
  * Earlier versions of Flex don't declare these, so we declare them
  * ourselves to squelch warnings.
diff --git a/sf-pcap.c b/sf-pcap.c
index d8443e9..4294933 100644
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -46,6 +46,7 @@
 #include <limits.h> /* for INT_MAX */
 
 #include "pcap-int.h"
+#include "pcap-util.h"
 
 #include "pcap-common.h"
 
@@ -70,6 +71,10 @@
 
 /*
  * Standard libpcap format.
+ *
+ * The same value is used in the rpcap protocol as an indication of
+ * the server byte order, to let the client know whether it needs to
+ * byte-swap some host-byte-order metadata.
  */
 #define TCPDUMP_MAGIC		0xa1b2c3d4
 
@@ -434,7 +439,7 @@
 
 /*
  * Read and return the next packet from the savefile.  Return the header
- * in hdr and a pointer to the contents in data.  Return 0 on success, 1
+ * in hdr and a pointer to the contents in data.  Return 1 on success, 0
  * if there were no more packets, and -1 on an error.
  */
 static int
@@ -467,7 +472,7 @@
 				return (-1);
 			}
 			/* EOF */
-			return (1);
+			return (0);
 		}
 	}
 
@@ -579,7 +584,7 @@
 		 * userland.
 		 *
 		 * However, perhaps some versions of libpcap failed to
-		 * set the snapshot length currectly in the file header
+		 * set the snapshot length correctly in the file header
 		 * or the per-packet header, or perhaps this is a
 		 * corrupted safefile or a savefile built/modified by a
 		 * fuzz tester, so we check anyway.  We grow the buffer
@@ -622,7 +627,7 @@
 				 * the read finished.
 				 */
 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "truncated dump file; tried to read %u captured bytes, only got %zu",
+				    "truncated dump file; tried to read %d captured bytes, only got %zu",
 				    p->snapshot, amt_read);
 			}
 			return (-1);
@@ -706,10 +711,9 @@
 	}
 	*data = p->buffer;
 
-	if (p->swapped)
-		swap_pseudo_headers(p->linktype, hdr, *data);
+	pcap_post_process(p->linktype, p->swapped, hdr, *data);
 
-	return (0);
+	return (1);
 }
 
 static int
@@ -749,6 +753,24 @@
 
 	f = (FILE *)user;
 	/*
+	 * If the output file handle is in an error state, don't write
+	 * anything.
+	 *
+	 * While in principle a file handle can return from an error state
+	 * to a normal state (for example if a disk that is full has space
+	 * freed), we have possibly left a broken file already, and won't
+	 * be able to clean it up. The safest option is to do nothing.
+	 *
+	 * Note that if we could guarantee that fwrite() was atomic we
+	 * might be able to insure that we don't produce a corrupted file,
+	 * but the standard defines fwrite() as a series of fputc() calls,
+	 * so we really have no insurance that things are not fubared.
+	 *
+	 * http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html
+	 */
+	if (ferror(f))
+		return;
+	/*
 	 * Better not try writing pcap files after
 	 * 2038-01-19 03:14:07 UTC; switch to pcapng.
 	 */
@@ -756,9 +778,17 @@
 	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 */
-	(void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f);
-	(void)fwrite(sp, h->caplen, 1, f);
+	/*
+	 * We only write the packet if we can write the header properly.
+	 *
+	 * This doesn't prevent us from having corrupted output, and if we
+	 * for some reason don't get a complete write we don't have any
+	 * way to set ferror() to prevent future writes from being
+	 * attempted, but it is better than nothing.
+	 */
+	if (fwrite(&sf_hdr, sizeof(sf_hdr), 1, f) == 1) {
+		(void)fwrite(sp, h->caplen, 1, f);
+	}
 }
 
 static pcap_dumper_t *
diff --git a/sf-pcapng.c b/sf-pcapng.c
index 3fd366c..058a724 100644
--- a/sf-pcapng.c
+++ b/sf-pcapng.c
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include "pcap-int.h"
+#include "pcap-util.h"
 
 #include "pcap-common.h"
 
@@ -1094,7 +1095,7 @@
 
 /*
  * Read and return the next packet from the savefile.  Return the header
- * in hdr and a pointer to the contents in data.  Return 0 on success, 1
+ * in hdr and a pointer to the contents in data.  Return 1 on success, 0
  * if there were no more packets, and -1 on an error.
  */
 static int
@@ -1123,7 +1124,7 @@
 		 */
 		status = read_block(fp, p, &cursor, p->errbuf);
 		if (status == 0)
-			return (1);	/* EOF */
+			return (0);	/* EOF */
 		if (status == -1)
 			return (-1);	/* error */
 		switch (cursor.block_type) {
@@ -1511,8 +1512,7 @@
 	if (*data == NULL)
 		return (-1);
 
-	if (p->swapped)
-		swap_pseudo_headers(p->linktype, hdr, *data);
+	pcap_post_process(p->linktype, p->swapped, hdr, *data);
 
-	return (0);
+	return (1);
 }