Import libpcap-1.8.1. vendor/LIBPCAP
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sat, 17 Mar 2018 15:21:54 +0000 (08:21 -0700)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sat, 17 Mar 2018 15:21:54 +0000 (08:21 -0700)
See CHANGES for the details.

113 files changed:
contrib/libpcap/CHANGES
contrib/libpcap/LICENSE
contrib/libpcap/README
contrib/libpcap/README.DELETED
contrib/libpcap/VERSION
contrib/libpcap/arcnet.h
contrib/libpcap/atmuni31.h
contrib/libpcap/bpf/net/bpf_filter.c
contrib/libpcap/bpf_dump.c
contrib/libpcap/bpf_image.c
contrib/libpcap/etherent.c
contrib/libpcap/ethertype.h
contrib/libpcap/extract.h [new file with mode: 0644]
contrib/libpcap/fad-getad.c
contrib/libpcap/fad-helpers.c [copied from contrib/libpcap/inet.c with 59% similarity]
contrib/libpcap/gencode.c
contrib/libpcap/gencode.h
contrib/libpcap/grammar.y
contrib/libpcap/inet.c
contrib/libpcap/llc.h
contrib/libpcap/nametoaddr.c
contrib/libpcap/nametoaddr.h [copied from contrib/libpcap/pcap-namedb.h with 84% similarity]
contrib/libpcap/nlpid.h
contrib/libpcap/optimize.c
contrib/libpcap/pcap-bpf.c
contrib/libpcap/pcap-bpf.h
contrib/libpcap/pcap-common.c
contrib/libpcap/pcap-common.h
contrib/libpcap/pcap-filter.manmisc.in
contrib/libpcap/pcap-int.h
contrib/libpcap/pcap-linktype.manmisc.in
contrib/libpcap/pcap-namedb.h
contrib/libpcap/pcap-savefile.manfile.in
contrib/libpcap/pcap-tstamp.manmisc.in
contrib/libpcap/pcap.3pcap.in
contrib/libpcap/pcap.c
contrib/libpcap/pcap.h
contrib/libpcap/pcap/bluetooth.h
contrib/libpcap/pcap/bpf.h
contrib/libpcap/pcap/can_socketcan.h [copied from contrib/libpcap/pcap-bpf.h with 87% similarity]
contrib/libpcap/pcap/dlt.h [copied from contrib/libpcap/pcap/bpf.h with 79% similarity]
contrib/libpcap/pcap/export-defs.h [new file with mode: 0644]
contrib/libpcap/pcap/namedb.h
contrib/libpcap/pcap/nflog.h [new file with mode: 0644]
contrib/libpcap/pcap/pcap.h
contrib/libpcap/pcap/sll.h
contrib/libpcap/pcap/usb.h
contrib/libpcap/pcap/vlan.h
contrib/libpcap/pcap_activate.3pcap
contrib/libpcap/pcap_breakloop.3pcap
contrib/libpcap/pcap_can_set_rfmon.3pcap
contrib/libpcap/pcap_close.3pcap
contrib/libpcap/pcap_compile.3pcap.in
contrib/libpcap/pcap_create.3pcap
contrib/libpcap/pcap_datalink.3pcap.in
contrib/libpcap/pcap_datalink_name_to_val.3pcap
contrib/libpcap/pcap_datalink_val_to_name.3pcap
contrib/libpcap/pcap_dump.3pcap
contrib/libpcap/pcap_dump_close.3pcap
contrib/libpcap/pcap_dump_file.3pcap
contrib/libpcap/pcap_dump_flush.3pcap
contrib/libpcap/pcap_dump_ftell.3pcap
contrib/libpcap/pcap_dump_open.3pcap.in
contrib/libpcap/pcap_file.3pcap
contrib/libpcap/pcap_fileno.3pcap
contrib/libpcap/pcap_findalldevs.3pcap
contrib/libpcap/pcap_freecode.3pcap
contrib/libpcap/pcap_get_selectable_fd.3pcap
contrib/libpcap/pcap_get_tstamp_precision.3pcap.in [new file with mode: 0644]
contrib/libpcap/pcap_geterr.3pcap
contrib/libpcap/pcap_inject.3pcap
contrib/libpcap/pcap_is_swapped.3pcap
contrib/libpcap/pcap_lib_version.3pcap
contrib/libpcap/pcap_list_datalinks.3pcap.in
contrib/libpcap/pcap_list_tstamp_types.3pcap.in
contrib/libpcap/pcap_lookupdev.3pcap
contrib/libpcap/pcap_lookupnet.3pcap
contrib/libpcap/pcap_loop.3pcap
contrib/libpcap/pcap_major_version.3pcap
contrib/libpcap/pcap_next_ex.3pcap
contrib/libpcap/pcap_offline_filter.3pcap
contrib/libpcap/pcap_open_dead.3pcap.in
contrib/libpcap/pcap_open_live.3pcap
contrib/libpcap/pcap_open_offline.3pcap.in
contrib/libpcap/pcap_set_buffer_size.3pcap
contrib/libpcap/pcap_set_datalink.3pcap
contrib/libpcap/pcap_set_immediate_mode.3pcap [copied from contrib/libpcap/pcap_set_snaplen.3pcap with 76% similarity]
contrib/libpcap/pcap_set_promisc.3pcap
contrib/libpcap/pcap_set_rfmon.3pcap
contrib/libpcap/pcap_set_snaplen.3pcap
contrib/libpcap/pcap_set_timeout.3pcap
contrib/libpcap/pcap_set_tstamp_precision.3pcap.in [new file with mode: 0644]
contrib/libpcap/pcap_set_tstamp_type.3pcap.in
contrib/libpcap/pcap_setdirection.3pcap
contrib/libpcap/pcap_setfilter.3pcap
contrib/libpcap/pcap_setnonblock.3pcap
contrib/libpcap/pcap_snapshot.3pcap
contrib/libpcap/pcap_stats.3pcap
contrib/libpcap/pcap_statustostr.3pcap
contrib/libpcap/pcap_strerror.3pcap
contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap
contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap
contrib/libpcap/portability.h [new file with mode: 0644]
contrib/libpcap/ppp.h
contrib/libpcap/savefile.c
contrib/libpcap/scanner.l
contrib/libpcap/sf-pcap-ng.c
contrib/libpcap/sf-pcap-ng.h
contrib/libpcap/sf-pcap.c
contrib/libpcap/sf-pcap.h
contrib/libpcap/sockutils.c [new file with mode: 0644]
contrib/libpcap/sockutils.h [new file with mode: 0644]
contrib/libpcap/sunatmpos.h

index 0dcf957..1784096 100644 (file)
@@ -1,9 +1,141 @@
-Monday March 18, 2013 guy@alum.mit.edu
+Tuesday, Oct. 25, 2016 mcr@sandelman.ca
+  Summary for 1.8.1 libpcap release
+    Add a target in Makefile.in for Exuberant Ctags use: 'extags'.
+    Rename configure.in to configure.ac: autoconf 2.59
+    Clean up the name-to-DLT mapping table.
+    Add some newer DLT_ values: IPMI_HPM_2,ZWAVE_R1_R2,ZWAVE_R3,WATTSTOPPER_DLM,ISO_14443,RDS
+    Clarify what the return values are for both success and failure.
+    Many changes to build on windows
+    Check for the "break the loop" condition in the inner loop for TPACKET_V3.
+    Fix handling of packet count in the TPACKET_V3 inner loop: GitHub issue #493.
+    Filter out duplicate looped back CAN frames.
+    Fix the handling of loopback filters for IPv6 packets.
+    Add a link-layer header type for RDS (IEC 62106) groups.
+    Use different intermediate folders for x86 and x64 builds on Windows.
+    On Linux, handle all CAN captures with pcap-linux.c, in cooked mode.
+    Removes the need for the "host-endian" link-layer header type.
+    Compile with '-Wused-but-marked-unused' in devel mode if supported
+    Have separate DLTs for big-endian and host-endian SocketCAN headers.
+    Reflect version.h being renamed to pcap_version.h.
+    Require that version.h be generated: all build procedures we support generate version.h (autoconf, CMake, MSVC)!
+    Properly check for sock_recv() errors.
+    Re-impose some of Winsock's limitations on sock_recv().
+    Replace sprintf() with pcap_snprintf().
+    Fix signature of pcap_stats_ex_remote().
+    Initial cmake support for remote packet capture.
+    Have rpcap_remoteact_getsock() return a SOCKET and supply an "is active" flag.
+    Clean up {DAG, Septel, Myricom SNF}-only builds.
+    Do UTF-16-to-ASCII conversion into the right place.
+    pcap_create_interface() needs the interface name on Linux.
+    Clean up hardware time stamp support: the "any" device does not support any time stamp types.
+    Add support for capturing on FreeBSD usbusN interfaces.
+    Add a LINKTYPE/DLT_ value for FreeBSD USB.
+    Go back to using PCAP_API on Windows.
+    CMake support
+    Add TurboCap support from WinPcap.
+    Recognize 802.1ad nested VLAN tag in vlan filter.
+
+Thursday Sep. 3, 2015 guy@alum.mit.edu
+  Summary for 1.7.5 libpcap release
+       Man page cleanups.
+       Add some allocation failure checks.
+       Fix a number of Linux/ucLinux configure/build issues.
+       Fix some memory leaks.
+       Recognize 802.1ad nested VLAN tag in vlan filter.
+       Fix building Bluetooth Linux Monitor support with BlueZ 5.1+
+
+Saturday Jun. 27, 2015 mcr@sandelman.ca
+  Summary for 1.7.4 libpcap release
+       Include fix for GitHub issue #424 -- out of tree builds.
+
+Friday Apr. 10, 2015 guy@alum.mit.edu
+  Summary for 1.7.3 libpcap release
+       Work around a Linux bonding driver bug.
+
+Thursday Feb. 12, 2015 guy@alum.mit.edu/mcr@sandelman.ca
+  Summary for 1.7.2 libpcap release
+       Support for filtering Geneve encapsulated packets.
+       Generalize encapsulation handling, fixing some bugs.
+       Don't add null addresses to address lists.
+       Add pcap_dump_open_append() to open for appending.
+       Fix the swapping of isochronous descriptors in Linux USB.
+       Attempt to handle TPACKET_V1 with 32-bit userland and 64-bit kernel.
+
+Wednesday Nov. 12, 2014 guy@alum.mit.edu/mcr@sandelman.ca
+  Summary for 1.7.0 libpcap release
+       Fix handling of zones for BPF on Solaris
+       new DLT for ZWAVE
+       clarifications for read timeouts.
+       Use BPF extensions in compiled filters, fixing VLAN filters
+       some fixes to compilation without stdint.h
+       EBUSY can now be returned by SNFv3 code.
+       Fix the range checks in BPF loads
+       Various DAG fixes.
+       Various Linux fixes.
+
+Monday Aug. 12, 2014 guy@alum.mit.edu
+  Summary for 1.6.2 libpcap release
+       Don't crash on filters testing a non-existent link-layer type
+           field.
+       Fix sending in non-blocking mode on Linux with memory-mapped
+           capture.
+       Fix timestamps when reading pcap-ng files on big-endian
+           machines.
+
+Saturday  Jul. 19, 2014 mcr@sandelman.ca
+  Summary for 1.6.1 libpcap release
+       some fixes for the any device
+       changes for how --enable-XXX (--enable-sniffing, --enable-can) works
+
+Wednesday Jul. 2, 2014 mcr@sandelman.ca
+  Summary for 1.6.0 libpcap release
+        Don't support D-Bus sniffing on OS X
+        fixes for byte order issues with NFLOG captures
+        Handle using cooked mode for DLT_NETLINK in activate_new().
+        on platforms where you can not capture on down interfaces, do not list them
+        but: do list interfaces which are down, if you can capture on them!
+
+Wednesday December 18, 2013 guy@alum.mit.edu
+Summary for 1.5.3 libpcap release
+       Don't let packets that don't match the current filter get to the
+           application when TPACKET_V3 is used. (GitHub issue #331)
+       Fix handling of pcap_loop()/pcap_dispatch() with a packet count
+           of 0 on some platforms (including Linux with TPACKET_V3).
+           (GitHub issue #333)
+       Work around TPACKET_V3 deficiency that causes packets to be lost
+           when a timeout of 0 is specified. (GitHub issue #335)
+       Man page formatting fixes.
+
+Wednesday December 4, 2013 guy@alum.mit.edu
+Summary for 1.5.2 libpcap release
+       Fix libpcap to work when compiled with TPACKET_V3 support and
+           running on a kernel without TPACKET_V3 support. (GitHub
+           issue #329)
+
+Wednesday November 20, 2013 guy@alum.mit.edu
+Summary for 1.5.1 libpcap release
+       Report an error, rather than crashing, if an IPv6 address is
+           used for link-layer filtering.  (Wireshark bug 9376)
+
+Wednesday October 30, 2013 guy@alum.mit.edu
+Summary for 1.5.0 libpcap release
+       TPACKET_V3 support added for Linux
+       Point users to the the-tcpdump-group repository on GitHub rather
+           than the mcr repository
+       Checks added for malloc()/realloc()/etc. failures
+       Fixed build on Solaris 11
+       Support filtering filtering E1 SS7 traffic on MTP2 layer Annex A
+       Use "ln -s" to link man pages by default
+        Add support for getting nanosecond-resolution time stamps when
+           capturing and reading capture files
+        Many changes to autoconf to deal better with non-GCC compilers
+        added many new DLT types
+
+Saturday April 6, 2013 guy@alum.mit.edu
 Summary for 1.4.0 libpcap release
        Add netfilter/nfqueue interface.
        If we don't have support for IPv6 address resolution, support,
            in filter expressions, what IPv6 stuff we can.
-       Checks added for malloc()/realloc()/etc. failures.
        Fix pcap-config to include -lpthread if canusb support is
            present
        Try to fix "pcap_parse not defined" problems when --without-flex
@@ -29,6 +161,7 @@ Summary for 1.4.0 libpcap release
            kernels, for VLAN tag valid flag
        Clean up some man pages
        Support libnl3 as well as libnl1 and libnl2 on Linux
+       Fix handling of Bluetooth devices on 3.x Linux kernels
 
 Friday  March 30, 2012.  mcr@sandelman.ca
 Summary for 1.3.0 libpcap release
@@ -208,7 +341,7 @@ Mon.    October 27, 2008.  ken@netfunctional.ca.  Summary for 1.0.0 libpcap rele
        DLT: Add JUNIPER_ST
        802.15.4 support
        Variable length 802.11 header support
-       X2E data type support 
+       X2E data type support
        SITA ACN Interface support - see README.sita
        Support for memory-mapped capture on Linux
        Support for zerocopy BPF on platforms that support it
@@ -220,7 +353,7 @@ Mon.    October 27, 2008.  ken@netfunctional.ca.  Summary for 1.0.0 libpcap rele
         can print better diagnostic information
        Return PCAP_ERROR_PERM_DENIED if we don't have permission to open a device, so
         applications can tell the user they need to go play with permissions
-       On Linux, ignore ENETDOWN so we can continue to capture packets if the 
+       On Linux, ignore ENETDOWN so we can continue to capture packets if the
         interface goes down and comes back up again.
        On Linux, support new tpacket frame headers (2.6.27+)
        On Mac OS X, add scripts for changing permissions on /dev/bpf* and launchd plist
@@ -233,14 +366,14 @@ Mon.    September 10, 2007.  ken@xelerance.com.  Summary for 0.9.8 libpcap relea
         Change build process to put public libpcap headers into pcap subir
         DLT: Add value for IPMI IPMB packets
         DLT: Add value for u10 Networks boards
-        Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted 
+        Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
          libpcap files on an OS other than where the file was generated
 
 Wed.   April 25, 2007.  ken@xelerance.com.  Summary for 0.9.6 libpcap release
 
        Put the public libpcap headers into a pcap subdirectory in both the
         source directory and the target include directory, and have include
-        files at the top-level directory to include those headers, for 
+        files at the top-level directory to include those headers, for
         backwards compatibility.
        Add Bluetooth support
        Add USB capturing support on Linux
@@ -248,30 +381,30 @@ Wed.      April 25, 2007.  ken@xelerance.com.  Summary for 0.9.6 libpcap release
        Add support for new FreeBSD BIOCSDIRECTION ioctl
        Add additional filter operations for 802.11 frame types
        Add support for filtering on MTP2 frame types
-       Propagate some changes from the main branch, so the x.9 branch has 
+       Propagate some changes from the main branch, so the x.9 branch has
         all the DLT_ and LINKTYPE_ values that the main branch does
-       Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info) 
+       Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info)
         encapsulated packets
-       Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done 
+       Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done
         by Linux drivers
        Add LINKTYPE_ value corresponding to DLT_IEEE802_16_MAC_CPS.
        Add DLT for IEEE 802.16 (WiMAX) MAC Common Part Sublayer
        Add DLT for Bluetooth HCI UART transport layer
        When building a shared library, build with "-fPIC" on Linux to support x86_64
-       Link with "$(CC) -shared" rather than "ld -shared" when building a 
+       Link with "$(CC) -shared" rather than "ld -shared" when building a
         ".so" shared library
        Add support for autoconf 2.60
        Fixes to discard unread packets when changing filters
-       Changes to handle name changes in the DAG library resulting from 
+       Changes to handle name changes in the DAG library resulting from
         switching to libtool.
        Add support for new DAG ERF types.
-        Add an explicit "-ldag" when building the shared library, so the DAG 
+        Add an explicit "-ldag" when building the shared library, so the DAG
         library dependency is explicit.
        Mac OSX fixes for dealing with "wlt" devices
        Fixes in add_or_find_if() & pcap_findalldevs() to optimize generating
         device lists
        Fixed a bug in pcap_open_live(). The return value of PacketSetHwFilter
-        was not checked. 
+        was not checked.
 
 Tue.   September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release
 
@@ -283,19 +416,19 @@ Tue.      September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release
        OP_PACKET now matches the beginning of the packet, instead of
         beginning+link-layer
        Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay
-       Fix allocation of buffer for list of link-layer types  
+       Fix allocation of buffer for list of link-layer types
        Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages
        Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_
        Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN).
        Added definition for DLT_A429 and LINKTYPE_A429 as #184.
        Added a new DLT and LINKTYPE value for CAN v2.0B frames.
        Add support for DLT_JUNIPER_VP.
-       Don't double-count received packets on Linux systems that 
-        support the PACKET_STATISTICS getsockopt() argument on 
+       Don't double-count received packets on Linux systems that
+        support the PACKET_STATISTICS getsockopt() argument on
         PF_PACKET sockets.
-       Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link 
+       Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link
         layers in Windows
-       Add support to build libpcap.lib and wpcap.dll under Cygnus and 
+       Add support to build libpcap.lib and wpcap.dll under Cygnus and
         MingW32.
 
 Mon.   September 5, 2005.  ken@xelerance.com. Summary for 0.9.4 libpcap release
index dea5f7d..a10474d 100644 (file)
@@ -1,9 +1,9 @@
 License: BSD
+
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
-  
+
   1. Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright
@@ -13,7 +13,7 @@ are met:
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
-  
+
 THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
index 8cac0af..9f65948 100644 (file)
@@ -1,5 +1,3 @@
-@(#) $Header: /tcpdump/master/libpcap/README,v 1.34 2008-12-14 19:44:14 guy Exp $ (LBL)
-
 LIBPCAP 1.x.y
 
 www.tcpdump.org
@@ -10,18 +8,15 @@ Please send inquiries/comments/reports to:
 Anonymous Git is available via:
        git clone git://bpf.tcpdump.org/libpcap
 
-Version 1.x.y of LIBPCAP can be retrieved with the CVS tag "libpcap_1_{x}rel{y}":
-       cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_{x}rel{y} libpcap
-
 Please submit patches by forking the branch on GitHub at
 
-       http://github.com/mcr/libpcap/tree/master
+       http://github.com/the-tcpdump-group/libpcap/tree/master
 
 and issuing a pull request.
 
 formerly from  Lawrence Berkeley National Laboratory
                Network Research Group <libpcap@ee.lbl.gov>
-               ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4)
+               ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
 
 This directory contains source code for libpcap, a system-independent
 interface for user-level packet capture.  libpcap provides a portable
@@ -81,15 +76,15 @@ information on configuring that option.
 
 Note to Linux distributions and *BSD systems that include libpcap:
 
-There's now a rule to make a shared library, which should work on Linux 
+There's now a rule to make a shared library, which should work on Linux
 and *BSD, among other platforms.
 
-It sets the soname of the library to "libpcap.so.1"; this is what it 
-should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as 
+It sets the soname of the library to "libpcap.so.1"; this is what it
+should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as
 that.
 
-We've been maintaining binary compatibility between libpcap releases for 
-quite a while; there's no reason to tie a binary linked with libpcap to 
+We've been maintaining binary compatibility between libpcap releases for
+quite a while; there's no reason to tie a binary linked with libpcap to
 a particular release of libpcap.
 
 Problems, bugs, questions, desirable enhancements, etc. should be sent
@@ -97,12 +92,12 @@ to the address "tcpdump-workers@lists.tcpdump.org".  Bugs, support
 requests, and feature requests may also be submitted on the GitHub issue
 tracker for libpcap at
 
-       https://github.com/mcr/libpcap/issues
+       https://github.com/the-tcpdump-group/libpcap/issues
 
 Source code contributions, etc. should be sent to the email address
 above or submitted by forking the branch on GitHub at
 
-       http://github.com/mcr/libpcap/tree/master
+       http://github.com/the-tcpdump-group/libpcap/tree/master
 
 and issuing a pull request.
 
index d084061..afa061d 100644 (file)
@@ -1,4 +1,24 @@
+pcap-new.c
+pcap-rpcap.c
+pcap-rpcap.h
+remote-ext.h
+CMakeLists.txt
+GenVersion.bat
+Makefile-devel-adds
+cmake/
+cmakeconfig.h.in
+config/
+configure.ac
 CREDITS
+gen_version_c.sh
+gen_version_header.sh
+pcap-bt-monitor-linux.c
+pcap-bt-monitor-linux.h
+pcap-dbus.c
+pcap-dbus.h
+pcap-tc.c
+pcap-tc.h
+pcap_version.h.in
 ChmodBPF/
 INSTALL.txt
 Makefile.in
index 4f86043..5869098 100644 (file)
@@ -30,8 +30,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#) $Id: arcnet.h,v 1.2 2001-04-24 02:17:52 guy Exp $ (LBL)
- *
  * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
  */
 
index 880cc1a..0f85430 100644 (file)
@@ -28,8 +28,6 @@
  * 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.
- *
- * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.3 2007-10-22 19:28:58 guy Exp $ (LBL)
  */
 
 /* Based on UNI3.1 standard by ATM Forum */
index 0c4fb00..01a1b64 100644 (file)
  *     @(#)bpf.c       7.5 (Berkeley) 7/15/91
  */
 
-#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.46 2008-01-02 04:16:46 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #include <pcap-stdinc.h>
 
-#else /* WIN32 */
+#else /* _WIN32 */
 
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
@@ -78,7 +73,7 @@ static const char rcsid[] _U_ =
 # define       MLEN(m) ((m)->m_len)
 #endif /* defined(__hpux) || SOLARIS */
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <pcap/bpf.h>
 
@@ -104,7 +99,7 @@ static const char rcsid[] _U_ =
 #endif
 
 #ifndef LBL_ALIGN
-#ifndef WIN32
+#ifndef _WIN32
 #include <netinet/in.h>
 #endif
 
@@ -200,23 +195,41 @@ m_xhalf(m, k, err)
 }
 #endif
 
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
+
+enum {
+        BPF_S_ANC_NONE,
+        BPF_S_ANC_VLAN_TAG,
+        BPF_S_ANC_VLAN_TAG_PRESENT,
+};
+
 /*
  * Execute the filter program starting at pc on the packet p
  * wirelen is the length of the original packet
  * buflen is the amount of data present
+ * aux_data is auxiliary data, currently used only when interpreting
+ * filters intended for the Linux kernel in cases where the kernel
+ * rejects the filter; it contains VLAN tag information
  * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
  * in all other cases, p is a pointer to a buffer and buflen is its size.
+ *
+ * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
  */
 u_int
-bpf_filter(pc, p, wirelen, buflen)
+bpf_filter_with_aux_data(pc, p, wirelen, buflen, aux_data)
        register const struct bpf_insn *pc;
        register const u_char *p;
        u_int wirelen;
        register u_int buflen;
+       register const struct bpf_aux_data *aux_data;
 {
        register u_int32 A, X;
-       register int k;
-       int32 mem[BPF_MEMWORDS];
+       register bpf_u_int32 k;
+       u_int32 mem[BPF_MEMWORDS];
 #if defined(KERNEL) || defined(_KERNEL)
        struct mbuf *m, *n;
        int merr, len;
@@ -255,7 +268,7 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_W|BPF_ABS:
                        k = pc->k;
-                       if (k + sizeof(int32) > buflen) {
+                       if (k > buflen || sizeof(int32_t) > buflen - k) {
 #if defined(KERNEL) || defined(_KERNEL)
                                if (m == NULL)
                                        return 0;
@@ -272,7 +285,7 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_H|BPF_ABS:
                        k = pc->k;
-                       if (k + sizeof(short) > buflen) {
+                       if (k > buflen || sizeof(int16_t) > buflen - k) {
 #if defined(KERNEL) || defined(_KERNEL)
                                if (m == NULL)
                                        return 0;
@@ -288,22 +301,50 @@ bpf_filter(pc, p, wirelen, buflen)
                        continue;
 
                case BPF_LD|BPF_B|BPF_ABS:
-                       k = pc->k;
-                       if (k >= buflen) {
+                       {
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+                               int code = BPF_S_ANC_NONE;
+#define ANCILLARY(CODE) case SKF_AD_OFF + SKF_AD_##CODE:               \
+                               code = BPF_S_ANC_##CODE;                \
+                                        if (!aux_data)                  \
+                                                return 0;               \
+                                        break;
+
+                               switch (pc->k) {
+                                       ANCILLARY(VLAN_TAG);
+                                       ANCILLARY(VLAN_TAG_PRESENT);
+                               default :
+#endif
+                                       k = pc->k;
+                                       if (k >= buflen) {
 #if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               n = m;
-                               MINDEX(len, n, k);
-                               A = mtod(n, u_char *)[k];
-                               continue;
+                                               if (m == NULL)
+                                                       return 0;
+                                               n = m;
+                                               MINDEX(len, n, k);
+                                               A = mtod(n, u_char *)[k];
+                                               continue;
 #else
-                               return 0;
+                                               return 0;
+#endif
+                                       }
+                                       A = p[k];
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+                               }
+                               switch (code) {
+                               case BPF_S_ANC_VLAN_TAG:
+                                       if (aux_data)
+                                               A = aux_data->vlan_tag;
+                                       break;
+
+                               case BPF_S_ANC_VLAN_TAG_PRESENT:
+                                       if (aux_data)
+                                               A = aux_data->vlan_tag_present;
+                                       break;
+                               }
 #endif
+                               continue;
                        }
-                       A = p[k];
-                       continue;
-
                case BPF_LD|BPF_W|BPF_LEN:
                        A = wirelen;
                        continue;
@@ -314,7 +355,8 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_W|BPF_IND:
                        k = X + pc->k;
-                       if (k + sizeof(int32) > buflen) {
+                       if (pc->k > buflen || X > buflen - pc->k ||
+                           sizeof(int32_t) > buflen - k) {
 #if defined(KERNEL) || defined(_KERNEL)
                                if (m == NULL)
                                        return 0;
@@ -331,7 +373,8 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_H|BPF_IND:
                        k = X + pc->k;
-                       if (k + sizeof(short) > buflen) {
+                       if (X > buflen || pc->k > buflen - X ||
+                           sizeof(int16_t) > buflen - k) {
 #if defined(KERNEL) || defined(_KERNEL)
                                if (m == NULL)
                                        return 0;
@@ -348,7 +391,7 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_B|BPF_IND:
                        k = X + pc->k;
-                       if (k >= buflen) {
+                       if (pc->k >= buflen || X >= buflen - pc->k) {
 #if defined(KERNEL) || defined(_KERNEL)
                                if (m == NULL)
                                        return 0;
@@ -469,6 +512,12 @@ bpf_filter(pc, p, wirelen, buflen)
                        A /= X;
                        continue;
 
+               case BPF_ALU|BPF_MOD|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A %= X;
+                       continue;
+
                case BPF_ALU|BPF_AND|BPF_X:
                        A &= X;
                        continue;
@@ -477,6 +526,10 @@ bpf_filter(pc, p, wirelen, buflen)
                        A |= X;
                        continue;
 
+               case BPF_ALU|BPF_XOR|BPF_X:
+                       A ^= X;
+                       continue;
+
                case BPF_ALU|BPF_LSH|BPF_X:
                        A <<= X;
                        continue;
@@ -501,6 +554,10 @@ bpf_filter(pc, p, wirelen, buflen)
                        A /= pc->k;
                        continue;
 
+               case BPF_ALU|BPF_MOD|BPF_K:
+                       A %= pc->k;
+                       continue;
+
                case BPF_ALU|BPF_AND|BPF_K:
                        A &= pc->k;
                        continue;
@@ -509,6 +566,10 @@ bpf_filter(pc, p, wirelen, buflen)
                        A |= pc->k;
                        continue;
 
+               case BPF_ALU|BPF_XOR|BPF_K:
+                       A ^= pc->k;
+                       continue;
+
                case BPF_ALU|BPF_LSH|BPF_K:
                        A <<= pc->k;
                        continue;
@@ -518,7 +579,12 @@ bpf_filter(pc, p, wirelen, buflen)
                        continue;
 
                case BPF_ALU|BPF_NEG:
-                       A = -A;
+                       /*
+                        * Most BPF arithmetic is unsigned, but negation
+                        * can't be unsigned; throw some casts to
+                        * specify what we're trying to do.
+                        */
+                       A = (u_int32)(-(int32)A);
                        continue;
 
                case BPF_MISC|BPF_TAX:
@@ -532,6 +598,17 @@ bpf_filter(pc, p, wirelen, buflen)
        }
 }
 
+u_int
+bpf_filter(pc, p, wirelen, buflen)
+       register const struct bpf_insn *pc;
+       register const u_char *p;
+       u_int wirelen;
+       register u_int buflen;
+{
+       return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
+}
+
+
 /*
  * Return true if the 'fcode' is a valid filter program.
  * The constraints are that each jump be forward and to a valid
@@ -561,7 +638,7 @@ bpf_validate(f, len)
                return 0;
 #endif
 
-       for (i = 0; i < len; ++i) {
+       for (i = 0; i < (u_int)len; ++i) {
                p = &f[i];
                switch (BPF_CLASS(p->code)) {
                /*
@@ -611,13 +688,16 @@ bpf_validate(f, len)
                        case BPF_MUL:
                        case BPF_OR:
                        case BPF_AND:
+                       case BPF_XOR:
                        case BPF_LSH:
                        case BPF_RSH:
                        case BPF_NEG:
                                break;
                        case BPF_DIV:
+                       case BPF_MOD:
                                /*
-                                * Check for constant division by 0.
+                                * Check for constant division or modulus
+                                * by 0.
                                 */
                                if (BPF_SRC(p->code) == BPF_K && p->k == 0)
                                        return 0;
@@ -659,7 +739,7 @@ bpf_validate(f, len)
 #if defined(KERNEL) || defined(_KERNEL)
                                if (from + p->k < from || from + p->k >= len)
 #else
-                               if (from + p->k >= len)
+                               if (from + p->k >= (u_int)len)
 #endif
                                        return 0;
                                break;
@@ -667,7 +747,7 @@ bpf_validate(f, len)
                        case BPF_JGT:
                        case BPF_JGE:
                        case BPF_JSET:
-                               if (from + p->jt >= len || from + p->jf >= len)
+                               if (from + p->jt >= (u_int)len || from + p->jf >= (u_int)len)
                                        return 0;
                                break;
                        default:
index e4ff4a2..d5ab61e 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.15 2008-01-02 04:16:46 guy Exp $ (LBL)";
-#endif
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -55,7 +51,10 @@ bpf_dump(const struct bpf_program *p, int option)
        for (i = 0; i < n; ++insn, ++i) {
 #ifdef BDEBUG
                extern int bids[];
-               printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+               if (bids[i] > 0)
+                       printf("[%02d]", bids[i] - 1);
+               else
+                       printf(" -- ");
 #endif
                puts(bpf_image(insn, i));
        }
index e6c0f62..01ec536 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.28 2008-01-02 04:16:46 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -40,7 +35,7 @@ static const char rcsid[] _U_ =
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 #include <string.h>
@@ -216,6 +211,11 @@ bpf_image(p, n)
                fmt = "x";
                break;
 
+       case BPF_ALU|BPF_MOD|BPF_X:
+               op = "mod";
+               fmt = "x";
+               break;
+
        case BPF_ALU|BPF_AND|BPF_X:
                op = "and";
                fmt = "x";
@@ -226,6 +226,11 @@ bpf_image(p, n)
                fmt = "x";
                break;
 
+       case BPF_ALU|BPF_XOR|BPF_X:
+               op = "xor";
+               fmt = "x";
+               break;
+
        case BPF_ALU|BPF_LSH|BPF_X:
                op = "lsh";
                fmt = "x";
@@ -256,6 +261,11 @@ bpf_image(p, n)
                fmt = "#%d";
                break;
 
+       case BPF_ALU|BPF_MOD|BPF_K:
+               op = "mod";
+               fmt = "#%d";
+               break;
+
        case BPF_ALU|BPF_AND|BPF_K:
                op = "and";
                fmt = "#0x%x";
@@ -266,6 +276,11 @@ bpf_image(p, n)
                fmt = "#0x%x";
                break;
 
+       case BPF_ALU|BPF_XOR|BPF_K:
+               op = "xor";
+               fmt = "#0x%x";
+               break;
+
        case BPF_ALU|BPF_LSH|BPF_K:
                op = "lsh";
                fmt = "#%d";
@@ -291,13 +306,13 @@ bpf_image(p, n)
                fmt = "";
                break;
        }
-       (void)snprintf(operand, sizeof operand, fmt, v);
+       (void)pcap_snprintf(operand, sizeof operand, fmt, v);
        if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
-               (void)snprintf(image, sizeof image,
+               (void)pcap_snprintf(image, sizeof image,
                              "(%03d) %-8s %-16s jt %d\tjf %d",
                              n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
        } else {
-               (void)snprintf(image, sizeof image,
+               (void)pcap_snprintf(image, sizeof image,
                              "(%03d) %-8s %s",
                              n, op, operand);
        }
index d9de114..5cfd1b4 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.23 2006-10-04 18:09:22 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -40,7 +35,7 @@ static const char rcsid[] _U_ =
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <ctype.h>
 #include <memory.h>
index 2d6bbeb..51f6308 100644 (file)
@@ -17,8 +17,6 @@
  * 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.
- *
- * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.14 2005-09-05 09:06:58 guy Exp $ (LBL)
  */
 
 /*
 #ifndef ETHERTYPE_PPPOES
 #define ETHERTYPE_PPPOES       0x8864
 #endif
+#ifndef ETHERTYPE_8021AD
+#define ETHERTYPE_8021AD       0x88a8
+#endif
 #ifndef        ETHERTYPE_LOOPBACK
 #define        ETHERTYPE_LOOPBACK      0x9000
 #endif
diff --git a/contrib/libpcap/extract.h b/contrib/libpcap/extract.h
new file mode 100644 (file)
index 0000000..face5b7
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+
+/*
+ * Macros to extract possibly-unaligned big-endian integral values.
+ */
+#ifdef LBL_ALIGN
+/*
+ * The processor doesn't natively handle unaligned loads.
+ */
+#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+    (defined(__alpha) || defined(__alpha__) || \
+     defined(__mips) || defined(__mips__))
+
+/*
+ * This is a GCC-compatible compiler and we have __attribute__, which
+ * we assume that mean we have __attribute__((packed)), and this is
+ * MIPS or Alpha, which has instructions that can help when doing
+ * unaligned loads.
+ *
+ * Declare packed structures containing a uint16_t and a uint32_t,
+ * cast the pointer to point to one of those, and fetch through it;
+ * the GCC manual doesn't appear to explicitly say that
+ * __attribute__((packed)) causes the compiler to generate unaligned-safe
+ * code, but it apppears to do so.
+ *
+ * We do this in case the compiler can generate code using those
+ * instructions to do an unaligned load and pass stuff to "ntohs()" or
+ * "ntohl()", which might be better than than the code to fetch the
+ * bytes one at a time and assemble them.  (That might not be the
+ * case on a little-endian platform, such as DEC's MIPS machines and
+ * Alpha machines, where "ntohs()" and "ntohl()" might not be done
+ * inline.)
+ *
+ * We do this only for specific architectures because, for example,
+ * at least some versions of GCC, when compiling for 64-bit SPARC,
+ * generate code that assumes alignment if we do this.
+ *
+ * XXX - add other architectures and compilers as possible and
+ * appropriate.
+ *
+ * HP's C compiler, indicated by __HP_cc being defined, supports
+ * "#pragma unaligned N" in version A.05.50 and later, where "N"
+ * specifies a number of bytes at which the typedef on the next
+ * line is aligned, e.g.
+ *
+ *     #pragma unalign 1
+ *     typedef uint16_t unaligned_uint16_t;
+ *
+ * to define unaligned_uint16_t as a 16-bit unaligned data type.
+ * This could be presumably used, in sufficiently recent versions of
+ * the compiler, with macros similar to those below.  This would be
+ * useful only if that compiler could generate better code for PA-RISC
+ * or Itanium than would be generated by a bunch of shifts-and-ORs.
+ *
+ * DEC C, indicated by __DECC being defined, has, at least on Alpha,
+ * an __unaligned qualifier that can be applied to pointers to get the
+ * compiler to generate code that does unaligned loads and stores when
+ * dereferencing the pointer in question.
+ *
+ * XXX - what if the native C compiler doesn't support
+ * __attribute__((packed))?  How can we get it to generate unaligned
+ * accesses for *specific* items?
+ */
+typedef struct {
+       uint16_t        val;
+} __attribute__((packed)) unaligned_uint16_t;
+
+typedef struct {
+       uint32_t        val;
+} __attribute__((packed)) unaligned_uint32_t;
+
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+       return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+       return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+       return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+               ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+
+#else /* have to do it a byte at a time */
+/*
+ * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * or we do but we don't know of any better way with this instruction
+ * set to do unaligned loads, so do unaligned loads of big-endian
+ * quantities the hard way - fetch the bytes one at a time and
+ * assemble them.
+ */
+#define EXTRACT_16BITS(p) \
+       ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+                   ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
+#define EXTRACT_32BITS(p) \
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
+#define EXTRACT_64BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+#endif /* must special-case unaligned accesses */
+#else /* LBL_ALIGN */
+/*
+ * The processor natively handles unaligned loads, so we can just
+ * cast the pointer and fetch through it.
+ */
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+       return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+       return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+       return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \
+               ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
+#endif /* LBL_ALIGN */
+
+#define EXTRACT_24BITS(p) \
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
+
+#define EXTRACT_40BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
+
+#define EXTRACT_48BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
+
+#define EXTRACT_56BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
+
+/*
+ * Macros to extract possibly-unaligned little-endian integral values.
+ * XXX - do loads on little-endian machines that support unaligned loads?
+ */
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+       ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_32BITS(p) \
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_24BITS(p) \
+       ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_64BITS(p) \
+       ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+                   ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
index f4d5869..b67b5cd 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.12 2007-09-14 00:44:55 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -60,9 +55,15 @@ static const char rcsid[] _U_ =
 #include "os-proto.h"
 #endif
 
-#ifdef AF_PACKET
+/*
+ * We don't do this on Solaris 11 and later, as it appears there aren't
+ * any AF_PACKET addresses on interfaces, so we don't need this, and
+ * we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
+ * and their definitions of some data structures collide.
+ */
+#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
 # ifdef HAVE_NETPACKET_PACKET_H
-/* Solaris 11 and later, Linux distributions with newer glibc */
+/* Linux distributions with newer glibc */
 #  include <netpacket/packet.h>
 # else /* HAVE_NETPACKET_PACKET_H */
 /* LynxOS, Linux distributions with older glibc */
@@ -75,7 +76,7 @@ static const char rcsid[] _U_ =
 #  include <linux/if_packet.h>
 # endif /* __Lynx__ */
 # endif /* HAVE_NETPACKET_PACKET_H */
-#endif /* AF_PACKET */
+#endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
 
 /*
  * This is fun.
@@ -120,7 +121,7 @@ get_sa_len(struct sockaddr *addr)
                return (sizeof (struct sockaddr_in6));
 #endif
 
-#ifdef AF_PACKET
+#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
        case AF_PACKET:
                return (sizeof (struct sockaddr_ll));
 #endif
@@ -140,10 +141,11 @@ get_sa_len(struct sockaddr *addr)
  * Get a list of all interfaces that are up and that we can open.
  * Returns -1 on error, 0 otherwise.
  * The list, as returned through "alldevsp", may be null if no interfaces
- * were up and could be opened.
+ * could be opened.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+    int (*check_usable)(const char *))
 {
        pcap_if_t *devlist = NULL;
        struct ifaddrs *ifap, *ifa;
@@ -156,10 +158,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
         * Get the list of interface addresses.
         *
         * Note: this won't return information about interfaces
-        * with no addresses; are there any such interfaces
-        * that would be capable of receiving packets?
-        * (Interfaces incapable of receiving packets aren't
-        * very interesting from libpcap's point of view.)
+        * with no addresses, so, if a platform has interfaces
+        * with no interfaces on which traffic can be captured,
+        * we must check for those interfaces as well (see, for
+        * example, what's done on Linux).
         *
         * LAN interfaces will probably have link-layer
         * addresses; I don't know whether all implementations
@@ -167,40 +169,56 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
         * those.
         */
        if (getifaddrs(&ifap) != 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                    "getifaddrs: %s", pcap_strerror(errno));
                return (-1);
        }
        for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
                /*
-                * Is this interface up?
+                * If this entry has a colon followed by a number at
+                * the end, we assume it's a logical interface.  Those
+                * are just the way you assign multiple IP addresses to
+                * a real interface on Linux, so an entry for a logical
+                * interface should be treated like the entry for the
+                * real interface; we do that by stripping off the ":"
+                * and the number.
+                *
+                * XXX - should we do this only on Linux?
                 */
-               if (!(ifa->ifa_flags & IFF_UP)) {
+               p = strchr(ifa->ifa_name, ':');
+               if (p != NULL) {
                        /*
-                        * No, so don't add it to the list.
+                        * We have a ":"; is it followed by a number?
+                        */
+                       q = p + 1;
+                       while (isdigit((unsigned char)*q))
+                               q++;
+                       if (*q == '\0') {
+                               /*
+                                * All digits after the ":" until the end.
+                                * Strip off the ":" and everything after
+                                * it.
+                                */
+                              *p = '\0';
+                       }
+               }
+
+               /*
+                * Can we capture on this device?
+                */
+               if (!(*check_usable)(ifa->ifa_name)) {
+                       /*
+                        * No.
                         */
                        continue;
                }
 
                /*
                 * "ifa_addr" was apparently null on at least one
-                * interface on some system.
-                *
-                * "ifa_broadaddr" may be non-null even on
-                * non-broadcast interfaces, and was null on
-                * at least one OpenBSD 3.4 system on at least
-                * one interface with IFF_BROADCAST set.
-                *
-                * "ifa_dstaddr" was, on at least one FreeBSD 4.1
-                * system, non-null on a non-point-to-point
-                * interface.
-                *
-                * Therefore, we supply the address and netmask only
-                * if "ifa_addr" is non-null (if there's no address,
-                * there's obviously no netmask), and supply the
-                * broadcast and destination addresses if the appropriate
-                * flag is set *and* the appropriate "ifa_" entry doesn't
-                * evaluate to a null pointer.
+                * interface on some system.  Therefore, we supply
+                * the address and netmask only if "ifa_addr" is
+                * non-null (if there's no address, there's obviously
+                * no netmask).
                 */
                if (ifa->ifa_addr != NULL) {
                        addr = ifa->ifa_addr;
@@ -211,6 +229,22 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                        addr_size = 0;
                        netmask = NULL;
                }
+
+               /*
+                * Note that, on some platforms, ifa_broadaddr and
+                * ifa_dstaddr could be the same field (true on at
+                * least some versions of *BSD and OS X), so we
+                * can't just check whether the broadcast address
+                * is null and add it if so and check whether the
+                * destination address is null and add it if so.
+                *
+                * Therefore, we must also check the IFF_BROADCAST
+                * flag, and only add a broadcast address if it's
+                * set, and check the IFF_POINTTOPOINT flag, and
+                * only add a destination address if it's set (as
+                * per man page recommendations on some of those
+                * platforms).
+                */
                if (ifa->ifa_flags & IFF_BROADCAST &&
                    ifa->ifa_broadaddr != NULL) {
                        broadaddr = ifa->ifa_broadaddr;
@@ -228,40 +262,12 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                        dstaddr_size = 0;
                }
 
-               /*
-                * If this entry has a colon followed by a number at
-                * the end, we assume it's a logical interface.  Those
-                * are just the way you assign multiple IP addresses to
-                * a real interface on Linux, so an entry for a logical
-                * interface should be treated like the entry for the
-                * real interface; we do that by stripping off the ":"
-                * and the number.
-                *
-                * XXX - should we do this only on Linux?
-                */
-               p = strchr(ifa->ifa_name, ':');
-               if (p != NULL) {
-                       /*
-                        * We have a ":"; is it followed by a number?
-                        */
-                       q = p + 1;
-                       while (isdigit((unsigned char)*q))
-                               q++;
-                       if (*q == '\0') {
-                               /*
-                                * All digits after the ":" until the end.
-                                * Strip off the ":" and everything after
-                                * it.
-                                */
-                              *p = '\0';
-                       }
-               }
-
                /*
                 * Add information for this address to the list.
                 */
                if (add_addr_to_iflist(&devlist, ifa->ifa_name,
-                   ifa->ifa_flags, addr, addr_size, netmask, addr_size,
+                   if_flags_to_pcap_flags(ifa->ifa_name, ifa->ifa_flags),
+                   addr, addr_size, netmask, addr_size,
                    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
                    errbuf) < 0) {
                        ret = -1;
similarity index 59%
copy from contrib/libpcap/inet.c
copy to contrib/libpcap/fad-helpers.c
index 6ae46ef..4860bc5 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.79 2008-04-20 18:19:02 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 
 #include <sys/param.h>
 #ifndef MSDOS
@@ -59,7 +54,7 @@ struct mbuf;          /* Squelch compiler warnings on some platforms for */
 struct rtentry;                /* declarations in <net/if.h> */
 #include <net/if.h>
 #include <netinet/in.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <ctype.h>
 #include <errno.h>
@@ -67,9 +62,9 @@ struct rtentry;               /* declarations in <net/if.h> */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#if !defined(WIN32) && !defined(__BORLANDC__)
+#if !defined(_WIN32) && !defined(__BORLANDC__)
 #include <unistd.h>
-#endif /* !WIN32 && !__BORLANDC__ */
+#endif /* !_WIN32 && !__BORLANDC__ */
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #else
@@ -82,6 +77,7 @@ struct rtentry;               /* declarations in <net/if.h> */
 #include "os-proto.h"
 #endif
 
+#ifndef _WIN32
 /* Not all systems have IFF_LOOPBACK */
 #ifdef IFF_LOOPBACK
 #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
@@ -90,7 +86,38 @@ struct rtentry;              /* declarations in <net/if.h> */
     (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
 #endif
 
-struct sockaddr *
+#ifdef IFF_UP
+#define ISUP(flags) ((flags) & IFF_UP)
+#else
+#define ISUP(flags) 0
+#endif
+
+#ifdef IFF_RUNNING
+#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
+#else
+#define ISRUNNING(flags) 0
+#endif
+
+/*
+ * Map UN*X-style interface flags to libpcap flags.
+ */
+bpf_u_int32
+if_flags_to_pcap_flags(const char *name _U_, u_int if_flags)
+{
+       bpf_u_int32 pcap_flags;
+
+       pcap_flags = 0;
+       if (ISLOOPBACK(name, if_flags))
+               pcap_flags |= PCAP_IF_LOOPBACK;
+       if (ISUP(if_flags))
+               pcap_flags |= PCAP_IF_UP;
+       if (ISRUNNING(if_flags))
+               pcap_flags |= PCAP_IF_RUNNING;
+       return (pcap_flags);
+}
+#endif
+
+static struct sockaddr *
 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
 {
        struct sockaddr *newsa;
@@ -100,40 +127,259 @@ dup_sockaddr(struct sockaddr *sa, size_t sa_length)
        return (memcpy(newsa, sa, sa_length));
 }
 
-static int
-get_instance(const char *name)
+/*
+ * Construct a "figure of merit" for an interface, for use when sorting
+ * the list of interfaces, in which interfaces that are up are superior
+ * to interfaces that aren't up, interfaces that are up and running are
+ * superior to interfaces that are up but not running, and non-loopback
+ * interfaces that are up and running are superior to loopback interfaces,
+ * and interfaces with the same flags have a figure of merit that's higher
+ * the lower the instance number.
+ *
+ * The goal is to try to put the interfaces most likely to be useful for
+ * capture at the beginning of the list.
+ *
+ * The figure of merit, which is lower the "better" the interface is,
+ * has the uppermost bit set if the interface isn't running, the bit
+ * below that set if the interface isn't up, the bit below that set
+ * if the interface is a loopback interface, and the interface index
+ * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
+ */
+static u_int
+get_figure_of_merit(pcap_if_t *dev)
 {
-       const char *cp, *endcp;
-       int n;
+       const char *cp;
+       u_int n;
 
-       if (strcmp(name, "any") == 0) {
+       if (strcmp(dev->name, "any") == 0) {
                /*
                 * Give the "any" device an artificially high instance
                 * number, so it shows up after all other non-loopback
                 * interfaces.
                 */
-               return INT_MAX;
+               n = 0x1FFFFFFF; /* 29 all-1 bits */
+       } else {
+               /*
+                * A number at the end of the device name string is
+                * assumed to be a unit number.
+                */
+               cp = dev->name + strlen(dev->name) - 1;
+               while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
+                       cp--;
+               if (*cp >= '0' && *cp <= '9')
+                       n = atoi(cp);
+               else
+                       n = 0;
        }
+       if (!(dev->flags & PCAP_IF_RUNNING))
+               n |= 0x80000000;
+       if (!(dev->flags & PCAP_IF_UP))
+               n |= 0x40000000;
+       if (dev->flags & PCAP_IF_LOOPBACK)
+               n |= 0x20000000;
+       return (n);
+}
 
-       endcp = name + strlen(name);
-       for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
-               continue;
+/*
+ * Try to get a description for a given device.
+ * Returns a mallocated description if it could and NULL if it couldn't.
+ *
+ * XXX - on FreeBSDs that support it, should it get the sysctl named
+ * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
+ * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
+ * with my Cisco 350 card, so the name isn't entirely descriptive.  The
+ * "dev.an.0.%pnpinfo" has a better description, although one might argue
+ * that the problem is really a driver bug - if it can find out that it's
+ * a Cisco 340 or 350, rather than an old Aironet card, it should use
+ * that in the description.
+ *
+ * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
+ * and OpenBSD let you get a description, but it's not generated by the OS,
+ * it's set with another ioctl that ifconfig supports; we use that to get
+ * a description in FreeBSD and OpenBSD, but if there is no such
+ * description available, it still might be nice to get some description
+ * string based on the device type or something such as that.
+ *
+ * In OS X, the System Configuration framework can apparently return
+ * names in 10.4 and later.
+ *
+ * It also appears that freedesktop.org's HAL offers an "info.product"
+ * string, but the HAL specification says it "should not be used in any
+ * UI" and "subsystem/capability specific properties" should be used
+ * instead and, in any case, I think HAL is being deprecated in
+ * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
+ * to have any obvious product information for devices, but maybe
+ * I haven't looked hard enough.
+ *
+ * Using the System Configuration framework, or HAL, or DeviceKit, or
+ * whatever, would require that libpcap applications be linked with
+ * the frameworks/libraries in question.  That shouldn't be a problem
+ * for programs linking with the shared version of libpcap (unless
+ * you're running on AIX - which I think is the only UN*X that doesn't
+ * support linking a shared library with other libraries on which it
+ * depends, and having an executable linked only with the first shared
+ * library automatically pick up the other libraries when started -
+ * and using HAL or whatever).  Programs linked with the static
+ * version of libpcap would have to use pcap-config with the --static
+ * flag in order to get the right linker flags in order to pick up
+ * the additional libraries/frameworks; those programs need that anyway
+ * for libpcap 1.1 and beyond on Linux, as, by default, it requires
+ * -lnl.
+ *
+ * Do any other UN*Xes, or desktop environments support getting a
+ * description?
+ */
+static char *
+get_if_description(const char *name)
+{
+#ifdef SIOCGIFDESCR
+       char *description = NULL;
+       int s;
+       struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+       size_t descrlen = 64;
+#else
+       size_t descrlen = IFDESCRSIZE;
+#endif /* IFDESCRSIZE */
 
-       if (isdigit((unsigned char)*cp))
-               n = atoi(cp);
-       else
-               n = 0;
-       return (n);
+       /*
+        * Get the description for the interface.
+        */
+       memset(&ifrdesc, 0, sizeof ifrdesc);
+       strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s >= 0) {
+#ifdef __FreeBSD__
+               /*
+                * On FreeBSD, if the buffer isn't big enough for the
+                * description, the ioctl succeeds, but the description
+                * isn't copied, ifr_buffer.length is set to the description
+                * length, and ifr_buffer.buffer is set to NULL.
+                */
+               for (;;) {
+                       free(description);
+                       if ((description = malloc(descrlen)) != NULL) {
+                               ifrdesc.ifr_buffer.buffer = description;
+                               ifrdesc.ifr_buffer.length = descrlen;
+                               if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
+                                       if (ifrdesc.ifr_buffer.buffer ==
+                                           description)
+                                               break;
+                                       else
+                                               descrlen = ifrdesc.ifr_buffer.length;
+                               } else {
+                                       /*
+                                        * Failed to get interface description.
+                                        */
+                                       free(description);
+                                       description = NULL;
+                                       break;
+                               }
+                       } else
+                               break;
+               }
+#else /* __FreeBSD__ */
+               /*
+                * The only other OS that currently supports
+                * SIOCGIFDESCR is OpenBSD, and it has no way
+                * to get the description length - it's clamped
+                * to a maximum of IFDESCRSIZE.
+                */
+               if ((description = malloc(descrlen)) != NULL) {
+                       ifrdesc.ifr_data = (caddr_t)description;
+                       if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
+                               /*
+                                * Failed to get interface description.
+                                */
+                               free(description);
+                               description = NULL;
+                       }
+               }
+#endif /* __FreeBSD__ */
+               close(s);
+               if (description != NULL && strlen(description) == 0) {
+                       /*
+                        * Description is empty, so discard it.
+                        */
+                       free(description);
+                       description = NULL;
+               }
+       }
+
+#ifdef __FreeBSD__
+       /*
+        * For FreeBSD, if we didn't get a description, and this is
+        * a device with a name of the form usbusN, label it as a USB
+        * bus.
+        */
+       if (description == NULL) {
+               if (strncmp(name, "usbus", 5) == 0) {
+                       /*
+                        * OK, it begins with "usbus".
+                        */
+                       long busnum;
+                       char *p;
+
+                       errno = 0;
+                       busnum = strtol(name + 5, &p, 10);
+                       if (errno == 0 && p != name + 5 && *p == '\0' &&
+                           busnum >= 0 && busnum <= INT_MAX) {
+                               /*
+                                * OK, it's a valid number that's not
+                                * bigger than INT_MAX.  Construct
+                                * a description from it.
+                                */
+                               static const char descr_prefix[] = "USB bus number ";
+                               size_t descr_size;
+
+                               /*
+                                * Allow enough room for a 32-bit bus number.
+                                * sizeof (descr_prefix) includes the
+                                * terminating NUL.
+                                */
+                               descr_size = sizeof (descr_prefix) + 10;
+                               description = malloc(descr_size);
+                               if (description != NULL) {
+                                       pcap_snprintf(description, descr_size,
+                                           "%s%ld", descr_prefix, busnum);
+                               }
+                       }
+               }
+       }
+#endif
+       return (description);
+#else /* SIOCGIFDESCR */
+       return (NULL);
+#endif /* SIOCGIFDESCR */
 }
 
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0 and set *curdev_ret to point to it.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
+ *
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags and description, and, if that succeeds, return 0
+ *     and set *curdev_ret to point to the new entry, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.  If we
+ *     weren't given a description, try to get one.
+ */
 int
 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
-    u_int flags, const char *description, char *errbuf)
+    bpf_u_int32 flags, const char *description, char *errbuf)
 {
        pcap_t *p;
        pcap_if_t *curdev, *prevdev, *nextdev;
-       int this_instance;
+       u_int this_figure_of_merit, nextdev_figure_of_merit;
        char open_errbuf[PCAP_ERRBUF_SIZE];
+       int ret;
 
        /*
         * Is there already an entry in the list for this interface?
@@ -187,34 +433,83 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
                        en_name_len = strlen(name) - 1;
                        en_name = malloc(en_name_len + 1);
                        if (en_name == NULL) {
-                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                                    "malloc: %s", pcap_strerror(errno));
                                return (-1);
                        }
                        strcpy(en_name, "en");
                        strcat(en_name, name + 3);
-                       p = pcap_open_live(en_name, 68, 0, 0, open_errbuf);
+                       p = pcap_create(en_name, open_errbuf);
                        free(en_name);
                } else
 #endif /* __APPLE */
-               p = pcap_open_live(name, 68, 0, 0, open_errbuf);
+               p = pcap_create(name, open_errbuf);
                if (p == NULL) {
                        /*
-                        * No.  Don't bother including it.
-                        * Don't treat this as an error, though.
+                        * The attempt to create the pcap_t failed;
+                        * that's probably an indication that we're
+                        * out of memory.
+                        *
+                        * Don't bother including this interface,
+                        * but don't treat it as an error.
                         */
                        *curdev_ret = NULL;
                        return (0);
                }
+               /* Small snaplen, so we don't try to allocate much memory. */
+               pcap_set_snaplen(p, 68);
+               ret = pcap_activate(p);
                pcap_close(p);
+               switch (ret) {
+
+               case PCAP_ERROR_NO_SUCH_DEVICE:
+               case PCAP_ERROR_IFACE_NOT_UP:
+                       /*
+                        * We expect these two errors - they're the
+                        * reason we try to open the device.
+                        *
+                        * PCAP_ERROR_NO_SUCH_DEVICE typically means
+                        * "there's no such device *known to the
+                        * OS's capture mechanism*", so, even though
+                        * it might be a valid network interface, you
+                        * can't capture on it (e.g., the loopback
+                        * device in Solaris up to Solaris 10, or
+                        * the vmnet devices in OS X with VMware
+                        * Fusion).  We don't include those devices
+                        * in our list of devices, as there's no
+                        * point in doing so - they're not available
+                        * for capture.
+                        *
+                        * PCAP_ERROR_IFACE_NOT_UP means that the
+                        * OS's capture mechanism doesn't work on
+                        * interfaces not marked as up; some capture
+                        * mechanisms *do* support that, so we no
+                        * longer reject those interfaces out of hand,
+                        * but we *do* want to reject them if they
+                        * can't be opened for capture.
+                        */
+                       *curdev_ret = NULL;
+                       return (0);
+               }
 
                /*
-                * Yes, we can open it.
+                * Yes, we can open it, or we can't, for some other
+                * reason.
+                *
+                * If we can open it, we want to offer it for
+                * capture, as you can capture on it.  If we can't,
+                * we want to offer it for capture, so that, if
+                * the user tries to capture on it, they'll get
+                * an error and they'll know why they can't
+                * capture on it (e.g., insufficient permissions)
+                * or they'll report it as a problem (and then
+                * have the error message to provide as information).
+                *
                 * Allocate a new entry.
                 */
                curdev = malloc(sizeof(pcap_if_t));
                if (curdev == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        return (-1);
                }
@@ -225,47 +520,45 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
                curdev->next = NULL;
                curdev->name = strdup(name);
                if (curdev->name == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        free(curdev);
                        return (-1);
                }
-               if (description != NULL) {
+               if (description == NULL) {
                        /*
-                        * We have a description for this interface.
+                        * We weren't handed a description for the
+                        * interface, so see if we can generate one
+                        * ourselves.
+                        */
+                       curdev->description = get_if_description(name);
+               } else {
+                       /*
+                        * We were handed a description; make a copy.
                         */
                        curdev->description = strdup(description);
                        if (curdev->description == NULL) {
-                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                                    "malloc: %s", pcap_strerror(errno));
                                free(curdev->name);
                                free(curdev);
                                return (-1);
                        }
-               } else {
-                       /*
-                        * We don't.
-                        */
-                       curdev->description = NULL;
                }
                curdev->addresses = NULL;       /* list starts out as empty */
-               curdev->flags = 0;
-               if (ISLOOPBACK(name, flags))
-                       curdev->flags |= PCAP_IF_LOOPBACK;
+               curdev->flags = flags;
 
                /*
                 * Add it to the list, in the appropriate location.
-                * First, get the instance number of this interface.
+                * First, get the "figure of merit" for this
+                * interface.
                 */
-               this_instance = get_instance(name);
+               this_figure_of_merit = get_figure_of_merit(curdev);
 
                /*
-                * Now look for the last interface with an instance number
-                * less than or equal to the new interface's instance
-                * number - except that non-loopback interfaces are
-                * arbitrarily treated as having interface numbers less
-                * than those of loopback interfaces, so the loopback
-                * interfaces are put at the end of the list.
+                * Now look for the last interface with an figure of merit
+                * less than or equal to the new interface's figure of
+                * merit.
                 *
                 * We start with "prevdev" being NULL, meaning we're before
                 * the first element in the list.
@@ -295,34 +588,13 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
                        }
 
                        /*
-                        * Is the new interface a non-loopback interface
-                        * and the next interface a loopback interface?
+                        * Is the new interface's figure of merit less
+                        * than the next interface's figure of merit,
+                        * meaning that the new interface is better
+                        * than the next interface?
                         */
-                       if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
-                           (nextdev->flags & PCAP_IF_LOOPBACK)) {
-                               /*
-                                * Yes, we should put the new entry
-                                * before "nextdev", i.e. after "prevdev".
-                                */
-                               break;
-                       }
-
-                       /*
-                        * Is the new interface's instance number less
-                        * than the next interface's instance number,
-                        * and is it the case that the new interface is a
-                        * non-loopback interface or the next interface is
-                        * a loopback interface?
-                        *
-                        * (The goal of both loopback tests is to make
-                        * sure that we never put a loopback interface
-                        * before any non-loopback interface and that we
-                        * always put a non-loopback interface before all
-                        * loopback interfaces.)
-                        */
-                       if (this_instance < get_instance(nextdev->name) &&
-                           (!(curdev->flags & PCAP_IF_LOOPBACK) ||
-                              (nextdev->flags & PCAP_IF_LOOPBACK))) {
+                       nextdev_figure_of_merit = get_figure_of_merit(nextdev);
+                       if (this_figure_of_merit < nextdev_figure_of_merit) {
                                /*
                                 * Yes - we should put the new entry
                                 * before "nextdev", i.e. after "prevdev".
@@ -358,53 +630,34 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
 }
 
 /*
- * XXX - on FreeBSDs that support it, should it get the sysctl named
- * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
- * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
- * with my Cisco 350 card, so the name isn't entirely descriptive.  The
- * "dev.an.0.%pnpinfo" has a better description, although one might argue
- * that the problem is really a driver bug - if it can find out that it's
- * a Cisco 340 or 350, rather than an old Aironet card, it should use
- * that in the description.
+ * Try to get a description for a given device, and then look for that
+ * device in the specified list of devices.
  *
- * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
- * and OpenBSD let you get a description, but it's not generated by the OS,
- * it's set with another ioctl that ifconfig supports; we use that to get
- * a description in FreeBSD and OpenBSD, but if there is no such
- * description available, it still might be nice to get some description
- * string based on the device type or something such as that.
+ * If we find it, then, if the specified address isn't null, add it to
+ * the list of addresses for the device and return 0.
  *
- * In OS X, the System Configuration framework can apparently return
- * names in 10.4 and later.
+ * If we don't find it, check whether we can open it:
  *
- * It also appears that freedesktop.org's HAL offers an "info.product"
- * string, but the HAL specification says it "should not be used in any
- * UI" and "subsystem/capability specific properties" should be used
- * instead and, in any case, I think HAL is being deprecated in
- * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
- * to have any obvious product information for devices, but maybe
- * I haven't looked hard enough.
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
  *
- * Using the System Configuration framework, or HAL, or DeviceKit, or
- * whatever, would require that libpcap applications be linked with
- * the frameworks/libraries in question.  That shouldn't be a problem
- * for programs linking with the shared version of libpcap (unless
- * you're running on AIX - which I think is the only UN*X that doesn't
- * support linking a shared library with other libraries on which it
- * depends, and having an executable linked only with the first shared
- * library automatically pick up the other libraries when started -
- * and using HAL or whatever).  Programs linked with the static
- * version of libpcap would have to use pcap-config with the --static
- * flag in order to get the right linker flags in order to pick up
- * the additional libraries/frameworks; those programs need that anyway
- * for libpcap 1.1 and beyond on Linux, as, by default, it requires
- * -lnl.
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags, and, if that succeeds, add the specified address
+ *     to its list of addresses if that address is non-null, set
+ *     *curdev_ret to point to the new entry, and return 0, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.
  *
- * Do any other UN*Xes, or desktop environments support getting a
- * description?
+ * (We can get called with a null address because we might get a list
+ * of interface name/address combinations from the underlying OS, with
+ * the address being absent in some cases, rather than a list of
+ * interfaces with each interface having a list of addresses, so this
+ * call may be the only call made to add to the list, and we want to
+ * add interfaces even if they have no addresses.)
  */
 int
-add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
     struct sockaddr *addr, size_t addr_size,
     struct sockaddr *netmask, size_t netmask_size,
     struct sockaddr *broadaddr, size_t broadaddr_size,
@@ -412,90 +665,13 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
     char *errbuf)
 {
        pcap_if_t *curdev;
-       char *description = NULL;
-       pcap_addr_t *curaddr, *prevaddr, *nextaddr;
-#ifdef SIOCGIFDESCR
-       int s;
-       struct ifreq ifrdesc;
-#ifndef IFDESCRSIZE
-       size_t descrlen = 64;
-#else
-       size_t descrlen = IFDESCRSIZE;
-#endif /* IFDESCRSIZE */
-#endif /* SIOCGIFDESCR */
 
-#ifdef SIOCGIFDESCR
-       /*
-        * Get the description for the interface.
-        */
-       memset(&ifrdesc, 0, sizeof ifrdesc);
-       strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
-       s = socket(AF_INET, SOCK_DGRAM, 0);
-       if (s >= 0) {
-#ifdef __FreeBSD__
-               /*
-                * On FreeBSD, if the buffer isn't big enough for the
-                * description, the ioctl succeeds, but the description
-                * isn't copied, ifr_buffer.length is set to the description
-                * length, and ifr_buffer.buffer is set to NULL.
-                */
-               for (;;) {
-                       free(description);
-                       if ((description = malloc(descrlen)) != NULL) {
-                               ifrdesc.ifr_buffer.buffer = description;
-                               ifrdesc.ifr_buffer.length = descrlen;
-                               if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
-                                       if (ifrdesc.ifr_buffer.buffer ==
-                                           description)
-                                               break;
-                                       else
-                                               descrlen = ifrdesc.ifr_buffer.length;
-                               } else {
-                                       /*
-                                        * Failed to get interface description.
-                                        */
-                                       free(description);
-                                       description = NULL;
-                                       break;
-                               }
-                       } else
-                               break;
-               }
-#else /* __FreeBSD__ */
-               /*
-                * The only other OS that currently supports
-                * SIOCGIFDESCR is OpenBSD, and it has no way
-                * to get the description length - it's clamped
-                * to a maximum of IFDESCRSIZE.
-                */
-               if ((description = malloc(descrlen)) != NULL) {
-                       ifrdesc.ifr_data = (caddr_t)description;
-                       if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
-                               /*
-                                * Failed to get interface description.
-                                */
-                               free(description);
-                               description = NULL;
-                       }
-               }
-#endif /* __FreeBSD__ */
-               close(s);
-               if (description != NULL && strlen(description) == 0) {
-                       free(description);
-                       description = NULL;
-               }
-       }
-#endif /* SIOCGIFDESCR */
-
-       if (add_or_find_if(&curdev, alldevs, name, flags, description,
-           errbuf) == -1) {
-               free(description);
+       if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
                /*
                 * Error - give up.
                 */
                return (-1);
        }
-       free(description);
        if (curdev == NULL) {
                /*
                 * Device wasn't added because it can't be opened.
@@ -504,15 +680,45 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
                return (0);
        }
 
+       if (addr == NULL) {
+               /*
+                * There's no address to add; this entry just meant
+                * "here's a new interface".
+                */
+               return (0);
+       }
+
        /*
-        * "curdev" is an entry for this interface; add an entry for this
-        * address to its list of addresses.
+        * "curdev" is an entry for this interface, and we have an
+        * address for it; add an entry for that address to the
+        * interface's list of addresses.
         *
         * Allocate the new entry and fill it in.
         */
+       return (add_addr_to_dev(curdev, addr, addr_size, netmask,
+           netmask_size, broadaddr, broadaddr_size, dstaddr,
+           dstaddr_size, errbuf));
+}
+
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ * If this is the first IP address added to the interface, move it
+ * in the list as appropriate.
+ */
+int
+add_addr_to_dev(pcap_if_t *curdev,
+    struct sockaddr *addr, size_t addr_size,
+    struct sockaddr *netmask, size_t netmask_size,
+    struct sockaddr *broadaddr, size_t broadaddr_size,
+    struct sockaddr *dstaddr, size_t dstaddr_size,
+    char *errbuf)
+{
+       pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
        curaddr = malloc(sizeof(pcap_addr_t));
        if (curaddr == NULL) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                    "malloc: %s", pcap_strerror(errno));
                return (-1);
        }
@@ -521,7 +727,7 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
        if (addr != NULL) {
                curaddr->addr = dup_sockaddr(addr, addr_size);
                if (curaddr->addr == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        free(curaddr);
                        return (-1);
@@ -532,7 +738,7 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
        if (netmask != NULL) {
                curaddr->netmask = dup_sockaddr(netmask, netmask_size);
                if (curaddr->netmask == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        if (curaddr->addr != NULL)
                                free(curaddr->addr);
@@ -545,7 +751,7 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
        if (broadaddr != NULL) {
                curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
                if (curaddr->broadaddr == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        if (curaddr->netmask != NULL)
                                free(curaddr->netmask);
@@ -560,7 +766,7 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
        if (dstaddr != NULL) {
                curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
                if (curaddr->dstaddr == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                            "malloc: %s", pcap_strerror(errno));
                        if (curaddr->broadaddr != NULL)
                                free(curaddr->broadaddr);
@@ -603,6 +809,23 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
        return (0);
 }
 
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
+ *
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags and description, and, if that succeeds, return 0
+ *     and set *curdev_ret to point to the new entry, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.
+ */
 int
 pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
     const char *description, char *errbuf)
@@ -659,275 +882,3 @@ pcap_freealldevs(pcap_if_t *alldevs)
                free(curdev);
        }
 }
-
-#if !defined(WIN32) && !defined(MSDOS)
-
-/*
- * Return the name of a network interface attached to the system, or NULL
- * if none can be found.  The interface must be configured up; the
- * lowest unit number is preferred; loopback is ignored.
- */
-char *
-pcap_lookupdev(errbuf)
-       register char *errbuf;
-{
-       pcap_if_t *alldevs;
-/* for old BSD systems, including bsdi3 */
-#ifndef IF_NAMESIZE
-#define IF_NAMESIZE IFNAMSIZ
-#endif
-       static char device[IF_NAMESIZE + 1];
-       char *ret;
-
-       if (pcap_findalldevs(&alldevs, errbuf) == -1)
-               return (NULL);
-
-       if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
-               /*
-                * There are no devices on the list, or the first device
-                * on the list is a loopback device, which means there
-                * are no non-loopback devices on the list.  This means
-                * we can't return any device.
-                *
-                * XXX - why not return a loopback device?  If we can't
-                * capture on it, it won't be on the list, and if it's
-                * on the list, there aren't any non-loopback devices,
-                * so why not just supply it as the default device?
-                */
-               (void)strlcpy(errbuf, "no suitable device found",
-                   PCAP_ERRBUF_SIZE);
-               ret = NULL;
-       } else {
-               /*
-                * Return the name of the first device on the list.
-                */
-               (void)strlcpy(device, alldevs->name, sizeof(device));
-               ret = device;
-       }
-
-       pcap_freealldevs(alldevs);
-       return (ret);
-}
-
-int
-pcap_lookupnet(device, netp, maskp, errbuf)
-       register const char *device;
-       register bpf_u_int32 *netp, *maskp;
-       register char *errbuf;
-{
-       register int fd;
-       register struct sockaddr_in *sin4;
-       struct ifreq ifr;
-
-       /*
-        * The pseudo-device "any" listens on all interfaces and therefore
-        * has the network address and -mask "0.0.0.0" therefore catching
-        * all traffic. Using NULL for the interface is the same as "any".
-        */
-       if (!device || strcmp(device, "any") == 0
-#ifdef HAVE_DAG_API
-           || strstr(device, "dag") != NULL
-#endif
-#ifdef HAVE_SEPTEL_API
-           || strstr(device, "septel") != NULL
-#endif
-#ifdef PCAP_SUPPORT_BT
-           || strstr(device, "bluetooth") != NULL
-#endif
-#ifdef PCAP_SUPPORT_USB
-           || strstr(device, "usbmon") != NULL
-#endif
-#ifdef HAVE_SNF_API
-           || strstr(device, "snf") != NULL
-#endif
-           ) {
-               *netp = *maskp = 0;
-               return 0;
-       }
-
-       fd = socket(AF_INET, SOCK_DGRAM, 0);
-       if (fd < 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
-                   pcap_strerror(errno));
-               return (-1);
-       }
-       memset(&ifr, 0, sizeof(ifr));
-#ifdef linux
-       /* XXX Work around Linux kernel bug */
-       ifr.ifr_addr.sa_family = AF_INET;
-#endif
-       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
-               if (errno == EADDRNOTAVAIL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "%s: no IPv4 address assigned", device);
-               } else {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "SIOCGIFADDR: %s: %s",
-                           device, pcap_strerror(errno));
-               }
-               (void)close(fd);
-               return (-1);
-       }
-       sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
-       *netp = sin4->sin_addr.s_addr;
-       memset(&ifr, 0, sizeof(ifr));
-#ifdef linux
-       /* XXX Work around Linux kernel bug */
-       ifr.ifr_addr.sa_family = AF_INET;
-#endif
-       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
-               (void)close(fd);
-               return (-1);
-       }
-       (void)close(fd);
-       *maskp = sin4->sin_addr.s_addr;
-       if (*maskp == 0) {
-               if (IN_CLASSA(*netp))
-                       *maskp = IN_CLASSA_NET;
-               else if (IN_CLASSB(*netp))
-                       *maskp = IN_CLASSB_NET;
-               else if (IN_CLASSC(*netp))
-                       *maskp = IN_CLASSC_NET;
-               else {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "inet class for 0x%x unknown", *netp);
-                       return (-1);
-               }
-       }
-       *netp &= *maskp;
-       return (0);
-}
-
-#elif defined(WIN32)
-
-/*
- * Return the name of a network interface attached to the system, or NULL
- * if none can be found.  The interface must be configured up; the
- * lowest unit number is preferred; loopback is ignored.
- */
-char *
-pcap_lookupdev(errbuf)
-       register char *errbuf;
-{
-       DWORD dwVersion;
-       DWORD dwWindowsMajorVersion;
-       dwVersion = GetVersion();       /* get the OS version */
-       dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
-       
-       if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
-               /*
-                * Windows 95, 98, ME.
-                */
-               ULONG NameLength = 8192;
-               static char AdaptersName[8192];
-               
-               if (PacketGetAdapterNames(AdaptersName,&NameLength) )
-                       return (AdaptersName);
-               else
-                       return NULL;
-       } else {
-               /*
-                * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
-                */
-               ULONG NameLength = 8192;
-               static WCHAR AdaptersName[8192];
-               char *tAstr;
-               WCHAR *tUstr;
-               WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
-               int NAdapts = 0;
-
-               if(TAdaptersName == NULL)
-               {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
-                       return NULL;
-               }
-
-               if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
-               {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                               "PacketGetAdapterNames: %s",
-                               pcap_win32strerror());
-                       free(TAdaptersName);
-                       return NULL;
-               }
-
-
-               tAstr = (char*)TAdaptersName;
-               tUstr = (WCHAR*)AdaptersName;
-
-               /*
-                * Convert and copy the device names
-                */
-               while(sscanf(tAstr, "%S", tUstr) > 0)
-               {
-                       tAstr += strlen(tAstr) + 1;
-                       tUstr += wcslen(tUstr) + 1;
-                       NAdapts ++;
-               }
-
-               tAstr++;
-               *tUstr = 0;
-               tUstr++;
-
-               /*
-                * Copy the descriptions
-                */
-               while(NAdapts--)
-               {
-                       char* tmp = (char*)tUstr;
-                       strcpy(tmp, tAstr);
-                       tmp += strlen(tAstr) + 1;
-                       tUstr = (WCHAR*)tmp;
-                       tAstr += strlen(tAstr) + 1;
-               }
-
-               free(TAdaptersName);
-               return (char *)(AdaptersName);
-       }       
-}
-
-
-int
-pcap_lookupnet(device, netp, maskp, errbuf)
-       register const char *device;
-       register bpf_u_int32 *netp, *maskp;
-       register char *errbuf;
-{
-       /* 
-        * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
-        * in order to skip non IPv4 (i.e. IPv6 addresses)
-        */
-       npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
-       LONG if_addr_size = 1;
-       struct sockaddr_in *t_addr;
-       unsigned int i;
-
-       if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
-               *netp = *maskp = 0;
-               return (0);
-       }
-
-       for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
-       {
-               if(if_addrs[i].IPAddress.ss_family == AF_INET)
-               {
-                       t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
-                       *netp = t_addr->sin_addr.S_un.S_addr;
-                       t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
-                       *maskp = t_addr->sin_addr.S_un.S_addr;
-
-                       *netp &= *maskp;
-                       return (0);
-               }
-                               
-       }
-
-       *netp = *maskp = 0;
-       return (0);
-}
-
-#endif /* !WIN32 && !MSDOS */
index cdb0d34..a887f27 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.309 2008-12-23 20:13:29 guy Exp $ (LBL)";
-#endif
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -41,16 +37,9 @@ static const char rcsid[] _U_ =
 #endif
 #include <sys/types.h>
 #include <sys/socket.h>
-#endif /* WIN32 */
-
-/*
- * XXX - why was this included even on UNIX?
- */
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
+#endif /* _WIN32 */
 
-#ifndef WIN32
+#ifndef _WIN32
 
 #ifdef __NetBSD__
 #include <sys/param.h>
@@ -59,7 +48,7 @@ static const char rcsid[] _U_ =
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdlib.h>
 #include <string.h>
@@ -84,29 +73,86 @@ static const char rcsid[] _U_ =
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
 #include "arcnet.h"
-#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+
+#include "grammar.h"
+#include "scanner.h"
+
+#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
 #include <linux/types.h>
 #include <linux/if_packet.h>
 #include <linux/filter.h>
 #endif
+
 #ifdef HAVE_NET_PFVAR_H
 #include <sys/socket.h>
 #include <net/if.h>
 #include <net/pfvar.h>
 #include <net/if_pflog.h>
 #endif
+
 #ifndef offsetof
 #define offsetof(s, e) ((size_t)&((s *)0)->e)
 #endif
+
 #ifdef INET6
-#ifndef WIN32
+#ifdef _WIN32
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+       u_int8_t                u6_addr8[16];
+       u_int16_t       u6_addr16[8];
+       u_int32_t       u6_addr32[4];
+      } in6_u;
+#define s6_addr                        in6_u.u6_addr8
+#define s6_addr16              in6_u.u6_addr16
+#define s6_addr32              in6_u.u6_addr32
+#define s6_addr64              in6_u.u6_addr64
+  };
+
+typedef unsigned short sa_family_t;
+
+#define        __SOCKADDR_COMMON(sa_prefix) \
+  sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6.  */
+struct sockaddr_in6
+  {
+    __SOCKADDR_COMMON (sin6_);
+    u_int16_t sin6_port;               /* Transport layer port # */
+    u_int32_t sin6_flowinfo;   /* IPv6 flow information */
+    struct in6_addr sin6_addr; /* IPv6 address */
+  };
+
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif /* EAI_ADDRFAMILY */
+#endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+#else /* _WIN32 */
 #include <netdb.h>     /* for "struct addrinfo" */
-#endif /* WIN32 */
-#endif /*INET6*/
+#endif /* _WIN32 */
+#endif /* INET6 */
 #include <pcap/namedb.h>
 
+#include "nametoaddr.h"
+
 #define ETHERMTU       1500
 
+#ifndef ETHERTYPE_TEB
+#define ETHERTYPE_TEB 0x6558
+#endif
+
 #ifndef IPPROTO_HOPOPTS
 #define IPPROTO_HOPOPTS 0
 #endif
@@ -123,76 +169,75 @@ static const char rcsid[] _U_ =
 #define IPPROTO_SCTP 132
 #endif
 
+#define GENEVE_PORT 6081
+
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
 #endif
 
 #define JMP(c) ((c)|BPF_JMP|BPF_K)
 
-/* Locals */
-static jmp_buf top_ctx;
-static pcap_t *bpf_pcap;
-
-/* Hack for updating VLAN, MPLS, and PPPoE offsets. */
-#ifdef WIN32
-static u_int   orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
-#else
-static u_int   orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
-#endif
-
-/* XXX */
-#ifdef PCAP_FDDIPAD
-static int     pcap_fddipad;
-#endif
-
-/* VARARGS */
-void
-bpf_error(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       if (bpf_pcap != NULL)
-               (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
-                   fmt, ap);
-       va_end(ap);
-       longjmp(top_ctx, 1);
-       /* NOTREACHED */
+/*
+ * "Push" the current value of the link-layer header type and link-layer
+ * header offset onto a "stack", and set a new value.  (It's not a
+ * full-blown stack; we keep only the top two items.)
+ */
+#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
+{ \
+       (cs)->prevlinktype = (cs)->linktype; \
+       (cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
+       (cs)->linktype = (new_linktype); \
+       (cs)->off_linkhdr.is_variable = (new_is_variable); \
+       (cs)->off_linkhdr.constant_part = (new_constant_part); \
+       (cs)->off_linkhdr.reg = (new_reg); \
+       (cs)->is_geneve = 0; \
 }
 
-static void init_linktype(pcap_t *);
-
-static void init_regs(void);
-static int alloc_reg(void);
-static void free_reg(int);
+/*
+ * Offset "not set" value.
+ */
+#define OFFSET_NOT_SET 0xffffffffU
 
-static struct block *root;
+/*
+ * Absolute offsets, which are offsets from the beginning of the raw
+ * packet data, are, in the general case, the sum of a variable value
+ * and a constant value; the variable value may be absent, in which
+ * case the offset is only the constant value, and the constant value
+ * may be zero, in which case the offset is only the variable value.
+ *
+ * bpf_abs_offset is a structure containing all that information:
+ *
+ *   is_variable is 1 if there's a variable part.
+ *
+ *   constant_part is the constant part of the value, possibly zero;
+ *
+ *   if is_variable is 1, reg is the register number for a register
+ *   containing the variable value if the register has been assigned,
+ *   and -1 otherwise.
+ */
+typedef struct {
+       int     is_variable;
+       u_int   constant_part;
+       int     reg;
+} bpf_abs_offset;
 
 /*
  * Value passed to gen_load_a() to indicate what the offset argument
- * is relative to.
+ * is relative to the beginning of.
  */
 enum e_offrel {
-       OR_PACKET,      /* relative to the beginning of the packet */
-       OR_LINK,        /* relative to the beginning of the link-layer header */
-       OR_MACPL,       /* relative to the end of the MAC-layer header */
-       OR_NET,         /* relative to the network-layer header */
-       OR_NET_NOSNAP,  /* relative to the network-layer header, with no SNAP header at the link layer */
-       OR_TRAN_IPV4,   /* relative to the transport-layer header, with IPv4 network layer */
-       OR_TRAN_IPV6    /* relative to the transport-layer header, with IPv6 network layer */
+       OR_PACKET,              /* full packet data */
+       OR_LINKHDR,             /* link-layer header */
+       OR_PREVLINKHDR,         /* previous link-layer header */
+       OR_LLC,                 /* 802.2 LLC header */
+       OR_PREVMPLSHDR,         /* previous MPLS header */
+       OR_LINKTYPE,            /* link-layer type */
+       OR_LINKPL,              /* link-layer payload */
+       OR_LINKPL_NOSNAP,       /* link-layer payload, with no SNAP header at the link layer */
+       OR_TRAN_IPV4,           /* transport-layer header, with IPv4 network layer */
+       OR_TRAN_IPV6            /* transport-layer header, with IPv6 network layer */
 };
 
-#ifdef INET6
-/*
- * As errors are handled by a longjmp, anything allocated must be freed
- * in the longjmp handler, so it must be reachable from that handler.
- * One thing that's allocated is the result of pcap_nametoaddrinfo();
- * it must be freed with freeaddrinfo().  This variable points to any
- * addrinfo structure that would need to be freed.
- */
-static struct addrinfo *ai;
-#endif
-
 /*
  * We divy out chunks of memory rather than call malloc each time so
  * we don't have to worry about leaking memory.  It's probably
@@ -204,100 +249,324 @@ static struct addrinfo *ai;
 #define NCHUNKS 16
 #define CHUNK0SIZE 1024
 struct chunk {
-       u_int n_left;
+       size_t n_left;
        void *m;
 };
 
-static struct chunk chunks[NCHUNKS];
-static int cur_chunk;
+/* Code generator state */
+
+struct _compiler_state {
+       jmp_buf top_ctx;
+       pcap_t *bpf_pcap;
+
+       struct icode ic;
+
+       int snaplen;
+
+       int linktype;
+       int prevlinktype;
+       int outermostlinktype;
+
+       bpf_u_int32 netmask;
+       int no_optimize;
 
-static void *newchunk(u_int);
-static void freechunks(void);
-static inline struct block *new_block(int);
-static inline struct slist *new_stmt(int);
-static struct block *gen_retblk(int);
-static inline void syntax(void);
+       /* Hack for handling VLAN and MPLS stacks. */
+       u_int label_stack_depth;
+       u_int vlan_stack_depth;
+
+       /* XXX */
+       u_int pcap_fddipad;
+
+#ifdef INET6
+       /*
+        * As errors are handled by a longjmp, anything allocated must
+        * be freed in the longjmp handler, so it must be reachable
+        * from that handler.
+        *
+        * One thing that's allocated is the result of pcap_nametoaddrinfo();
+        * it must be freed with freeaddrinfo().  This variable points to
+        * any addrinfo structure that would need to be freed.
+        */
+       struct addrinfo *ai;
+#endif
+
+       /*
+        * Various code constructs need to know the layout of the packet.
+        * These values give the necessary offsets from the beginning
+        * of the packet data.
+        */
+
+       /*
+        * Absolute offset of the beginning of the link-layer header.
+        */
+       bpf_abs_offset off_linkhdr;
+
+       /*
+        * If we're checking a link-layer header for a packet encapsulated
+        * in another protocol layer, this is the equivalent information
+        * for the previous layers' link-layer header from the beginning
+        * of the raw packet data.
+        */
+       bpf_abs_offset off_prevlinkhdr;
+
+       /*
+        * This is the equivalent information for the outermost layers'
+        * link-layer header.
+        */
+       bpf_abs_offset off_outermostlinkhdr;
+
+       /*
+        * Absolute offset of the beginning of the link-layer payload.
+        */
+       bpf_abs_offset off_linkpl;
+
+       /*
+        * "off_linktype" is the offset to information in the link-layer
+        * header giving the packet type. This is an absolute offset
+        * from the beginning of the packet.
+        *
+        * For Ethernet, it's the offset of the Ethernet type field; this
+        * means that it must have a value that skips VLAN tags.
+        *
+        * For link-layer types that always use 802.2 headers, it's the
+        * offset of the LLC header; this means that it must have a value
+        * that skips VLAN tags.
+        *
+        * For PPP, it's the offset of the PPP type field.
+        *
+        * For Cisco HDLC, it's the offset of the CHDLC type field.
+        *
+        * For BSD loopback, it's the offset of the AF_ value.
+        *
+        * For Linux cooked sockets, it's the offset of the type field.
+        *
+        * off_linktype.constant_part is set to OFFSET_NOT_SET for no
+        * encapsulation, in which case, IP is assumed.
+        */
+       bpf_abs_offset off_linktype;
+
+       /*
+        * TRUE if the link layer includes an ATM pseudo-header.
+        */
+       int is_atm;
+
+       /*
+        * TRUE if "geneve" appeared in the filter; it causes us to
+        * generate code that checks for a Geneve header and assume
+        * that later filters apply to the encapsulated payload.
+        */
+       int is_geneve;
+
+       /*
+        * These are offsets for the ATM pseudo-header.
+        */
+       u_int off_vpi;
+       u_int off_vci;
+       u_int off_proto;
+
+       /*
+        * These are offsets for the MTP2 fields.
+        */
+       u_int off_li;
+       u_int off_li_hsl;
+
+       /*
+        * These are offsets for the MTP3 fields.
+        */
+       u_int off_sio;
+       u_int off_opc;
+       u_int off_dpc;
+       u_int off_sls;
+
+       /*
+        * This is the offset of the first byte after the ATM pseudo_header,
+        * or -1 if there is no ATM pseudo-header.
+        */
+       u_int off_payload;
+
+       /*
+        * These are offsets to the beginning of the network-layer header.
+        * They are relative to the beginning of the link-layer payload
+        * (i.e., they don't include off_linkhdr.constant_part or
+        * off_linkpl.constant_part).
+        *
+        * If the link layer never uses 802.2 LLC:
+        *
+        *      "off_nl" and "off_nl_nosnap" are the same.
+        *
+        * If the link layer always uses 802.2 LLC:
+        *
+        *      "off_nl" is the offset if there's a SNAP header following
+        *      the 802.2 header;
+        *
+        *      "off_nl_nosnap" is the offset if there's no SNAP header.
+        *
+        * If the link layer is Ethernet:
+        *
+        *      "off_nl" is the offset if the packet is an Ethernet II packet
+        *      (we assume no 802.3+802.2+SNAP);
+        *
+        *      "off_nl_nosnap" is the offset if the packet is an 802.3 packet
+        *      with an 802.2 header following it.
+        */
+       u_int off_nl;
+       u_int off_nl_nosnap;
+
+       /*
+        * Here we handle simple allocation of the scratch registers.
+        * If too many registers are alloc'd, the allocator punts.
+        */
+       int regused[BPF_MEMWORDS];
+       int curreg;
+
+       /*
+        * Memory chunks.
+        */
+       struct chunk chunks[NCHUNKS];
+       int cur_chunk;
+};
+
+void
+bpf_syntax_error(compiler_state_t *cstate, const char *msg)
+{
+       bpf_error(cstate, "syntax error in filter expression: %s", msg);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+void
+bpf_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (cstate->bpf_pcap != NULL)
+               (void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
+                   PCAP_ERRBUF_SIZE, fmt, ap);
+       va_end(ap);
+       longjmp(cstate->top_ctx, 1);
+       /* NOTREACHED */
+}
+
+static void init_linktype(compiler_state_t *, pcap_t *);
+
+static void init_regs(compiler_state_t *);
+static int alloc_reg(compiler_state_t *);
+static void free_reg(compiler_state_t *, int);
+
+static void initchunks(compiler_state_t *cstate);
+static void *newchunk(compiler_state_t *cstate, size_t);
+static void freechunks(compiler_state_t *cstate);
+static inline struct block *new_block(compiler_state_t *cstate, int);
+static inline struct slist *new_stmt(compiler_state_t *cstate, int);
+static struct block *gen_retblk(compiler_state_t *cstate, int);
+static inline void syntax(compiler_state_t *cstate);
 
 static void backpatch(struct block *, struct block *);
 static void merge(struct block *, struct block *);
-static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
-    bpf_u_int32);
-static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
-static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
-    bpf_u_int32, bpf_u_int32, int, bpf_int32);
-static struct slist *gen_load_llrel(u_int, u_int);
-static struct slist *gen_load_macplrel(u_int, u_int);
-static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
-static struct slist *gen_loadx_iphdrlen(void);
-static struct block *gen_uncond(int);
-static inline struct block *gen_true(void);
-static inline struct block *gen_false(void);
-static struct block *gen_ether_linktype(int);
-static struct block *gen_ipnet_linktype(int);
-static struct block *gen_linux_sll_linktype(int);
-static struct slist *gen_load_prism_llprefixlen(void);
-static struct slist *gen_load_avs_llprefixlen(void);
-static struct slist *gen_load_radiotap_llprefixlen(void);
-static struct slist *gen_load_ppi_llprefixlen(void);
-static void insert_compute_vloffsets(struct block *);
-static struct slist *gen_llprefixlen(void);
-static struct slist *gen_off_macpl(void);
+static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, const u_char *);
+static struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
+    bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
+static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
+    u_int, u_int);
+static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
+    u_int);
+static struct slist *gen_loadx_iphdrlen(compiler_state_t *);
+static struct block *gen_uncond(compiler_state_t *, int);
+static inline struct block *gen_true(compiler_state_t *);
+static inline struct block *gen_false(compiler_state_t *);
+static struct block *gen_ether_linktype(compiler_state_t *, int);
+static struct block *gen_ipnet_linktype(compiler_state_t *, int);
+static struct block *gen_linux_sll_linktype(compiler_state_t *, int);
+static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
+static void insert_compute_vloffsets(compiler_state_t *, struct block *);
+static struct slist *gen_abs_offset_varpart(compiler_state_t *,
+    bpf_abs_offset *);
 static int ethertype_to_ppptype(int);
-static struct block *gen_linktype(int);
-static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
-static struct block *gen_llc_linktype(int);
-static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
+static struct block *gen_linktype(compiler_state_t *, int);
+static struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
+static struct block *gen_llc_linktype(compiler_state_t *, int);
+static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+    int, int, u_int, u_int);
 #ifdef INET6
-static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
+static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
+    struct in6_addr *, int, int, u_int, u_int);
 #endif
-static struct block *gen_ahostop(const u_char *, int);
-static struct block *gen_ehostop(const u_char *, int);
-static struct block *gen_fhostop(const u_char *, int);
-static struct block *gen_thostop(const u_char *, int);
-static struct block *gen_wlanhostop(const u_char *, int);
-static struct block *gen_ipfchostop(const u_char *, int);
-static struct block *gen_dnhostop(bpf_u_int32, int);
-static struct block *gen_mpls_linktype(int);
-static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
+static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
+static struct block *gen_mpls_linktype(compiler_state_t *, int);
+static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+    int, int, int);
 #ifdef INET6
-static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
+static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
+    struct in6_addr *, int, int, int);
 #endif
 #ifndef INET6
 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
 #endif
-static struct block *gen_ipfrag(void);
-static struct block *gen_portatom(int, bpf_int32);
-static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
-static struct block *gen_portatom6(int, bpf_int32);
-static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
-struct block *gen_portop(int, int, int);
-static struct block *gen_port(int, int, int);
-struct block *gen_portrangeop(int, int, int, int);
-static struct block *gen_portrange(int, int, int, int);
-struct block *gen_portop6(int, int, int);
-static struct block *gen_port6(int, int, int);
-struct block *gen_portrangeop6(int, int, int, int);
-static struct block *gen_portrange6(int, int, int, int);
-static int lookup_proto(const char *, int);
-static struct block *gen_protochain(int, int, int);
-static struct block *gen_proto(int, int, int);
-static struct slist *xfer_to_x(struct arth *);
-static struct slist *xfer_to_a(struct arth *);
-static struct block *gen_mac_multicast(int);
-static struct block *gen_len(int, int);
-static struct block *gen_check_802_11_data_frame(void);
-
-static struct block *gen_ppi_dlt_check(void);
-static struct block *gen_msg_abbrev(int type);
+static struct block *gen_ipfrag(compiler_state_t *);
+static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
+    bpf_int32);
+static struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
+    bpf_int32);
+struct block *gen_portop(compiler_state_t *, int, int, int);
+static struct block *gen_port(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange(compiler_state_t *, int, int, int, int);
+struct block *gen_portop6(compiler_state_t *, int, int, int);
+static struct block *gen_port6(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
+static int lookup_proto(compiler_state_t *, const char *, int);
+static struct block *gen_protochain(compiler_state_t *, int, int, int);
+static struct block *gen_proto(compiler_state_t *, int, int, int);
+static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
+static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
+static struct block *gen_mac_multicast(compiler_state_t *, int);
+static struct block *gen_len(compiler_state_t *, int, int);
+static struct block *gen_check_802_11_data_frame(compiler_state_t *);
+static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
+
+static struct block *gen_ppi_dlt_check(compiler_state_t *);
+static struct block *gen_msg_abbrev(compiler_state_t *, int type);
+
+static void
+initchunks(compiler_state_t *cstate)
+{
+       int i;
+
+       for (i = 0; i < NCHUNKS; i++) {
+               cstate->chunks[i].n_left = 0;
+               cstate->chunks[i].m = NULL;
+       }
+       cstate->cur_chunk = 0;
+}
 
 static void *
-newchunk(n)
-       u_int n;
+newchunk(compiler_state_t *cstate, size_t n)
 {
        struct chunk *cp;
        int k;
@@ -311,58 +580,53 @@ newchunk(n)
        n = ALIGN(n);
 #endif
 
-       cp = &chunks[cur_chunk];
+       cp = &cstate->chunks[cstate->cur_chunk];
        if (n > cp->n_left) {
-               ++cp, k = ++cur_chunk;
+               ++cp, k = ++cstate->cur_chunk;
                if (k >= NCHUNKS)
-                       bpf_error("out of memory");
+                       bpf_error(cstate, "out of memory");
                size = CHUNK0SIZE << k;
                cp->m = (void *)malloc(size);
                if (cp->m == NULL)
-                       bpf_error("out of memory");
+                       bpf_error(cstate, "out of memory");
                memset((char *)cp->m, 0, size);
                cp->n_left = size;
                if (n > size)
-                       bpf_error("out of memory");
+                       bpf_error(cstate, "out of memory");
        }
        cp->n_left -= n;
        return (void *)((char *)cp->m + cp->n_left);
 }
 
 static void
-freechunks()
+freechunks(compiler_state_t *cstate)
 {
        int i;
 
-       cur_chunk = 0;
        for (i = 0; i < NCHUNKS; ++i)
-               if (chunks[i].m != NULL) {
-                       free(chunks[i].m);
-                       chunks[i].m = NULL;
-               }
+               if (cstate->chunks[i].m != NULL)
+                       free(cstate->chunks[i].m);
 }
 
 /*
  * A strdup whose allocations are freed after code generation is over.
  */
 char *
-sdup(s)
-       register const char *s;
+sdup(compiler_state_t *cstate, const char *s)
 {
-       int n = strlen(s) + 1;
-       char *cp = newchunk(n);
+       size_t n = strlen(s) + 1;
+       char *cp = newchunk(cstate, n);
 
        strlcpy(cp, s, n);
        return (cp);
 }
 
 static inline struct block *
-new_block(code)
-       int code;
+new_block(compiler_state_t *cstate, int code)
 {
        struct block *p;
 
-       p = (struct block *)newchunk(sizeof(*p));
+       p = (struct block *)newchunk(cstate, sizeof(*p));
        p->s.code = code;
        p->head = p;
 
@@ -370,126 +634,129 @@ new_block(code)
 }
 
 static inline struct slist *
-new_stmt(code)
-       int code;
+new_stmt(compiler_state_t *cstate, int code)
 {
        struct slist *p;
 
-       p = (struct slist *)newchunk(sizeof(*p));
+       p = (struct slist *)newchunk(cstate, sizeof(*p));
        p->s.code = code;
 
        return p;
 }
 
 static struct block *
-gen_retblk(v)
-       int v;
+gen_retblk(compiler_state_t *cstate, int v)
 {
-       struct block *b = new_block(BPF_RET|BPF_K);
+       struct block *b = new_block(cstate, BPF_RET|BPF_K);
 
        b->s.k = v;
        return b;
 }
 
 static inline void
-syntax()
-{
-       bpf_error("syntax error in filter expression");
-}
-
-static bpf_u_int32 netmask;
-static int snaplen;
-int no_optimize;
-#ifdef WIN32
-static int
-pcap_compile_unsafe(pcap_t *p, struct bpf_program *program,
-            const char *buf, int optimize, bpf_u_int32 mask);
-
-int
-pcap_compile(pcap_t *p, struct bpf_program *program,
-            const char *buf, int optimize, bpf_u_int32 mask)
+syntax(compiler_state_t *cstate)
 {
-       int result;
-
-       EnterCriticalSection(&g_PcapCompileCriticalSection);
-
-       result = pcap_compile_unsafe(p, program, buf, optimize, mask);
-
-       LeaveCriticalSection(&g_PcapCompileCriticalSection);
-       
-       return result;
+       bpf_error(cstate, "syntax error in filter expression");
 }
 
-static int
-pcap_compile_unsafe(pcap_t *p, struct bpf_program *program,
-            const char *buf, int optimize, bpf_u_int32 mask)
-#else /* WIN32 */
 int
 pcap_compile(pcap_t *p, struct bpf_program *program,
             const char *buf, int optimize, bpf_u_int32 mask)
-#endif /* WIN32 */
 {
-       extern int n_errors;
+       compiler_state_t cstate;
        const char * volatile xbuf = buf;
+       yyscan_t scanner = NULL;
+       YY_BUFFER_STATE in_buffer = NULL;
        u_int len;
+       int  rc;
+
+#ifdef _WIN32
+       static int done = 0;
+
+       if (!done)
+               pcap_wsockinit();
+       done = 1;
+#endif
 
        /*
         * If this pcap_t hasn't been activated, it doesn't have a
         * link-layer type, so we can't use it.
         */
        if (!p->activated) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                    "not-yet-activated pcap_t passed to pcap_compile");
-               return (-1);
+               rc = -1;
+               goto quit;
        }
-       no_optimize = 0;
-       n_errors = 0;
-       root = NULL;
-       bpf_pcap = p;
-       init_regs();
-       if (setjmp(top_ctx)) {
+       initchunks(&cstate);
+       cstate.no_optimize = 0;
+       cstate.ai = NULL;
+       cstate.ic.root = NULL;
+       cstate.ic.cur_mark = 0;
+       cstate.bpf_pcap = p;
+       init_regs(&cstate);
+
+       if (setjmp(cstate.top_ctx)) {
 #ifdef INET6
-               if (ai != NULL) {
-                       freeaddrinfo(ai);
-                       ai = NULL;
-               }
+               if (cstate.ai != NULL)
+                       freeaddrinfo(cstate.ai);
 #endif
-               lex_cleanup();
-               freechunks();
-               return (-1);
+               rc = -1;
+               goto quit;
        }
 
-       netmask = mask;
+       cstate.netmask = mask;
 
-       snaplen = pcap_snapshot(p);
-       if (snaplen == 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+       cstate.snaplen = pcap_snapshot(p);
+       if (cstate.snaplen == 0) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                         "snaplen of 0 rejects all packets");
-               return -1;
+               rc = -1;
+               goto quit;
        }
 
-       lex_init(xbuf ? xbuf : "");
-       init_linktype(p);
-       (void)pcap_parse();
+       if (pcap_lex_init(&scanner) != 0)
+               bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
+       in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
+
+       /*
+        * Associate the compiler state with the lexical analyzer
+        * state.
+        */
+       pcap_set_extra(&cstate, scanner);
 
-       if (n_errors)
-               syntax();
+       init_linktype(&cstate, p);
+       (void)pcap_parse(scanner, &cstate);
 
-       if (root == NULL)
-               root = gen_retblk(snaplen);
+       if (cstate.ic.root == NULL)
+               cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
 
-       if (optimize && !no_optimize) {
-               bpf_optimize(&root);
-               if (root == NULL ||
-                   (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
-                       bpf_error("expression rejects all packets");
+       if (optimize && !cstate.no_optimize) {
+               bpf_optimize(&cstate, &cstate.ic);
+               if (cstate.ic.root == NULL ||
+                   (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0))
+                       bpf_error(&cstate, "expression rejects all packets");
        }
-       program->bf_insns = icode_to_fcode(root, &len);
+       program->bf_insns = icode_to_fcode(&cstate, &cstate.ic, cstate.ic.root, &len);
        program->bf_len = len;
 
-       lex_cleanup();
-       freechunks();
-       return (0);
+       rc = 0;  /* We're all okay */
+
+quit:
+       /*
+        * Clean up everything for the lexical analyzer.
+        */
+       if (in_buffer != NULL)
+               pcap__delete_buffer(in_buffer, scanner);
+       if (scanner != NULL)
+               pcap_lex_destroy(scanner);
+
+       /*
+        * Clean up our own allocated memory.
+        */
+       freechunks(&cstate);
+
+       return (rc);
 }
 
 /*
@@ -569,8 +836,7 @@ merge(b0, b1)
 }
 
 void
-finish_parse(p)
-       struct block *p;
+finish_parse(compiler_state_t *cstate, struct block *p)
 {
        struct block *ppi_dlt_check;
 
@@ -593,20 +859,29 @@ finish_parse(p)
         * for tests that fail early, and it's not clear that's
         * worth the effort.
         */
-       insert_compute_vloffsets(p->head);
-       
+       insert_compute_vloffsets(cstate, p->head);
+
        /*
         * For DLT_PPI captures, generate a check of the per-packet
         * DLT value to make sure it's DLT_IEEE802_11.
+        *
+        * XXX - TurboCap cards use DLT_PPI for Ethernet.
+        * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
+        * with appropriate Ethernet information and use that rather
+        * than using something such as DLT_PPI where you don't know
+        * the link-layer header type until runtime, which, in the
+        * general case, would force us to generate both Ethernet *and*
+        * 802.11 code (*and* anything else for which PPI is used)
+        * and choose between them early in the BPF program?
         */
-       ppi_dlt_check = gen_ppi_dlt_check();
+       ppi_dlt_check = gen_ppi_dlt_check(cstate);
        if (ppi_dlt_check != NULL)
                gen_and(ppi_dlt_check, p);
 
-       backpatch(p, gen_retblk(snaplen));
+       backpatch(p, gen_retblk(cstate, cstate->snaplen));
        p->sense = !p->sense;
-       backpatch(p, gen_retblk(0));
-       root = p->head;
+       backpatch(p, gen_retblk(cstate, 0));
+       cstate->ic.root = p->head;
 }
 
 void
@@ -640,65 +915,50 @@ gen_not(b)
 }
 
 static struct block *
-gen_cmp(offrel, offset, size, v)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
+gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-       return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
+       return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
 }
 
 static struct block *
-gen_cmp_gt(offrel, offset, size, v)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
+gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-       return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
+       return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
 }
 
 static struct block *
-gen_cmp_ge(offrel, offset, size, v)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
+gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-       return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
+       return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
 }
 
 static struct block *
-gen_cmp_lt(offrel, offset, size, v)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
+gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-       return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
+       return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
 }
 
 static struct block *
-gen_cmp_le(offrel, offset, size, v)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
+gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-       return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
+       return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
 }
 
 static struct block *
-gen_mcmp(offrel, offset, size, v, mask)
-       enum e_offrel offrel;
-       u_int offset, size;
-       bpf_int32 v;
-       bpf_u_int32 mask;
+gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v, bpf_u_int32 mask)
 {
-       return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
+       return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
 }
 
 static struct block *
-gen_bcmp(offrel, offset, size, v)
-       enum e_offrel offrel;
-       register u_int offset, size;
-       register const u_char *v;
+gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, const u_char *v)
 {
        register struct block *b, *tmp;
 
@@ -708,7 +968,7 @@ gen_bcmp(offrel, offset, size, v)
                bpf_int32 w = ((bpf_int32)p[0] << 24) |
                    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
 
-               tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
+               tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;
@@ -718,14 +978,14 @@ gen_bcmp(offrel, offset, size, v)
                register const u_char *p = &v[size - 2];
                bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
 
-               tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
+               tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;
                size -= 2;
        }
        if (size > 0) {
-               tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
+               tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;
@@ -740,24 +1000,22 @@ gen_bcmp(offrel, offset, size, v)
  * should test the opposite of "jtype".
  */
 static struct block *
-gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
-       enum e_offrel offrel;
-       bpf_int32 v;
-       bpf_u_int32 offset, size, mask, jtype;
-       int reverse;
+gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
+    bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
+    bpf_int32 v)
 {
        struct slist *s, *s2;
        struct block *b;
 
-       s = gen_load_a(offrel, offset, size);
+       s = gen_load_a(cstate, offrel, offset, size);
 
        if (mask != 0xffffffff) {
-               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
                s2->s.k = mask;
                sappend(s, s2);
        }
 
-       b = new_block(JMP(jtype));
+       b = new_block(cstate, JMP(jtype));
        b->stmts = s;
        b->s.k = v;
        if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
@@ -765,294 +1023,152 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
        return b;
 }
 
-/*
- * Various code constructs need to know the layout of the data link
- * layer.  These variables give the necessary offsets from the beginning
- * of the packet data.
- */
-
-/*
- * This is the offset of the beginning of the link-layer header from
- * the beginning of the raw packet data.
- *
- * It's usually 0, except for 802.11 with a fixed-length radio header.
- * (For 802.11 with a variable-length radio header, we have to generate
- * code to compute that offset; off_ll is 0 in that case.)
- */
-static u_int off_ll;
-
-/*
- * If there's a variable-length header preceding the link-layer header,
- * "reg_off_ll" is the register number for a register containing the
- * length of that header, and therefore the offset of the link-layer
- * header from the beginning of the raw packet data.  Otherwise,
- * "reg_off_ll" is -1.
- */
-static int reg_off_ll;
-
-/*
- * This is the offset of the beginning of the MAC-layer header from
- * the beginning of the link-layer header.
- * It's usually 0, except for ATM LANE, where it's the offset, relative
- * to the beginning of the raw packet data, of the Ethernet header, and
- * for Ethernet with various additional information.
- */
-static u_int off_mac;
-
-/*
- * This is the offset of the beginning of the MAC-layer payload,
- * from the beginning of the raw packet data.
- *
- * I.e., it's the sum of the length of the link-layer header (without,
- * for example, any 802.2 LLC header, so it's the MAC-layer
- * portion of that header), plus any prefix preceding the
- * link-layer header.
- */
-static u_int off_macpl;
-
-/*
- * This is 1 if the offset of the beginning of the MAC-layer payload
- * from the beginning of the link-layer header is variable-length.
- */
-static int off_macpl_is_variable;
-
-/*
- * If the link layer has variable_length headers, "reg_off_macpl"
- * is the register number for a register containing the length of the
- * link-layer header plus the length of any variable-length header
- * preceding the link-layer header.  Otherwise, "reg_off_macpl"
- * is -1.
- */
-static int reg_off_macpl;
-
-/*
- * "off_linktype" is the offset to information in the link-layer header
- * giving the packet type.  This offset is relative to the beginning
- * of the link-layer header (i.e., it doesn't include off_ll).
- *
- * For Ethernet, it's the offset of the Ethernet type field.
- *
- * For link-layer types that always use 802.2 headers, it's the
- * offset of the LLC header.
- *
- * For PPP, it's the offset of the PPP type field.
- *
- * For Cisco HDLC, it's the offset of the CHDLC type field.
- *
- * For BSD loopback, it's the offset of the AF_ value.
- *
- * For Linux cooked sockets, it's the offset of the type field.
- *
- * It's set to -1 for no encapsulation, in which case, IP is assumed.
- */
-static u_int off_linktype;
-
-/*
- * TRUE if "pppoes" appeared in the filter; it causes link-layer type
- * checks to check the PPP header, assumed to follow a LAN-style link-
- * layer header and a PPPoE session header.
- */
-static int is_pppoes = 0;
-
-/*
- * TRUE if the link layer includes an ATM pseudo-header.
- */
-static int is_atm = 0;
-
-/*
- * TRUE if "lane" appeared in the filter; it causes us to generate
- * code that assumes LANE rather than LLC-encapsulated traffic in SunATM.
- */
-static int is_lane = 0;
-
-/*
- * These are offsets for the ATM pseudo-header.
- */
-static u_int off_vpi;
-static u_int off_vci;
-static u_int off_proto;
-
-/*
- * These are offsets for the MTP2 fields.
- */
-static u_int off_li;
+static void
+init_linktype(compiler_state_t *cstate, pcap_t *p)
+{
+       cstate->pcap_fddipad = p->fddipad;
 
-/*
* These are offsets for the MTP3 fields.
- */
-static u_int off_sio;
-static u_int off_opc;
-static u_int off_dpc;
-static u_int off_sls;
+       /*
       * We start out with only one link-layer header.
       */
+       cstate->outermostlinktype = pcap_datalink(p);
+       cstate->off_outermostlinkhdr.constant_part = 0;
+       cstate->off_outermostlinkhdr.is_variable = 0;
+       cstate->off_outermostlinkhdr.reg = -1;
 
-/*
- * This is the offset of the first byte after the ATM pseudo_header,
- * or -1 if there is no ATM pseudo-header.
- */
-static u_int off_payload;
+       cstate->prevlinktype = cstate->outermostlinktype;
+       cstate->off_prevlinkhdr.constant_part = 0;
+       cstate->off_prevlinkhdr.is_variable = 0;
+       cstate->off_prevlinkhdr.reg = -1;
 
-/*
- * These are offsets to the beginning of the network-layer header.
- * They are relative to the beginning of the MAC-layer payload (i.e.,
- * they don't include off_ll or off_macpl).
- *
- * If the link layer never uses 802.2 LLC:
- *
- *     "off_nl" and "off_nl_nosnap" are the same.
- *
- * If the link layer always uses 802.2 LLC:
- *
- *     "off_nl" is the offset if there's a SNAP header following
- *     the 802.2 header;
- *
- *     "off_nl_nosnap" is the offset if there's no SNAP header.
- *
- * If the link layer is Ethernet:
- *
- *     "off_nl" is the offset if the packet is an Ethernet II packet
- *     (we assume no 802.3+802.2+SNAP);
- *
- *     "off_nl_nosnap" is the offset if the packet is an 802.3 packet
- *     with an 802.2 header following it.
- */
-static u_int off_nl;
-static u_int off_nl_nosnap;
+       cstate->linktype = cstate->outermostlinktype;
+       cstate->off_linkhdr.constant_part = 0;
+       cstate->off_linkhdr.is_variable = 0;
+       cstate->off_linkhdr.reg = -1;
 
-static int linktype;
+       /*
+        * XXX
+        */
+       cstate->off_linkpl.constant_part = 0;
+       cstate->off_linkpl.is_variable = 0;
+       cstate->off_linkpl.reg = -1;
 
-static void
-init_linktype(p)
-       pcap_t *p;
-{
-       linktype = pcap_datalink(p);
-#ifdef PCAP_FDDIPAD
-       pcap_fddipad = p->fddipad;
-#endif
+       cstate->off_linktype.constant_part = 0;
+       cstate->off_linktype.is_variable = 0;
+       cstate->off_linktype.reg = -1;
 
        /*
         * Assume it's not raw ATM with a pseudo-header, for now.
         */
-       off_mac = 0;
-       is_atm = 0;
-       is_lane = 0;
-       off_vpi = -1;
-       off_vci = -1;
-       off_proto = -1;
-       off_payload = -1;
+       cstate->is_atm = 0;
+       cstate->off_vpi = -1;
+       cstate->off_vci = -1;
+       cstate->off_proto = -1;
+       cstate->off_payload = -1;
 
        /*
-        * And that we're not doing PPPoE.
+        * And not Geneve.
         */
-       is_pppoes = 0;
+       cstate->is_geneve = 0;
 
        /*
         * And assume we're not doing SS7.
         */
-       off_li = -1;
-       off_sio = -1;
-       off_opc = -1;
-       off_dpc = -1;
-       off_sls = -1;
-
-       /*
-        * Also assume it's not 802.11.
-        */
-       off_ll = 0;
-       off_macpl = 0;
-       off_macpl_is_variable = 0;
+       cstate->off_li = -1;
+       cstate->off_li_hsl = -1;
+       cstate->off_sio = -1;
+       cstate->off_opc = -1;
+       cstate->off_dpc = -1;
+       cstate->off_sls = -1;
 
-       orig_linktype = -1;
-       orig_nl = -1;
-        label_stack_depth = 0;
+       cstate->label_stack_depth = 0;
+       cstate->vlan_stack_depth = 0;
 
-       reg_off_ll = -1;
-       reg_off_macpl = -1;
-
-       switch (linktype) {
+       switch (cstate->linktype) {
 
        case DLT_ARCNET:
-               off_linktype = 2;
-               off_macpl = 6;
-               off_nl = 0;             /* XXX in reality, variable! */
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 2;
+               cstate->off_linkpl.constant_part = 6;
+               cstate->off_nl = 0;     /* XXX in reality, variable! */
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_ARCNET_LINUX:
-               off_linktype = 4;
-               off_macpl = 8;
-               off_nl = 0;             /* XXX in reality, variable! */
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 4;
+               cstate->off_linkpl.constant_part = 8;
+               cstate->off_nl = 0;             /* XXX in reality, variable! */
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_EN10MB:
-               off_linktype = 12;
-               off_macpl = 14;         /* Ethernet header length */
-               off_nl = 0;             /* Ethernet II */
-               off_nl_nosnap = 3;      /* 802.3+802.2 */
-               return;
+               cstate->off_linktype.constant_part = 12;
+               cstate->off_linkpl.constant_part = 14;  /* Ethernet header length */
+               cstate->off_nl = 0;             /* Ethernet II */
+               cstate->off_nl_nosnap = 3;      /* 802.3+802.2 */
+               break;
 
        case DLT_SLIP:
                /*
                 * SLIP doesn't have a link level type.  The 16 byte
                 * header is hacked into our SLIP driver.
                 */
-               off_linktype = -1;
-               off_macpl = 16;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 16;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_SLIP_BSDOS:
                /* XXX this may be the same as the DLT_PPP_BSDOS case */
-               off_linktype = -1;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
                /* XXX end */
-               off_macpl = 24;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linkpl.constant_part = 24;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_NULL:
        case DLT_LOOP:
-               off_linktype = 0;
-               off_macpl = 4;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 0;
+               cstate->off_linkpl.constant_part = 4;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_ENC:
-               off_linktype = 0;
-               off_macpl = 12;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 0;
+               cstate->off_linkpl.constant_part = 12;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_PPP:
        case DLT_PPP_PPPD:
        case DLT_C_HDLC:                /* BSD/OS Cisco HDLC */
        case DLT_PPP_SERIAL:            /* NetBSD sync/async serial PPP */
-               off_linktype = 2;
-               off_macpl = 4;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 2; /* skip HDLC-like framing */
+               cstate->off_linkpl.constant_part = 4;   /* skip HDLC-like framing and protocol field */
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_PPP_ETHER:
                /*
                 * This does no include the Ethernet header, and
                 * only covers session state.
                 */
-               off_linktype = 6;
-               off_macpl = 8;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 6;
+               cstate->off_linkpl.constant_part = 8;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_PPP_BSDOS:
-               off_linktype = 5;
-               off_macpl = 24;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 5;
+               cstate->off_linkpl.constant_part = 24;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_FDDI:
                /*
@@ -1063,17 +1179,13 @@ init_linktype(p)
                 * is being used and pick out the encapsulated Ethernet type.
                 * XXX - should we generate code to check for SNAP?
                 */
-               off_linktype = 13;
-#ifdef PCAP_FDDIPAD
-               off_linktype += pcap_fddipad;
-#endif
-               off_macpl = 13;         /* FDDI MAC header length */
-#ifdef PCAP_FDDIPAD
-               off_macpl += pcap_fddipad;
-#endif
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 13;
+               cstate->off_linktype.constant_part += cstate->pcap_fddipad;
+               cstate->off_linkpl.constant_part = 13;  /* FDDI MAC header length */
+               cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_IEEE802:
                /*
@@ -1099,19 +1211,24 @@ init_linktype(p)
                 * the 16-bit value at an offset of 14 (shifted right
                 * 8 - figure out which byte that is).
                 */
-               off_linktype = 14;
-               off_macpl = 14;         /* Token Ring MAC header length */
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 14;
+               cstate->off_linkpl.constant_part = 14;  /* Token Ring MAC header length */
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
-       case DLT_IEEE802_11:
        case DLT_PRISM_HEADER:
        case DLT_IEEE802_11_RADIO_AVS:
        case DLT_IEEE802_11_RADIO:
+               cstate->off_linkhdr.is_variable = 1;
+               /* Fall through, 802.11 doesn't have a variable link
+                * prefix but is otherwise the same. */
+
+       case DLT_IEEE802_11:
                /*
                 * 802.11 doesn't really have a link-level type field.
-                * We set "off_linktype" to the offset of the LLC header.
+                * We set "off_linktype.constant_part" to the offset of
+                * the LLC header.
                 *
                 * To check for Ethernet types, we assume that SSAP = SNAP
                 * is being used and pick out the encapsulated Ethernet type.
@@ -1126,15 +1243,15 @@ init_linktype(p)
                 * header or an AVS header, so, in practice, it's
                 * variable-length.
                 */
-               off_linktype = 24;
-               off_macpl = 0;          /* link-layer header is variable-length */
-               off_macpl_is_variable = 1;
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 24;
+               cstate->off_linkpl.constant_part = 0;   /* link-layer header is variable-length */
+               cstate->off_linkpl.is_variable = 1;
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_PPI:
-               /* 
+               /*
                 * At the moment we treat PPI the same way that we treat
                 * normal Radiotap encoded packets. The difference is in
                 * the function that generates the code at the beginning
@@ -1143,12 +1260,13 @@ init_linktype(p)
                 * the encapsulated DLT should be DLT_IEEE802_11) we
                 * generate code to check for this too.
                 */
-               off_linktype = 24;
-               off_macpl = 0;          /* link-layer header is variable-length */
-               off_macpl_is_variable = 1;
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 24;
+               cstate->off_linkpl.constant_part = 0;   /* link-layer header is variable-length */
+               cstate->off_linkpl.is_variable = 1;
+               cstate->off_linkhdr.is_variable = 1;
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_ATM_RFC1483:
        case DLT_ATM_CLIP:      /* Linux ATM defines this */
@@ -1163,44 +1281,43 @@ init_linktype(p)
                 * or "pppoa and tcp port 80" and have it check for
                 * PPPo{A,E} and a PPP protocol of IP and....
                 */
-               off_linktype = 0;
-               off_macpl = 0;          /* packet begins with LLC header */
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 0;
+               cstate->off_linkpl.constant_part = 0;   /* packet begins with LLC header */
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_SUNATM:
                /*
                 * Full Frontal ATM; you get AALn PDUs with an ATM
                 * pseudo-header.
                 */
-               is_atm = 1;
-               off_vpi = SUNATM_VPI_POS;
-               off_vci = SUNATM_VCI_POS;
-               off_proto = PROTO_POS;
-               off_mac = -1;   /* assume LLC-encapsulated, so no MAC-layer header */
-               off_payload = SUNATM_PKT_BEGIN_POS;
-               off_linktype = off_payload;
-               off_macpl = off_payload;        /* if LLC-encapsulated */
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->is_atm = 1;
+               cstate->off_vpi = SUNATM_VPI_POS;
+               cstate->off_vci = SUNATM_VCI_POS;
+               cstate->off_proto = PROTO_POS;
+               cstate->off_payload = SUNATM_PKT_BEGIN_POS;
+               cstate->off_linktype.constant_part = cstate->off_payload;
+               cstate->off_linkpl.constant_part = cstate->off_payload; /* if LLC-encapsulated */
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_RAW:
        case DLT_IPV4:
        case DLT_IPV6:
-               off_linktype = -1;
-               off_macpl = 0;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 0;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_LINUX_SLL:     /* fake header for Linux cooked socket */
-               off_linktype = 14;
-               off_macpl = 16;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 14;
+               cstate->off_linkpl.constant_part = 16;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_LTALK:
                /*
@@ -1208,11 +1325,11 @@ init_linktype(p)
                 * but really it just indicates whether there is a "short" or
                 * "long" DDP packet following.
                 */
-               off_linktype = -1;
-               off_macpl = 0;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 0;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_IP_OVER_FC:
                /*
@@ -1225,22 +1342,22 @@ init_linktype(p)
                 * XXX - should we generate code to check for SNAP? RFC
                 * 2625 says SNAP should be used.
                 */
-               off_linktype = 16;
-               off_macpl = 16;
-               off_nl = 8;             /* 802.2+SNAP */
-               off_nl_nosnap = 3;      /* 802.2 */
-               return;
+               cstate->off_linktype.constant_part = 16;
+               cstate->off_linkpl.constant_part = 16;
+               cstate->off_nl = 8;             /* 802.2+SNAP */
+               cstate->off_nl_nosnap = 3;      /* 802.2 */
+               break;
 
        case DLT_FRELAY:
                /*
                 * XXX - we should set this to handle SNAP-encapsulated
                 * frames (NLPID of 0x80).
                 */
-               off_linktype = -1;
-               off_macpl = 0;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 0;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
                 /*
                  * the only BPF-interesting FRF.16 frames are non-control frames;
@@ -1248,33 +1365,33 @@ init_linktype(p)
                  * so lets start with offset 4 for now and increments later on (FIXME);
                  */
        case DLT_MFR:
-               off_linktype = -1;
-               off_macpl = 0;
-               off_nl = 4;
-               off_nl_nosnap = 0;      /* XXX - for now -> no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 0;
+               cstate->off_nl = 4;
+               cstate->off_nl_nosnap = 0;      /* XXX - for now -> no 802.2 LLC */
+               break;
 
        case DLT_APPLE_IP_OVER_IEEE1394:
-               off_linktype = 16;
-               off_macpl = 18;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 16;
+               cstate->off_linkpl.constant_part = 18;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_SYMANTEC_FIREWALL:
-               off_linktype = 6;
-               off_macpl = 44;
-               off_nl = 0;             /* Ethernet II */
-               off_nl_nosnap = 0;      /* XXX - what does it do with 802.3 packets? */
-               return;
+               cstate->off_linktype.constant_part = 6;
+               cstate->off_linkpl.constant_part = 44;
+               cstate->off_nl = 0;             /* Ethernet II */
+               cstate->off_nl_nosnap = 0;      /* XXX - what does it do with 802.3 packets? */
+               break;
 
 #ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
-               off_linktype = 0;
-               off_macpl = PFLOG_HDRLEN;
-               off_nl = 0;
-               off_nl_nosnap = 0;      /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 0;
+               cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 #endif
 
         case DLT_JUNIPER_MFR:
@@ -1283,279 +1400,244 @@ init_linktype(p)
         case DLT_JUNIPER_PPP:
         case DLT_JUNIPER_CHDLC:
         case DLT_JUNIPER_FRELAY:
-                off_linktype = 4;
-               off_macpl = 4;
-               off_nl = 0;
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-                return;
+               cstate->off_linktype.constant_part = 4;
+               cstate->off_linkpl.constant_part = 4;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+                break;
 
        case DLT_JUNIPER_ATM1:
-               off_linktype = 4;       /* in reality variable between 4-8 */
-               off_macpl = 4;  /* in reality variable between 4-8 */
-               off_nl = 0;
-               off_nl_nosnap = 10;
-               return;
+               cstate->off_linktype.constant_part = 4;         /* in reality variable between 4-8 */
+               cstate->off_linkpl.constant_part = 4;   /* in reality variable between 4-8 */
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 10;
+               break;
 
        case DLT_JUNIPER_ATM2:
-               off_linktype = 8;       /* in reality variable between 8-12 */
-               off_macpl = 8;  /* in reality variable between 8-12 */
-               off_nl = 0;
-               off_nl_nosnap = 10;
-               return;
+               cstate->off_linktype.constant_part = 8;         /* in reality variable between 8-12 */
+               cstate->off_linkpl.constant_part = 8;   /* in reality variable between 8-12 */
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 10;
+               break;
 
                /* frames captured on a Juniper PPPoE service PIC
                 * contain raw ethernet frames */
        case DLT_JUNIPER_PPPOE:
         case DLT_JUNIPER_ETHER:
-               off_macpl = 14;
-               off_linktype = 16;
-               off_nl = 18;            /* Ethernet II */
-               off_nl_nosnap = 21;     /* 802.3+802.2 */
-               return;
+               cstate->off_linkpl.constant_part = 14;
+               cstate->off_linktype.constant_part = 16;
+               cstate->off_nl = 18;            /* Ethernet II */
+               cstate->off_nl_nosnap = 21;     /* 802.3+802.2 */
+               break;
 
        case DLT_JUNIPER_PPPOE_ATM:
-               off_linktype = 4;
-               off_macpl = 6;
-               off_nl = 0;
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 4;
+               cstate->off_linkpl.constant_part = 6;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
 
        case DLT_JUNIPER_GGSN:
-               off_linktype = 6;
-               off_macpl = 12;
-               off_nl = 0;
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 6;
+               cstate->off_linkpl.constant_part = 12;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
 
        case DLT_JUNIPER_ES:
-               off_linktype = 6;
-               off_macpl = -1;         /* not really a network layer but raw IP addresses */
-               off_nl = -1;            /* not really a network layer but raw IP addresses */
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 6;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;      /* not really a network layer but raw IP addresses */
+               cstate->off_nl = -1;            /* not really a network layer but raw IP addresses */
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
 
        case DLT_JUNIPER_MONITOR:
-               off_linktype = 12;
-               off_macpl = 12;
-               off_nl = 0;             /* raw IP/IP6 header */
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 12;
+               cstate->off_linkpl.constant_part = 12;
+               cstate->off_nl = 0;             /* raw IP/IP6 header */
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
+
+       case DLT_BACNET_MS_TP:
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_JUNIPER_SERVICES:
-               off_linktype = 12;
-               off_macpl = -1;         /* L3 proto location dep. on cookie type */
-               off_nl = -1;            /* L3 proto location dep. on cookie type */
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               return;
+               cstate->off_linktype.constant_part = 12;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;      /* L3 proto location dep. on cookie type */
+               cstate->off_nl = -1;            /* L3 proto location dep. on cookie type */
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
 
        case DLT_JUNIPER_VP:
-               off_linktype = 18;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_linktype.constant_part = 18;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_JUNIPER_ST:
-               off_linktype = 18;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_linktype.constant_part = 18;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_JUNIPER_ISM:
-               off_linktype = 8;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_linktype.constant_part = 8;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_JUNIPER_VS:
        case DLT_JUNIPER_SRX_E2E:
        case DLT_JUNIPER_FIBRECHANNEL:
        case DLT_JUNIPER_ATM_CEMIC:
-               off_linktype = 8;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_linktype.constant_part = 8;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_MTP2:
-               off_li = 2;
-               off_sio = 3;
-               off_opc = 4;
-               off_dpc = 4;
-               off_sls = 7;
-               off_linktype = -1;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_li = 2;
+               cstate->off_li_hsl = 4;
+               cstate->off_sio = 3;
+               cstate->off_opc = 4;
+               cstate->off_dpc = 4;
+               cstate->off_sls = 7;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_MTP2_WITH_PHDR:
-               off_li = 6;
-               off_sio = 7;
-               off_opc = 8;
-               off_dpc = 8;
-               off_sls = 11;
-               off_linktype = -1;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_li = 6;
+               cstate->off_li_hsl = 8;
+               cstate->off_sio = 7;
+               cstate->off_opc = 8;
+               cstate->off_dpc = 8;
+               cstate->off_sls = 11;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_ERF:
-               off_li = 22;
-               off_sio = 23;
-               off_opc = 24;
-               off_dpc = 24;
-               off_sls = 27;
-               off_linktype = -1;
-               off_macpl = -1;
-               off_nl = -1;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_li = 22;
+               cstate->off_li_hsl = 24;
+               cstate->off_sio = 23;
+               cstate->off_opc = 24;
+               cstate->off_dpc = 24;
+               cstate->off_sls = 27;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_PFSYNC:
-               off_linktype = -1;
-               off_macpl = 4;
-               off_nl = 0;
-               off_nl_nosnap = 0;
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+               cstate->off_linkpl.constant_part = 4;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;
+               break;
 
        case DLT_AX25_KISS:
                /*
                 * Currently, only raw "link[N:M]" filtering is supported.
                 */
-               off_linktype = -1;      /* variable, min 15, max 71 steps of 7 */
-               off_macpl = -1;
-               off_nl = -1;            /* variable, min 16, max 71 steps of 7 */
-               off_nl_nosnap = -1;     /* no 802.2 LLC */
-               off_mac = 1;            /* step over the kiss length byte */
-               return;
+               cstate->off_linktype.constant_part = OFFSET_NOT_SET;    /* variable, min 15, max 71 steps of 7 */
+               cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+               cstate->off_nl = -1;            /* variable, min 16, max 71 steps of 7 */
+               cstate->off_nl_nosnap = -1;     /* no 802.2 LLC */
+               break;
 
        case DLT_IPNET:
-               off_linktype = 1;
-               off_macpl = 24;         /* ipnet header length */
-               off_nl = 0;
-               off_nl_nosnap = -1;
-               return;
+               cstate->off_linktype.constant_part = 1;
+               cstate->off_linkpl.constant_part = 24;  /* ipnet header length */
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = -1;
+               break;
 
        case DLT_NETANALYZER:
-               off_mac = 4;            /* MAC header is past 4-byte pseudo-header */
-               off_linktype = 16;      /* includes 4-byte pseudo-header */
-               off_macpl = 18;         /* pseudo-header+Ethernet header length */
-               off_nl = 0;             /* Ethernet II */
-               off_nl_nosnap = 3;      /* 802.3+802.2 */
-               return;
+               cstate->off_linkhdr.constant_part = 4;  /* Ethernet header is past 4-byte pseudo-header */
+               cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+               cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;      /* pseudo-header+Ethernet header length */
+               cstate->off_nl = 0;             /* Ethernet II */
+               cstate->off_nl_nosnap = 3;      /* 802.3+802.2 */
+               break;
 
        case DLT_NETANALYZER_TRANSPARENT:
-               off_mac = 12;           /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
-               off_linktype = 24;      /* includes 4-byte pseudo-header+preamble+SFD */
-               off_macpl = 26;         /* pseudo-header+preamble+SFD+Ethernet header length */
-               off_nl = 0;             /* Ethernet II */
-               off_nl_nosnap = 3;      /* 802.3+802.2 */
-               return;
+               cstate->off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
+               cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+               cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;      /* pseudo-header+preamble+SFD+Ethernet header length */
+               cstate->off_nl = 0;             /* Ethernet II */
+               cstate->off_nl_nosnap = 3;      /* 802.3+802.2 */
+               break;
 
        default:
                /*
                 * For values in the range in which we've assigned new
                 * DLT_ values, only raw "link[N:M]" filtering is supported.
                 */
-               if (linktype >= DLT_MATCHING_MIN &&
-                   linktype <= DLT_MATCHING_MAX) {
-                       off_linktype = -1;
-                       off_macpl = -1;
-                       off_nl = -1;
-                       off_nl_nosnap = -1;
-                       return;
+               if (cstate->linktype >= DLT_MATCHING_MIN &&
+                   cstate->linktype <= DLT_MATCHING_MAX) {
+                       cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+                       cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+                       cstate->off_nl = -1;
+                       cstate->off_nl_nosnap = -1;
+               } else {
+                       bpf_error(cstate, "unknown data link type %d", cstate->linktype);
                }
-
+               break;
        }
-       bpf_error("unknown data link type %d", linktype);
-       /* NOTREACHED */
-}
 
-/*
- * Load a value relative to the beginning of the link-layer header.
- * The link-layer header doesn't necessarily begin at the beginning
- * of the packet data; there might be a variable-length prefix containing
- * radio information.
- */
-static struct slist *
-gen_load_llrel(offset, size)
-       u_int offset, size;
-{
-       struct slist *s, *s2;
-
-       s = gen_llprefixlen();
-
-       /*
-        * If "s" is non-null, it has code to arrange that the X register
-        * contains the length of the prefix preceding the link-layer
-        * header.
-        *
-        * Otherwise, the length of the prefix preceding the link-layer
-        * header is "off_ll".
-        */
-       if (s != NULL) {
-               /*
-                * There's a variable-length prefix preceding the
-                * link-layer header.  "s" points to a list of statements
-                * that put the length of that prefix into the X register.
-                * do an indirect load, to use the X register as an offset.
-                */
-               s2 = new_stmt(BPF_LD|BPF_IND|size);
-               s2->s.k = offset;
-               sappend(s, s2);
-       } else {
-               /*
-                * There is no variable-length header preceding the
-                * link-layer header; add in off_ll, which, if there's
-                * a fixed-length header preceding the link-layer header,
-                * is the length of that header.
-                */
-               s = new_stmt(BPF_LD|BPF_ABS|size);
-               s->s.k = offset + off_ll;
-       }
-       return s;
+       cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
 }
 
 /*
- * Load a value relative to the beginning of the MAC-layer payload.
+ * Load a value relative to the specified absolute offset.
  */
 static struct slist *
-gen_load_macplrel(offset, size)
-       u_int offset, size;
+gen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
+    u_int offset, u_int size)
 {
        struct slist *s, *s2;
 
-       s = gen_off_macpl();
+       s = gen_abs_offset_varpart(cstate, abs_offset);
 
        /*
-        * If s is non-null, the offset of the MAC-layer payload is
-        * variable, and s points to a list of instructions that
-        * arrange that the X register contains that offset.
+        * If "s" is non-null, it has code to arrange that the X register
+        * contains the variable part of the absolute offset, so we
+        * generate a load relative to that, with an offset of
+        * abs_offset->constant_part + offset.
         *
-        * Otherwise, the offset of the MAC-layer payload is constant,
-        * and is in off_macpl.
+        * Otherwise, we can do an absolute load with an offset of
+        * abs_offset->constant_part + offset.
         */
        if (s != NULL) {
                /*
-                * The offset of the MAC-layer payload is in the X
-                * register.  Do an indirect load, to use the X register
-                * as an offset.
+                * "s" points to a list of statements that puts the
+                * variable part of the absolute offset into the X register.
+                * Do an indirect load, to use the X register as an offset.
                 */
-               s2 = new_stmt(BPF_LD|BPF_IND|size);
-               s2->s.k = offset;
+               s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+               s2->s.k = abs_offset->constant_part + offset;
                sappend(s, s2);
        } else {
                /*
-                * The offset of the MAC-layer payload is constant,
-                * and is in off_macpl; load the value at that offset
-                * plus the specified offset.
+                * There is no variable part of the absolute offset, so
+                * just do an absolute load.
                 */
-               s = new_stmt(BPF_LD|BPF_ABS|size);
-               s->s.k = off_macpl + offset;
+               s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
+               s->s.k = abs_offset->constant_part + offset;
        }
        return s;
 }
@@ -1564,33 +1646,44 @@ gen_load_macplrel(offset, size)
  * Load a value relative to the beginning of the specified header.
  */
 static struct slist *
-gen_load_a(offrel, offset, size)
-       enum e_offrel offrel;
-       u_int offset, size;
+gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size)
 {
        struct slist *s, *s2;
 
        switch (offrel) {
 
        case OR_PACKET:
-                s = new_stmt(BPF_LD|BPF_ABS|size);
+                s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
                 s->s.k = offset;
                break;
 
-       case OR_LINK:
-               s = gen_load_llrel(offset, size);
+       case OR_LINKHDR:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
                break;
 
-       case OR_MACPL:
-               s = gen_load_macplrel(offset, size);
+       case OR_PREVLINKHDR:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
                break;
 
-       case OR_NET:
-               s = gen_load_macplrel(off_nl + offset, size);
+       case OR_LLC:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
                break;
 
-       case OR_NET_NOSNAP:
-               s = gen_load_macplrel(off_nl_nosnap + offset, size);
+       case OR_PREVMPLSHDR:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
+               break;
+
+       case OR_LINKPL:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
+               break;
+
+       case OR_LINKPL_NOSNAP:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
+               break;
+
+       case OR_LINKTYPE:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
                break;
 
        case OR_TRAN_IPV4:
@@ -1600,25 +1693,26 @@ gen_load_a(offrel, offset, size)
                 * preceded by a variable-length header such as a radio
                 * header), in bytes.
                 */
-               s = gen_loadx_iphdrlen();
+               s = gen_loadx_iphdrlen(cstate);
 
                /*
-                * Load the item at {offset of the MAC-layer payload} +
-                * {offset, relative to the start of the MAC-layer
+                * Load the item at {offset of the link-layer payload} +
+                * {offset, relative to the start of the link-layer
                 * paylod, of the IPv4 header} + {length of the IPv4 header} +
                 * {specified offset}.
                 *
-                * (If the offset of the MAC-layer payload is variable,
-                * it's included in the value in the X register, and
-                * off_macpl is 0.)
+                * If the offset of the link-layer payload is variable,
+                * the variable part of that offset is included in the
+                * value in the X register, and we include the constant
+                * part in the offset of the load.
                 */
-               s2 = new_stmt(BPF_LD|BPF_IND|size);
-               s2->s.k = off_macpl + off_nl + offset;
+               s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+               s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
                sappend(s, s2);
                break;
 
        case OR_TRAN_IPV6:
-               s = gen_load_macplrel(off_nl + 40 + offset, size);
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
                break;
 
        default:
@@ -1630,87 +1724,87 @@ gen_load_a(offrel, offset, size)
 
 /*
  * Generate code to load into the X register the sum of the length of
- * the IPv4 header and any variable-length header preceding the link-layer
- * header.
+ * the IPv4 header and the variable part of the offset of the link-layer
+ * payload.
  */
 static struct slist *
-gen_loadx_iphdrlen()
+gen_loadx_iphdrlen(compiler_state_t *cstate)
 {
        struct slist *s, *s2;
 
-       s = gen_off_macpl();
+       s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
        if (s != NULL) {
                /*
-                * There's a variable-length prefix preceding the
-                * link-layer header, or the link-layer header is itself
-                * variable-length.  "s" points to a list of statements
-                * that put the offset of the MAC-layer payload into
-                * the X register.
+                * The offset of the link-layer payload has a variable
+                * part.  "s" points to a list of statements that put
+                * the variable part of that offset into the X register.
                 *
                 * The 4*([k]&0xf) addressing mode can't be used, as we
                 * don't have a constant offset, so we have to load the
                 * value in question into the A register and add to it
                 * the value from the X register.
                 */
-               s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
-               s2->s.k = off_nl;
+               s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+               s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
                sappend(s, s2);
-               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
                s2->s.k = 0xf;
                sappend(s, s2);
-               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
                s2->s.k = 2;
                sappend(s, s2);
 
                /*
-                * The A register now contains the length of the
-                * IP header.  We need to add to it the offset of
-                * the MAC-layer payload, which is still in the X
+                * The A register now contains the length of the IP header.
+                * We need to add to it the variable part of the offset of
+                * the link-layer payload, which is still in the X
                 * register, and move the result into the X register.
                 */
-               sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
-               sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+               sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+               sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
        } else {
                /*
-                * There is no variable-length header preceding the
-                * link-layer header, and the link-layer header is
-                * fixed-length; load the length of the IPv4 header,
-                * which is at an offset of off_nl from the beginning
-                * of the MAC-layer payload, and thus at an offset
-                * of off_mac_pl + off_nl from the beginning of the
-                * raw packet data.
-                */
-               s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
-               s->s.k = off_macpl + off_nl;
+                * The offset of the link-layer payload is a constant,
+                * so no code was generated to load the (non-existent)
+                * variable part of that offset.
+                *
+                * This means we can use the 4*([k]&0xf) addressing
+                * mode.  Load the length of the IPv4 header, which
+                * is at an offset of cstate->off_nl from the beginning of
+                * the link-layer payload, and thus at an offset of
+                * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
+                * of the raw packet data, using that addressing mode.
+                */
+               s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+               s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
        }
        return s;
 }
 
 static struct block *
-gen_uncond(rsense)
-       int rsense;
+gen_uncond(compiler_state_t *cstate, int rsense)
 {
        struct block *b;
        struct slist *s;
 
-       s = new_stmt(BPF_LD|BPF_IMM);
+       s = new_stmt(cstate, BPF_LD|BPF_IMM);
        s->s.k = !rsense;
-       b = new_block(JMP(BPF_JEQ));
+       b = new_block(cstate, JMP(BPF_JEQ));
        b->stmts = s;
 
        return b;
 }
 
 static inline struct block *
-gen_true()
+gen_true(compiler_state_t *cstate)
 {
-       return gen_uncond(1);
+       return gen_uncond(cstate, 1);
 }
 
 static inline struct block *
-gen_false()
+gen_false(compiler_state_t *cstate)
 {
-       return gen_uncond(0);
+       return gen_uncond(cstate, 0);
 }
 
 /*
@@ -1731,8 +1825,7 @@ gen_false()
  * the appropriate test.
  */
 static struct block *
-gen_ether_linktype(proto)
-       register int proto;
+gen_ether_linktype(compiler_state_t *cstate, int proto)
 {
        struct block *b0, *b1;
 
@@ -1753,9 +1846,9 @@ gen_ether_linktype(proto)
                 * DSAP, as we do for other types <= ETHERMTU
                 * (i.e., other SAP values)?
                 */
-               b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+               b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
                gen_not(b0);
-               b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
+               b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
                             ((proto << 8) | proto));
                gen_and(b0, b1);
                return b1;
@@ -1793,22 +1886,22 @@ gen_ether_linktype(proto)
                 * This generates code to check both for the
                 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
                 */
-               b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
-               b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
+               b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+               b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
                gen_or(b0, b1);
 
                /*
                 * Now we add code to check for SNAP frames with
                 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
                 */
-               b0 = gen_snap(0x000000, ETHERTYPE_IPX);
+               b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
                gen_or(b0, b1);
 
                /*
                 * Now we generate code to check for 802.3
                 * frames in general.
                 */
-               b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+               b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
                gen_not(b0);
 
                /*
@@ -1824,8 +1917,7 @@ gen_ether_linktype(proto)
                 * do that before checking for the other frame
                 * types.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
-                   (bpf_int32)ETHERTYPE_IPX);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
                gen_or(b0, b1);
                return b1;
 
@@ -1841,7 +1933,7 @@ gen_ether_linktype(proto)
                 * we check for an Ethernet type field less than
                 * 1500, which means it's an 802.3 length field.
                 */
-               b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+               b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
                gen_not(b0);
 
                /*
@@ -1856,9 +1948,9 @@ gen_ether_linktype(proto)
                 * type of ETHERTYPE_AARP (Appletalk ARP).
                 */
                if (proto == ETHERTYPE_ATALK)
-                       b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+                       b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
                else    /* proto == ETHERTYPE_AARP */
-                       b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+                       b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
                gen_and(b0, b1);
 
                /*
@@ -1866,7 +1958,7 @@ gen_ether_linktype(proto)
                 * phase 1?); we just check for the Ethernet
                 * protocol type.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 
                gen_or(b0, b1);
                return b1;
@@ -1881,10 +1973,9 @@ gen_ether_linktype(proto)
                         * a length field, <= ETHERMTU) and
                         * then check the DSAP.
                         */
-                       b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+                       b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
                        gen_not(b0);
-                       b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
-                           (bpf_int32)proto);
+                       b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
                        gen_and(b0, b1);
                        return b1;
                } else {
@@ -1897,29 +1988,62 @@ gen_ether_linktype(proto)
                         * will fail and the frame won't match,
                         * which is what we want).
                         */
-                       return gen_cmp(OR_LINK, off_linktype, BPF_H,
+                       return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
                            (bpf_int32)proto);
                }
        }
 }
 
+static struct block *
+gen_loopback_linktype(compiler_state_t *cstate, int proto)
+{
+       /*
+        * For DLT_NULL, the link-layer header is a 32-bit word
+        * containing an AF_ value in *host* byte order, and for
+        * DLT_ENC, the link-layer header begins with a 32-bit
+        * word containing an AF_ value in host byte order.
+        *
+        * In addition, if we're reading a saved capture file,
+        * the host byte order in the capture may not be the
+        * same as the host byte order on this machine.
+        *
+        * For DLT_LOOP, the link-layer header is a 32-bit
+        * word containing an AF_ value in *network* byte order.
+        */
+       if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
+               /*
+                * The AF_ value is in host byte order, but the BPF
+                * interpreter will convert it to network byte order.
+                *
+                * If this is a save file, and it's from a machine
+                * with the opposite byte order to ours, we byte-swap
+                * the AF_ value.
+                *
+                * Then we run it through "htonl()", and generate
+                * code to compare against the result.
+                */
+               if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
+                       proto = SWAPLONG(proto);
+               proto = htonl(proto);
+       }
+       return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
+}
+
 /*
  * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
  * or IPv6 then we have an error.
  */
 static struct block *
-gen_ipnet_linktype(proto)
-       register int proto;
+gen_ipnet_linktype(compiler_state_t *cstate, int proto)
 {
        switch (proto) {
 
        case ETHERTYPE_IP:
-               return gen_cmp(OR_LINK, off_linktype, BPF_B,
-                   (bpf_int32)IPH_AF_INET);
+               return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
                /* NOTREACHED */
 
        case ETHERTYPE_IPV6:
-               return gen_cmp(OR_LINK, off_linktype, BPF_B,
+               return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                    (bpf_int32)IPH_AF_INET6);
                /* NOTREACHED */
 
@@ -1927,7 +2051,7 @@ gen_ipnet_linktype(proto)
                break;
        }
 
-       return gen_false();
+       return gen_false(cstate);
 }
 
 /*
@@ -1939,8 +2063,7 @@ gen_ipnet_linktype(proto)
  * LINUX_SLL_P_802_2 value and then do the appropriate test.
  */
 static struct block *
-gen_linux_sll_linktype(proto)
-       register int proto;
+gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
 {
        struct block *b0, *b1;
 
@@ -1961,8 +2084,8 @@ gen_linux_sll_linktype(proto)
                 * DSAP, as we do for other types <= ETHERMTU
                 * (i.e., other SAP values)?
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
-               b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+               b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
                             ((proto << 8) | proto));
                gen_and(b0, b1);
                return b1;
@@ -1993,17 +2116,17 @@ gen_linux_sll_linktype(proto)
                 * then put a check for LINUX_SLL_P_802_2 frames
                 * before it.
                 */
-               b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
-               b1 = gen_snap(0x000000, ETHERTYPE_IPX);
+               b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+               b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
                gen_or(b0, b1);
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
                gen_and(b0, b1);
 
                /*
                 * Now check for 802.3 frames and OR that with
                 * the previous test.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
                gen_or(b0, b1);
 
                /*
@@ -2011,8 +2134,7 @@ gen_linux_sll_linktype(proto)
                 * do that before checking for the other frame
                 * types.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
-                   (bpf_int32)ETHERTYPE_IPX);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
                gen_or(b0, b1);
                return b1;
 
@@ -2028,7 +2150,7 @@ gen_linux_sll_linktype(proto)
                 * we check for the 802.2 protocol type in the
                 * "Ethernet type" field.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
 
                /*
                 * 802.2-encapsulated ETHERTYPE_ATALK packets are
@@ -2042,9 +2164,9 @@ gen_linux_sll_linktype(proto)
                 * type of ETHERTYPE_AARP (Appletalk ARP).
                 */
                if (proto == ETHERTYPE_ATALK)
-                       b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+                       b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
                else    /* proto == ETHERTYPE_AARP */
-                       b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+                       b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
                gen_and(b0, b1);
 
                /*
@@ -2052,7 +2174,7 @@ gen_linux_sll_linktype(proto)
                 * phase 1?); we just check for the Ethernet
                 * protocol type.
                 */
-               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+               b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 
                gen_or(b0, b1);
                return b1;
@@ -2066,9 +2188,8 @@ gen_linux_sll_linktype(proto)
                         * in the "Ethernet type" field, and
                         * then check the DSAP.
                         */
-                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
-                           LINUX_SLL_P_802_2);
-                       b1 = gen_cmp(OR_LINK, off_macpl, BPF_B,
+                       b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+                       b1 = gen_cmp(cstate, OR_LINKHDR, cstate->off_linkpl.constant_part, BPF_B,
                             (bpf_int32)proto);
                        gen_and(b0, b1);
                        return b1;
@@ -2082,14 +2203,13 @@ gen_linux_sll_linktype(proto)
                         * will fail and the frame won't match,
                         * which is what we want).
                         */
-                       return gen_cmp(OR_LINK, off_linktype, BPF_H,
-                           (bpf_int32)proto);
+                       return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
                }
        }
 }
 
 static struct slist *
-gen_load_prism_llprefixlen()
+gen_load_prism_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
        struct slist *sjeq_avs_cookie;
@@ -2100,7 +2220,7 @@ gen_load_prism_llprefixlen()
         * we are generating jmp instructions within a normal
         * slist of instructions
         */
-       no_optimize = 1;
+       cstate->no_optimize = 1;
 
        /*
         * Generate code to load the length of the radio header into
@@ -2121,24 +2241,24 @@ gen_load_prism_llprefixlen()
         * but no known software generates headers that aren't 144
         * bytes long.
         */
-       if (reg_off_ll != -1) {
+       if (cstate->off_linkhdr.reg != -1) {
                /*
                 * Load the cookie.
                 */
-               s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
                s1->s.k = 0;
 
                /*
                 * AND it with 0xFFFFF000.
                 */
-               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
                s2->s.k = 0xFFFFF000;
                sappend(s1, s2);
 
                /*
                 * Compare with 0x80211000.
                 */
-               sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
+               sjeq_avs_cookie = new_stmt(cstate, JMP(BPF_JEQ));
                sjeq_avs_cookie->s.k = 0x80211000;
                sappend(s1, sjeq_avs_cookie);
 
@@ -2149,7 +2269,7 @@ gen_load_prism_llprefixlen()
                 * the AVS header are the length of the AVS header.
                 * That field is big-endian.
                 */
-               s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
                s2->s.k = 4;
                sappend(s1, s2);
                sjeq_avs_cookie->s.jt = s2;
@@ -2162,7 +2282,7 @@ gen_load_prism_llprefixlen()
                 * it's added to the PC, so, as we're jumping
                 * over a single instruction, it should be 1.)
                 */
-               sjcommon = new_stmt(JMP(BPF_JA));
+               sjcommon = new_stmt(cstate, JMP(BPF_JA));
                sjcommon->s.k = 1;
                sappend(s1, sjcommon);
 
@@ -2172,7 +2292,7 @@ gen_load_prism_llprefixlen()
                 * into the A register.  Have the test for an AVS
                 * header branch here if we don't have an AVS header.
                 */
-               s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
+               s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
                s2->s.k = 144;
                sappend(s1, s2);
                sjeq_avs_cookie->s.jf = s2;
@@ -2182,15 +2302,15 @@ gen_load_prism_llprefixlen()
                 * it.  The code for the AVS header will jump here after
                 * loading the length of the AVS header.
                 */
-               s2 = new_stmt(BPF_ST);
-               s2->s.k = reg_off_ll;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkhdr.reg;
                sappend(s1, s2);
                sjcommon->s.jf = s2;
 
                /*
                 * Now move it into the X register.
                 */
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                return (s1);
@@ -2199,7 +2319,7 @@ gen_load_prism_llprefixlen()
 }
 
 static struct slist *
-gen_load_avs_llprefixlen()
+gen_load_avs_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
 
@@ -2210,27 +2330,27 @@ gen_load_avs_llprefixlen()
         * generated uses that prefix, so we don't need to generate any
         * code to load it.)
         */
-       if (reg_off_ll != -1) {
+       if (cstate->off_linkhdr.reg != -1) {
                /*
                 * The 4 bytes at an offset of 4 from the beginning of
                 * the AVS header are the length of the AVS header.
                 * That field is big-endian.
                 */
-               s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
                s1->s.k = 4;
 
                /*
                 * Now allocate a register to hold that value and store
                 * it.
                 */
-               s2 = new_stmt(BPF_ST);
-               s2->s.k = reg_off_ll;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkhdr.reg;
                sappend(s1, s2);
 
                /*
                 * Now move it into the X register.
                 */
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                return (s1);
@@ -2239,7 +2359,7 @@ gen_load_avs_llprefixlen()
 }
 
 static struct slist *
-gen_load_radiotap_llprefixlen()
+gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
 
@@ -2250,7 +2370,7 @@ gen_load_radiotap_llprefixlen()
         * generated uses that prefix, so we don't need to generate any
         * code to load it.)
         */
-       if (reg_off_ll != -1) {
+       if (cstate->off_linkhdr.reg != -1) {
                /*
                 * The 2 bytes at offsets of 2 and 3 from the beginning
                 * of the radiotap header are the length of the radiotap
@@ -2262,36 +2382,36 @@ gen_load_radiotap_llprefixlen()
                 * Load the high-order byte, at an offset of 3, shift it
                 * left a byte, and put the result in the X register.
                 */
-               s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
                s1->s.k = 3;
-               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
                sappend(s1, s2);
                s2->s.k = 8;
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                /*
                 * Load the next byte, at an offset of 2, and OR the
                 * value from the X register into it.
                 */
-               s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
                sappend(s1, s2);
                s2->s.k = 2;
-               s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
                sappend(s1, s2);
 
                /*
                 * Now allocate a register to hold that value and store
                 * it.
                 */
-               s2 = new_stmt(BPF_ST);
-               s2->s.k = reg_off_ll;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkhdr.reg;
                sappend(s1, s2);
 
                /*
                 * Now move it into the X register.
                 */
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                return (s1);
@@ -2299,7 +2419,7 @@ gen_load_radiotap_llprefixlen()
                return (NULL);
 }
 
-/* 
+/*
  * At the moment we treat PPI as normal Radiotap encoded
  * packets. The difference is in the function that generates
  * the code at the beginning to compute the header length.
@@ -2309,16 +2429,16 @@ gen_load_radiotap_llprefixlen()
  * that's done in finish_parse().
  */
 static struct slist *
-gen_load_ppi_llprefixlen()
+gen_load_ppi_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
-       
+
        /*
         * Generate code to load the length of the radiotap header
         * into the register assigned to hold that length, if one has
         * been assigned.
         */
-       if (reg_off_ll != -1) {
+       if (cstate->off_linkhdr.reg != -1) {
                /*
                 * The 2 bytes at offsets of 2 and 3 from the beginning
                 * of the radiotap header are the length of the radiotap
@@ -2330,36 +2450,36 @@ gen_load_ppi_llprefixlen()
                 * Load the high-order byte, at an offset of 3, shift it
                 * left a byte, and put the result in the X register.
                 */
-               s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
                s1->s.k = 3;
-               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
                sappend(s1, s2);
                s2->s.k = 8;
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                /*
                 * Load the next byte, at an offset of 2, and OR the
                 * value from the X register into it.
                 */
-               s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
                sappend(s1, s2);
                s2->s.k = 2;
-               s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
                sappend(s1, s2);
 
                /*
                 * Now allocate a register to hold that value and store
                 * it.
                 */
-               s2 = new_stmt(BPF_ST);
-               s2->s.k = reg_off_ll;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkhdr.reg;
                sappend(s1, s2);
 
                /*
                 * Now move it into the X register.
                 */
-               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
                sappend(s1, s2);
 
                return (s1);
@@ -2375,21 +2495,22 @@ gen_load_ppi_llprefixlen()
  * radio information.
  */
 static struct slist *
-gen_load_802_11_header_len(struct slist *s, struct slist *snext)
+gen_load_802_11_header_len(compiler_state_t *cstate, struct slist *s, struct slist *snext)
 {
        struct slist *s2;
        struct slist *sjset_data_frame_1;
        struct slist *sjset_data_frame_2;
        struct slist *sjset_qos;
-       struct slist *sjset_radiotap_flags;
-       struct slist *sjset_radiotap_tsft;
+       struct slist *sjset_radiotap_flags_present;
+       struct slist *sjset_radiotap_ext_present;
+       struct slist *sjset_radiotap_tsft_present;
        struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
        struct slist *s_roundup;
 
-       if (reg_off_macpl == -1) {
+       if (cstate->off_linkpl.reg == -1) {
                /*
                 * No register has been assigned to the offset of
-                * the MAC-layer payload, which means nobody needs
+                * the link-layer payload, which means nobody needs
                 * it; don't bother computing it - just return
                 * what we already have.
                 */
@@ -2401,15 +2522,15 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
         * we are generating jmp instructions within a normal
         * slist of instructions
         */
-       no_optimize = 1;
-       
+       cstate->no_optimize = 1;
+
        /*
         * If "s" is non-null, it has code to arrange that the X register
         * contains the length of the prefix preceding the link-layer
         * header.
         *
         * Otherwise, the length of the prefix preceding the link-layer
-        * header is "off_ll".
+        * header is "off_outermostlinkhdr.constant_part".
         */
        if (s == NULL) {
                /*
@@ -2418,30 +2539,30 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 *
                 * Load the length of the fixed-length prefix preceding
                 * the link-layer header (if any) into the X register,
-                * and store it in the reg_off_macpl register.
-                * That length is off_ll.
+                * and store it in the cstate->off_linkpl.reg register.
+                * That length is off_outermostlinkhdr.constant_part.
                 */
-               s = new_stmt(BPF_LDX|BPF_IMM);
-               s->s.k = off_ll;
+               s = new_stmt(cstate, BPF_LDX|BPF_IMM);
+               s->s.k = cstate->off_outermostlinkhdr.constant_part;
        }
 
        /*
         * The X register contains the offset of the beginning of the
         * link-layer header; add 24, which is the minimum length
         * of the MAC header for a data frame, to that, and store it
-        * in reg_off_macpl, and then load the Frame Control field,
+        * in cstate->off_linkpl.reg, and then load the Frame Control field,
         * which is at the offset in the X register, with an indexed load.
         */
-       s2 = new_stmt(BPF_MISC|BPF_TXA);
+       s2 = new_stmt(cstate, BPF_MISC|BPF_TXA);
        sappend(s, s2);
-       s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+       s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
        s2->s.k = 24;
        sappend(s, s2);
-       s2 = new_stmt(BPF_ST);
-       s2->s.k = reg_off_macpl;
+       s2 = new_stmt(cstate, BPF_ST);
+       s2->s.k = cstate->off_linkpl.reg;
        sappend(s, s2);
 
-       s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+       s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
        s2->s.k = 0;
        sappend(s, s2);
 
@@ -2450,15 +2571,15 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
         * a data frame has the 0x08 bit (b3) in that field set and the
         * 0x04 bit (b2) clear.
         */
-       sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
+       sjset_data_frame_1 = new_stmt(cstate, JMP(BPF_JSET));
        sjset_data_frame_1->s.k = 0x08;
        sappend(s, sjset_data_frame_1);
-               
+
        /*
         * If b3 is set, test b2, otherwise go to the first statement of
         * the rest of the program.
         */
-       sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
+       sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(cstate, JMP(BPF_JSET));
        sjset_data_frame_2->s.k = 0x04;
        sappend(s, sjset_data_frame_2);
        sjset_data_frame_1->s.jf = snext;
@@ -2469,24 +2590,24 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
         * program.
         */
        sjset_data_frame_2->s.jt = snext;
-       sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
+       sjset_data_frame_2->s.jf = sjset_qos = new_stmt(cstate, JMP(BPF_JSET));
        sjset_qos->s.k = 0x80;  /* QoS bit */
        sappend(s, sjset_qos);
-               
+
        /*
-        * If it's set, add 2 to reg_off_macpl, to skip the QoS
+        * If it's set, add 2 to cstate->off_linkpl.reg, to skip the QoS
         * field.
         * Otherwise, go to the first statement of the rest of the
         * program.
         */
-       sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
-       s2->s.k = reg_off_macpl;
+       sjset_qos->s.jt = s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+       s2->s.k = cstate->off_linkpl.reg;
        sappend(s, s2);
-       s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+       s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
        s2->s.k = 2;
        sappend(s, s2);
-       s2 = new_stmt(BPF_ST);
-       s2->s.k = reg_off_macpl;
+       s2 = new_stmt(cstate, BPF_ST);
+       s2->s.k = cstate->off_linkpl.reg;
        sappend(s, s2);
 
        /*
@@ -2498,32 +2619,54 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
         * little-endian, so we byte-swap all of the values
         * we test against, as they will be loaded as big-endian
         * values.
+        *
+        * XXX - in the general case, we would have to scan through
+        * *all* the presence bits, if there's more than one word of
+        * presence bits.  That would require a loop, meaning that
+        * we wouldn't be able to run the filter in the kernel.
+        *
+        * We assume here that the Atheros adapters that insert the
+        * annoying padding don't have multiple antennae and therefore
+        * do not generate radiotap headers with multiple presence words.
         */
-       if (linktype == DLT_IEEE802_11_RADIO) {
+       if (cstate->linktype == DLT_IEEE802_11_RADIO) {
                /*
                 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
-                * in the presence flag?
+                * in the first presence flag word?
                 */
-               sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
+               sjset_qos->s.jf = s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_W);
                s2->s.k = 4;
                sappend(s, s2);
 
-               sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
-               sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
-               sappend(s, sjset_radiotap_flags);
+               sjset_radiotap_flags_present = new_stmt(cstate, JMP(BPF_JSET));
+               sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
+               sappend(s, sjset_radiotap_flags_present);
 
                /*
                 * If not, skip all of this.
                 */
-               sjset_radiotap_flags->s.jf = snext;
+               sjset_radiotap_flags_present->s.jf = snext;
+
+               /*
+                * Otherwise, is the "extension" bit set in that word?
+                */
+               sjset_radiotap_ext_present = new_stmt(cstate, JMP(BPF_JSET));
+               sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
+               sappend(s, sjset_radiotap_ext_present);
+               sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
+
+               /*
+                * If so, skip all of this.
+                */
+               sjset_radiotap_ext_present->s.jt = snext;
 
                /*
                 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
                 */
-               sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
-                   new_stmt(JMP(BPF_JSET));
-               sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
-               sappend(s, sjset_radiotap_tsft);
+               sjset_radiotap_tsft_present = new_stmt(cstate, JMP(BPF_JSET));
+               sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
+               sappend(s, sjset_radiotap_tsft_present);
+               sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
 
                /*
                 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
@@ -2534,11 +2677,12 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
                 * is set.
                 */
-               sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
                s2->s.k = 16;
                sappend(s, s2);
+               sjset_radiotap_tsft_present->s.jt = s2;
 
-               sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
+               sjset_tsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
                sjset_tsft_datapad->s.k = 0x20;
                sappend(s, sjset_tsft_datapad);
 
@@ -2550,11 +2694,12 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
                 * is set.
                 */
-               sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
                s2->s.k = 8;
                sappend(s, s2);
+               sjset_radiotap_tsft_present->s.jf = s2;
 
-               sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
+               sjset_notsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
                sjset_notsft_datapad->s.k = 0x20;
                sappend(s, sjset_notsft_datapad);
 
@@ -2565,17 +2710,17 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 * dividing by and multiplying by 4, which we do by
                 * ANDing with ~3.
                 */
-               s_roundup = new_stmt(BPF_LD|BPF_MEM);
-               s_roundup->s.k = reg_off_macpl;
+               s_roundup = new_stmt(cstate, BPF_LD|BPF_MEM);
+               s_roundup->s.k = cstate->off_linkpl.reg;
                sappend(s, s_roundup);
-               s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
                s2->s.k = 3;
                sappend(s, s2);
-               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
                s2->s.k = ~3;
                sappend(s, s2);
-               s2 = new_stmt(BPF_ST);
-               s2->s.k = reg_off_macpl;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkpl.reg;
                sappend(s, s2);
 
                sjset_tsft_datapad->s.jt = s_roundup;
@@ -2589,33 +2734,46 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
 }
 
 static void
-insert_compute_vloffsets(b)
-       struct block *b;
+insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
 {
        struct slist *s;
 
+       /* There is an implicit dependency between the link
+        * payload and link header since the payload computation
+        * includes the variable part of the header. Therefore,
+        * if nobody else has allocated a register for the link
+        * header and we need it, do it now. */
+       if (cstate->off_linkpl.reg != -1 && cstate->off_linkhdr.is_variable &&
+           cstate->off_linkhdr.reg == -1)
+               cstate->off_linkhdr.reg = alloc_reg(cstate);
+
        /*
         * For link-layer types that have a variable-length header
         * preceding the link-layer header, generate code to load
         * the offset of the link-layer header into the register
         * assigned to that offset, if any.
+        *
+        * XXX - this, and the next switch statement, won't handle
+        * encapsulation of 802.11 or 802.11+radio information in
+        * some other protocol stack.  That's significantly more
+        * complicated.
         */
-       switch (linktype) {
+       switch (cstate->outermostlinktype) {
 
        case DLT_PRISM_HEADER:
-               s = gen_load_prism_llprefixlen();
+               s = gen_load_prism_llprefixlen(cstate);
                break;
 
        case DLT_IEEE802_11_RADIO_AVS:
-               s = gen_load_avs_llprefixlen();
+               s = gen_load_avs_llprefixlen(cstate);
                break;
 
        case DLT_IEEE802_11_RADIO:
-               s = gen_load_radiotap_llprefixlen();
+               s = gen_load_radiotap_llprefixlen(cstate);
                break;
 
        case DLT_PPI:
-               s = gen_load_ppi_llprefixlen();
+               s = gen_load_ppi_llprefixlen(cstate);
                break;
 
        default:
@@ -2625,17 +2783,17 @@ insert_compute_vloffsets(b)
 
        /*
         * For link-layer types that have a variable-length link-layer
-        * header, generate code to load the offset of the MAC-layer
+        * header, generate code to load the offset of the link-layer
         * payload into the register assigned to that offset, if any.
         */
-       switch (linktype) {
+       switch (cstate->outermostlinktype) {
 
        case DLT_IEEE802_11:
        case DLT_PRISM_HEADER:
        case DLT_IEEE802_11_RADIO_AVS:
        case DLT_IEEE802_11_RADIO:
        case DLT_PPI:
-               s = gen_load_802_11_header_len(s, b->stmts);
+               s = gen_load_802_11_header_len(cstate, s, b->stmts);
                break;
        }
 
@@ -2652,19 +2810,19 @@ insert_compute_vloffsets(b)
 }
 
 static struct block *
-gen_ppi_dlt_check(void)
+gen_ppi_dlt_check(compiler_state_t *cstate)
 {
        struct slist *s_load_dlt;
        struct block *b;
 
-       if (linktype == DLT_PPI)
+       if (cstate->linktype == DLT_PPI)
        {
                /* Create the statements that check for the DLT
                 */
-               s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s_load_dlt = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
                s_load_dlt->s.k = 4;
 
-               b = new_block(JMP(BPF_JEQ));
+               b = new_block(cstate, JMP(BPF_JEQ));
 
                b->stmts = s_load_dlt;
                b->s.k = SWAPLONG(DLT_IEEE802_11);
@@ -2673,164 +2831,49 @@ gen_ppi_dlt_check(void)
        {
                b = NULL;
        }
-
-       return b;
-}
-
-static struct slist *
-gen_prism_llprefixlen(void)
-{
-       struct slist *s;
-
-       if (reg_off_ll == -1) {
-               /*
-                * We haven't yet assigned a register for the length
-                * of the radio header; allocate one.
-                */
-               reg_off_ll = alloc_reg();
-       }
-
-       /*
-        * Load the register containing the radio length
-        * into the X register.
-        */
-       s = new_stmt(BPF_LDX|BPF_MEM);
-       s->s.k = reg_off_ll;
-       return s;
-}
-
-static struct slist *
-gen_avs_llprefixlen(void)
-{
-       struct slist *s;
-
-       if (reg_off_ll == -1) {
-               /*
-                * We haven't yet assigned a register for the length
-                * of the AVS header; allocate one.
-                */
-               reg_off_ll = alloc_reg();
-       }
-
-       /*
-        * Load the register containing the AVS length
-        * into the X register.
-        */
-       s = new_stmt(BPF_LDX|BPF_MEM);
-       s->s.k = reg_off_ll;
-       return s;
-}
-
-static struct slist *
-gen_radiotap_llprefixlen(void)
-{
-       struct slist *s;
-
-       if (reg_off_ll == -1) {
-               /*
-                * We haven't yet assigned a register for the length
-                * of the radiotap header; allocate one.
-                */
-               reg_off_ll = alloc_reg();
-       }
-
-       /*
-        * Load the register containing the radiotap length
-        * into the X register.
-        */
-       s = new_stmt(BPF_LDX|BPF_MEM);
-       s->s.k = reg_off_ll;
-       return s;
-}
-
-/* 
- * At the moment we treat PPI as normal Radiotap encoded
- * packets. The difference is in the function that generates
- * the code at the beginning to compute the header length.
- * Since this code generator of PPI supports bare 802.11
- * encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we generate code to check for this too.
- */
-static struct slist *
-gen_ppi_llprefixlen(void)
-{
-       struct slist *s;
-
-       if (reg_off_ll == -1) {
-               /*
-                * We haven't yet assigned a register for the length
-                * of the radiotap header; allocate one.
-                */
-               reg_off_ll = alloc_reg();
-       }
-
-       /*
-        * Load the register containing the PPI length
-        * into the X register.
-        */
-       s = new_stmt(BPF_LDX|BPF_MEM);
-       s->s.k = reg_off_ll;
-       return s;
-}
-
-/*
- * Generate code to compute the link-layer header length, if necessary,
- * putting it into the X register, and to return either a pointer to a
- * "struct slist" for the list of statements in that code, or NULL if
- * no code is necessary.
- */
-static struct slist *
-gen_llprefixlen(void)
-{
-       switch (linktype) {
-
-       case DLT_PRISM_HEADER:
-               return gen_prism_llprefixlen();
-
-       case DLT_IEEE802_11_RADIO_AVS:
-               return gen_avs_llprefixlen();
-
-       case DLT_IEEE802_11_RADIO:
-               return gen_radiotap_llprefixlen();
-
-       case DLT_PPI:
-               return gen_ppi_llprefixlen();
-
-       default:
-               return NULL;
-       }
+
+       return b;
 }
 
 /*
- * Generate code to load the register containing the offset of the
- * MAC-layer payload into the X register; if no register for that offset
- * has been allocated, allocate it first.
+ * Take an absolute offset, and:
+ *
+ *    if it has no variable part, return NULL;
+ *
+ *    if it has a variable part, generate code to load the register
+ *    containing that variable part into the X register, returning
+ *    a pointer to that code - if no register for that offset has
+ *    been allocated, allocate it first.
+ *
+ * (The code to set that register will be generated later, but will
+ * be placed earlier in the code sequence.)
  */
 static struct slist *
-gen_off_macpl(void)
+gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
 {
        struct slist *s;
 
-       if (off_macpl_is_variable) {
-               if (reg_off_macpl == -1) {
+       if (off->is_variable) {
+               if (off->reg == -1) {
                        /*
-                        * We haven't yet assigned a register for the offset
-                        * of the MAC-layer payload; allocate one.
+                        * We haven't yet assigned a register for the
+                        * variable part of the offset of the link-layer
+                        * header; allocate one.
                         */
-                       reg_off_macpl = alloc_reg();
+                       off->reg = alloc_reg(cstate);
                }
 
                /*
-                * Load the register containing the offset of the MAC-layer
-                * payload into the X register.
+                * Load the register containing the variable part of the
+                * offset of the link-layer header into the X register.
                 */
-               s = new_stmt(BPF_LDX|BPF_MEM);
-               s->s.k = reg_off_macpl;
+               s = new_stmt(cstate, BPF_LDX|BPF_MEM);
+               s->s.k = off->reg;
                return s;
        } else {
                /*
-                * That offset isn't variable, so we don't need to
-                * generate any code.
+                * That offset isn't variable, there's no variable part,
+                * so we don't need to generate any code.
                 */
                return NULL;
        }
@@ -2885,6 +2928,51 @@ ethertype_to_ppptype(proto)
        return (proto);
 }
 
+/*
+ * Generate any tests that, for encapsulation of a link-layer packet
+ * inside another protocol stack, need to be done to check for those
+ * link-layer packets (and that haven't already been done by a check
+ * for that encapsulation).
+ */
+static struct block *
+gen_prevlinkhdr_check(compiler_state_t *cstate)
+{
+       struct block *b0;
+
+       if (cstate->is_geneve)
+               return gen_geneve_ll_check(cstate);
+
+       switch (cstate->prevlinktype) {
+
+       case DLT_SUNATM:
+               /*
+                * This is LANE-encapsulated Ethernet; check that the LANE
+                * packet doesn't begin with an LE Control marker, i.e.
+                * that it's data, not a control message.
+                *
+                * (We've already generated a test for LANE.)
+                */
+               b0 = gen_cmp(cstate, OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
+               gen_not(b0);
+               return b0;
+
+       default:
+               /*
+                * No such tests are necessary.
+                */
+               return NULL;
+       }
+       /*NOTREACHED*/
+}
+
+/*
+ * The three different values we should check for when checking for an
+ * IPv6 packet with DLT_NULL.
+ */
+#define BSD_AFNUM_INET6_BSD    24      /* NetBSD, OpenBSD, BSD/OS, Npcap */
+#define BSD_AFNUM_INET6_FREEBSD        28      /* FreeBSD */
+#define BSD_AFNUM_INET6_DARWIN 30      /* OS X, iOS, other Darwin-based OSes */
+
 /*
  * Generate code to match a particular packet type by matching the
  * link-layer type field or fields in the 802.2 LLC header.
@@ -2893,55 +2981,46 @@ ethertype_to_ppptype(proto)
  * value, if <= ETHERMTU.
  */
 static struct block *
-gen_linktype(proto)
-       register int proto;
+gen_linktype(compiler_state_t *cstate, int proto)
 {
        struct block *b0, *b1, *b2;
+       const char *description;
 
        /* are we checking MPLS-encapsulated packets? */
-       if (label_stack_depth > 0) {
+       if (cstate->label_stack_depth > 0) {
                switch (proto) {
                case ETHERTYPE_IP:
                case PPP_IP:
                        /* FIXME add other L3 proto IDs */
-                       return gen_mpls_linktype(Q_IP); 
+                       return gen_mpls_linktype(cstate, Q_IP);
 
                case ETHERTYPE_IPV6:
                case PPP_IPV6:
                        /* FIXME add other L3 proto IDs */
-                       return gen_mpls_linktype(Q_IPV6); 
+                       return gen_mpls_linktype(cstate, Q_IPV6);
 
                default:
-                       bpf_error("unsupported protocol over mpls");
+                       bpf_error(cstate, "unsupported protocol over mpls");
                        /* NOTREACHED */
                }
        }
 
-       /*
-        * Are we testing PPPoE packets?
-        */
-       if (is_pppoes) {
-               /*
-                * The PPPoE session header is part of the
-                * MAC-layer payload, so all references
-                * should be relative to the beginning of
-                * that payload.
-                */
-
-               /*
-                * We use Ethernet protocol types inside libpcap;
-                * map them to the corresponding PPP protocol types.
-                */
-               proto = ethertype_to_ppptype(proto);
-               return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto);
-       }
-
-       switch (linktype) {
+       switch (cstate->linktype) {
 
        case DLT_EN10MB:
        case DLT_NETANALYZER:
        case DLT_NETANALYZER_TRANSPARENT:
-               return gen_ether_linktype(proto);
+               /* Geneve has an EtherType regardless of whether there is an
+                * L2 header. */
+               if (!cstate->is_geneve)
+                       b0 = gen_prevlinkhdr_check(cstate);
+               else
+                       b0 = NULL;
+
+               b1 = gen_ether_linktype(cstate, proto);
+               if (b0 != NULL)
+                       gen_and(b0, b1);
+               return b1;
                /*NOTREACHED*/
                break;
 
@@ -2953,8 +3032,7 @@ gen_linktype(proto)
                        /* fall through */
 
                default:
-                       return gen_cmp(OR_LINK, off_linktype, BPF_H,
-                           (bpf_int32)proto);
+                       return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
                        /*NOTREACHED*/
                        break;
                }
@@ -2968,12 +3046,12 @@ gen_linktype(proto)
                /*
                 * Check that we have a data frame.
                 */
-               b0 = gen_check_802_11_data_frame();
+               b0 = gen_check_802_11_data_frame(cstate);
 
                /*
                 * Now check for the specified link-layer type.
                 */
-               b1 = gen_llc_linktype(proto);
+               b1 = gen_llc_linktype(cstate, proto);
                gen_and(b0, b1);
                return b1;
                /*NOTREACHED*/
@@ -2981,9 +3059,9 @@ gen_linktype(proto)
 
        case DLT_FDDI:
                /*
-                * XXX - check for asynchronous frames, as per RFC 1103.
+                * XXX - check for LLC frames.
                 */
-               return gen_llc_linktype(proto);
+               return gen_llc_linktype(cstate, proto);
                /*NOTREACHED*/
                break;
 
@@ -2991,56 +3069,34 @@ gen_linktype(proto)
                /*
                 * XXX - check for LLC PDUs, as per IEEE 802.5.
                 */
-               return gen_llc_linktype(proto);
+               return gen_llc_linktype(cstate, proto);
                /*NOTREACHED*/
                break;
 
        case DLT_ATM_RFC1483:
        case DLT_ATM_CLIP:
        case DLT_IP_OVER_FC:
-               return gen_llc_linktype(proto);
+               return gen_llc_linktype(cstate, proto);
                /*NOTREACHED*/
                break;
 
        case DLT_SUNATM:
                /*
-                * If "is_lane" is set, check for a LANE-encapsulated
-                * version of this protocol, otherwise check for an
-                * LLC-encapsulated version of this protocol.
+                * Check for an LLC-encapsulated version of this protocol;
+                * if we were checking for LANE, linktype would no longer
+                * be DLT_SUNATM.
                 *
-                * We assume LANE means Ethernet, not Token Ring.
+                * Check for LLC encapsulation and then check the protocol.
                 */
-               if (is_lane) {
-                       /*
-                        * Check that the packet doesn't begin with an
-                        * LE Control marker.  (We've already generated
-                        * a test for LANE.)
-                        */
-                       b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
-                           0xFF00);
-                       gen_not(b0);
-
-                       /*
-                        * Now generate an Ethernet test.
-                        */
-                       b1 = gen_ether_linktype(proto);
-                       gen_and(b0, b1);
-                       return b1;
-               } else {
-                       /*
-                        * Check for LLC encapsulation and then check the
-                        * protocol.
-                        */
-                       b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
-                       b1 = gen_llc_linktype(proto);
-                       gen_and(b0, b1);
-                       return b1;
-               }
+               b0 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+               b1 = gen_llc_linktype(cstate, proto);
+               gen_and(b0, b1);
+               return b1;
                /*NOTREACHED*/
                break;
 
        case DLT_LINUX_SLL:
-               return gen_linux_sll_linktype(proto);
+               return gen_linux_sll_linktype(cstate, proto);
                /*NOTREACHED*/
                break;
 
@@ -3058,14 +3114,14 @@ gen_linktype(proto)
 
                case ETHERTYPE_IP:
                        /* Check for a version number of 4. */
-                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
+                       return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
 
                case ETHERTYPE_IPV6:
                        /* Check for a version number of 6. */
-                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
+                       return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
 
                default:
-                       return gen_false();             /* always false */
+                       return gen_false(cstate);       /* always false */
                }
                /*NOTREACHED*/
                break;
@@ -3075,10 +3131,10 @@ gen_linktype(proto)
                 * Raw IPv4, so no type field.
                 */
                if (proto == ETHERTYPE_IP)
-                       return gen_true();              /* always true */
+                       return gen_true(cstate);        /* always true */
 
                /* Checking for something other than IPv4; always false */
-               return gen_false();
+               return gen_false(cstate);
                /*NOTREACHED*/
                break;
 
@@ -3087,10 +3143,10 @@ gen_linktype(proto)
                 * Raw IPv6, so no type field.
                 */
                if (proto == ETHERTYPE_IPV6)
-                       return gen_true();              /* always true */
+                       return gen_true(cstate);        /* always true */
 
                /* Checking for something other than IPv6; always false */
-               return gen_false();
+               return gen_false(cstate);
                /*NOTREACHED*/
                break;
 
@@ -3103,7 +3159,7 @@ gen_linktype(proto)
                 * map them to the corresponding PPP protocol types.
                 */
                proto = ethertype_to_ppptype(proto);
-               return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+               return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
                /*NOTREACHED*/
                break;
 
@@ -3119,16 +3175,16 @@ gen_linktype(proto)
                         * Also check for Van Jacobson-compressed IP.
                         * XXX - do this for other forms of PPP?
                         */
-                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
-                       b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
+                       b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_IP);
+                       b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJC);
                        gen_or(b0, b1);
-                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
+                       b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
                        gen_or(b1, b0);
                        return b0;
 
                default:
                        proto = ethertype_to_ppptype(proto);
-                       return gen_cmp(OR_LINK, off_linktype, BPF_H,
+                       return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
                                (bpf_int32)proto);
                }
                /*NOTREACHED*/
@@ -3137,39 +3193,71 @@ gen_linktype(proto)
        case DLT_NULL:
        case DLT_LOOP:
        case DLT_ENC:
-               /*
-                * For DLT_NULL, the link-layer header is a 32-bit
-                * word containing an AF_ value in *host* byte order,
-                * and for DLT_ENC, the link-layer header begins
-                * with a 32-bit work containing an AF_ value in
-                * host byte order.
-                *
-                * In addition, if we're reading a saved capture file,
-                * the host byte order in the capture may not be the
-                * same as the host byte order on this machine.
-                *
-                * For DLT_LOOP, the link-layer header is a 32-bit
-                * word containing an AF_ value in *network* byte order.
-                *
-                * XXX - AF_ values may, unfortunately, be platform-
-                * dependent; for example, FreeBSD's AF_INET6 is 24
-                * whilst NetBSD's and OpenBSD's is 26.
-                *
-                * This means that, when reading a capture file, just
-                * checking for our AF_INET6 value won't work if the
-                * capture file came from another OS.
-                */
                switch (proto) {
 
                case ETHERTYPE_IP:
-                       proto = AF_INET;
-                       break;
+                       return (gen_loopback_linktype(cstate, AF_INET));
 
-#ifdef INET6
                case ETHERTYPE_IPV6:
-                       proto = AF_INET6;
-                       break;
-#endif
+                       /*
+                        * AF_ values may, unfortunately, be platform-
+                        * dependent; AF_INET isn't, because everybody
+                        * used 4.2BSD's value, but AF_INET6 is, because
+                        * 4.2BSD didn't have a value for it (given that
+                        * IPv6 didn't exist back in the early 1980's),
+                        * and they all picked their own values.
+                        *
+                        * This means that, if we're reading from a
+                        * savefile, we need to check for all the
+                        * possible values.
+                        *
+                        * If we're doing a live capture, we only need
+                        * to check for this platform's value; however,
+                        * Npcap uses 24, which isn't Windows's AF_INET6
+                        * value.  (Given the multiple different values,
+                        * programs that read pcap files shouldn't be
+                        * checking for their platform's AF_INET6 value
+                        * anyway, they should check for all of the
+                        * possible values. and they might as well do
+                        * that even for live captures.)
+                        */
+                       if (cstate->bpf_pcap->rfile != NULL) {
+                               /*
+                                * Savefile - check for all three
+                                * possible IPv6 values.
+                                */
+                               b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD);
+                               b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD);
+                               gen_or(b0, b1);
+                               b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN);
+                               gen_or(b0, b1);
+                               return (b1);
+                       } else {
+                               /*
+                                * Live capture, so we only need to
+                                * check for the value used on this
+                                * platform.
+                                */
+#ifdef _WIN32
+                               /*
+                                * Npcap doesn't use Windows's AF_INET6,
+                                * as that collides with AF_IPX on
+                                * some BSDs (both have the value 23).
+                                * Instead, it uses 24.
+                                */
+                               return (gen_loopback_linktype(cstate, 24));
+#else /* _WIN32 */
+#ifdef AF_INET6
+                               return (gen_loopback_linktype(cstate, AF_INET6));
+#else /* AF_INET6 */
+                               /*
+                                * I guess this platform doesn't support
+                                * IPv6, so we just reject all packets.
+                                */
+                               return gen_false(cstate);
+#endif /* AF_INET6 */
+#endif /* _WIN32 */
+                       }
 
                default:
                        /*
@@ -3177,28 +3265,8 @@ gen_linktype(proto)
                         * XXX - support those that have AF_ values
                         * #defined on this platform, at least?
                         */
-                       return gen_false();
-               }
-
-               if (linktype == DLT_NULL || linktype == DLT_ENC) {
-                       /*
-                        * The AF_ value is in host byte order, but
-                        * the BPF interpreter will convert it to
-                        * network byte order.
-                        *
-                        * If this is a save file, and it's from a
-                        * machine with the opposite byte order to
-                        * ours, we byte-swap the AF_ value.
-                        *
-                        * Then we run it through "htonl()", and
-                        * generate code to compare against the result.
-                        */
-                       if (bpf_pcap->sf.rfile != NULL &&
-                           bpf_pcap->sf.swapped)
-                               proto = SWAPLONG(proto);
-                       proto = htonl(proto);
+                       return gen_false(cstate);
                }
-               return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
 
 #ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
@@ -3207,13 +3275,13 @@ gen_linktype(proto)
                 * the packet.
                 */
                if (proto == ETHERTYPE_IP)
-                       return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+                       return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
                            BPF_B, (bpf_int32)AF_INET));
                else if (proto == ETHERTYPE_IPV6)
-                       return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+                       return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
                            BPF_B, (bpf_int32)AF_INET6));
                else
-                       return gen_false();
+                       return gen_false(cstate);
                /*NOTREACHED*/
                break;
 #endif /* HAVE_NET_PFVAR_H */
@@ -3227,34 +3295,34 @@ gen_linktype(proto)
                switch (proto) {
 
                default:
-                       return gen_false();
+                       return gen_false(cstate);
 
                case ETHERTYPE_IPV6:
-                       return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                (bpf_int32)ARCTYPE_INET6));
 
                case ETHERTYPE_IP:
-                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                     (bpf_int32)ARCTYPE_IP);
-                       b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                     (bpf_int32)ARCTYPE_IP_OLD);
                        gen_or(b0, b1);
                        return (b1);
 
                case ETHERTYPE_ARP:
-                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                     (bpf_int32)ARCTYPE_ARP);
-                       b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                     (bpf_int32)ARCTYPE_ARP_OLD);
                        gen_or(b0, b1);
                        return (b1);
 
                case ETHERTYPE_REVARP:
-                       return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                        (bpf_int32)ARCTYPE_REVARP));
 
                case ETHERTYPE_ATALK:
-                       return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+                       return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
                                        (bpf_int32)ARCTYPE_ATALK));
                }
                /*NOTREACHED*/
@@ -3263,9 +3331,9 @@ gen_linktype(proto)
        case DLT_LTALK:
                switch (proto) {
                case ETHERTYPE_ATALK:
-                       return gen_true();
+                       return gen_true(cstate);
                default:
-                       return gen_false();
+                       return gen_false(cstate);
                }
                /*NOTREACHED*/
                break;
@@ -3281,13 +3349,13 @@ gen_linktype(proto)
                        /*
                         * Check for the special NLPID for IP.
                         */
-                       return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
+                       return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
 
                case ETHERTYPE_IPV6:
                        /*
                         * Check for the special NLPID for IPv6.
                         */
-                       return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
+                       return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
 
                case LLCSAP_ISONS:
                        /*
@@ -3301,21 +3369,21 @@ gen_linktype(proto)
                         * control field of UI, i.e. 0x03 followed
                         * by the NLPID.
                         */
-                       b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
-                       b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
-                       b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
+                       b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
+                       b1 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
+                       b2 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
                        gen_or(b1, b2);
                        gen_or(b0, b2);
                        return b2;
 
                default:
-                       return gen_false();
+                       return gen_false(cstate);
                }
                /*NOTREACHED*/
                break;
 
        case DLT_MFR:
-               bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
+               bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
 
         case DLT_JUNIPER_MFR:
         case DLT_JUNIPER_MLFR:
@@ -3347,83 +3415,104 @@ gen_linktype(proto)
  &nb