Imported Upstream version 1.3.0 upstream/1.3.0
authorAnas Nashif <anas.nashif@intel.com>
Sun, 4 Nov 2012 14:54:55 +0000 (06:54 -0800)
committerAnas Nashif <anas.nashif@intel.com>
Sun, 4 Nov 2012 14:54:55 +0000 (06:54 -0800)
222 files changed:
CHANGES [new file with mode: 0644]
CREDITS [new file with mode: 0644]
ChmodBPF/ChmodBPF [new file with mode: 0755]
ChmodBPF/StartupParameters.plist [new file with mode: 0644]
INSTALL.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
README [new file with mode: 0644]
README.Win32 [new file with mode: 0644]
README.aix [new file with mode: 0644]
README.dag [new file with mode: 0644]
README.hpux [new file with mode: 0644]
README.linux [new file with mode: 0644]
README.macosx [new file with mode: 0644]
README.septel [new file with mode: 0644]
README.sita [new file with mode: 0644]
README.tru64 [new file with mode: 0644]
SUNOS4/nit_if.o.sparc [new file with mode: 0644]
SUNOS4/nit_if.o.sun3 [new file with mode: 0644]
SUNOS4/nit_if.o.sun4c.4.0.3c [new file with mode: 0644]
TODO [new file with mode: 0644]
VERSION [new file with mode: 0644]
Win32/Include/Gnuc.h [new file with mode: 0644]
Win32/Include/addrinfo.h [new file with mode: 0644]
Win32/Include/arpa/nameser.h [new file with mode: 0644]
Win32/Include/bittypes.h [new file with mode: 0644]
Win32/Include/cdecl_ext.h [new file with mode: 0644]
Win32/Include/inetprivate.h [new file with mode: 0644]
Win32/Include/ip6_misc.h [new file with mode: 0644]
Win32/Include/net/if.h [new file with mode: 0644]
Win32/Include/net/netdb.h [new file with mode: 0644]
Win32/Include/net/paths.h [new file with mode: 0644]
Win32/Include/sockstorage.h [new file with mode: 0644]
Win32/Prj/libpcap.dsp [new file with mode: 0644]
Win32/Prj/libpcap.dsw [new file with mode: 0644]
Win32/Src/ffs.c [new file with mode: 0644]
Win32/Src/gai_strerror.c [new file with mode: 0644]
Win32/Src/getaddrinfo.c [new file with mode: 0644]
Win32/Src/getnetbynm.c [new file with mode: 0644]
Win32/Src/getnetent.c [new file with mode: 0644]
Win32/Src/getopt.c [new file with mode: 0644]
Win32/Src/getservent.c [new file with mode: 0644]
Win32/Src/inet_aton.c [new file with mode: 0644]
Win32/Src/inet_net.c [new file with mode: 0644]
Win32/Src/inet_pton.c [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
arcnet.h [new file with mode: 0644]
atmuni31.h [new file with mode: 0644]
bpf/net/bpf_filter.c [new file with mode: 0644]
bpf_dump.c [new file with mode: 0644]
bpf_image.c [new file with mode: 0644]
chmod_bpf [new file with mode: 0755]
config.guess [new file with mode: 0755]
config.h.in [new file with mode: 0644]
config.sub [new file with mode: 0755]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
dlpisubs.c [new file with mode: 0644]
dlpisubs.h [new file with mode: 0644]
etherent.c [new file with mode: 0644]
ethertype.h [new file with mode: 0644]
fad-getad.c [new file with mode: 0644]
fad-gifc.c [new file with mode: 0644]
fad-glifc.c [new file with mode: 0644]
fad-null.c [new file with mode: 0644]
fad-sita.c [new file with mode: 0644]
fad-win32.c [new file with mode: 0644]
gencode.c [new file with mode: 0644]
gencode.h [new file with mode: 0644]
grammar.y [new file with mode: 0644]
ieee80211.h [new file with mode: 0644]
inet.c [new file with mode: 0644]
install-sh [new file with mode: 0755]
lbl/os-aix4.h [new file with mode: 0644]
lbl/os-hpux11.h [new file with mode: 0644]
lbl/os-osf4.h [new file with mode: 0644]
lbl/os-osf5.h [new file with mode: 0644]
lbl/os-solaris2.h [new file with mode: 0644]
lbl/os-sunos4.h [new file with mode: 0644]
lbl/os-ultrix4.h [new file with mode: 0644]
llc.h [new file with mode: 0644]
missing/snprintf.c [new file with mode: 0644]
mkdep [new file with mode: 0755]
msdos/bin2c.c [new file with mode: 0644]
msdos/common.dj [new file with mode: 0644]
msdos/makefile [new file with mode: 0644]
msdos/makefile.dj [new file with mode: 0644]
msdos/makefile.wc [new file with mode: 0644]
msdos/ndis2.c [new file with mode: 0644]
msdos/ndis2.h [new file with mode: 0644]
msdos/ndis_0.asm [new file with mode: 0644]
msdos/pkt_rx0.asm [new file with mode: 0644]
msdos/pkt_rx1.s [new file with mode: 0644]
msdos/pktdrvr.c [new file with mode: 0644]
msdos/pktdrvr.h [new file with mode: 0644]
msdos/readme.dos [new file with mode: 0644]
nametoaddr.c [new file with mode: 0644]
nlpid.h [new file with mode: 0644]
optimize.c [new file with mode: 0644]
org.tcpdump.chmod_bpf.plist [new file with mode: 0644]
packaging/pcap.spec.in [new file with mode: 0644]
pcap-bpf.c [new file with mode: 0644]
pcap-bpf.h [new file with mode: 0644]
pcap-bt-linux.c [new file with mode: 0644]
pcap-bt-linux.h [new file with mode: 0644]
pcap-can-linux.c [new file with mode: 0644]
pcap-can-linux.h [new file with mode: 0644]
pcap-canusb-linux.c [new file with mode: 0644]
pcap-canusb-linux.h [new file with mode: 0644]
pcap-common.c [new file with mode: 0644]
pcap-common.h [new file with mode: 0644]
pcap-config.1 [new file with mode: 0644]
pcap-config.in [new file with mode: 0644]
pcap-dag.c [new file with mode: 0644]
pcap-dag.h [new file with mode: 0644]
pcap-dlpi.c [new file with mode: 0644]
pcap-dos.c [new file with mode: 0644]
pcap-dos.h [new file with mode: 0644]
pcap-enet.c [new file with mode: 0644]
pcap-filter.manmisc.in [new file with mode: 0644]
pcap-int.h [new file with mode: 0644]
pcap-libdlpi.c [new file with mode: 0644]
pcap-linktype.manmisc.in [new file with mode: 0644]
pcap-linux.c [new file with mode: 0644]
pcap-namedb.h [new file with mode: 0644]
pcap-netfilter-linux.c [new file with mode: 0644]
pcap-netfilter-linux.h [new file with mode: 0644]
pcap-nit.c [new file with mode: 0644]
pcap-null.c [new file with mode: 0644]
pcap-pf.c [new file with mode: 0644]
pcap-savefile.manfile.in [new file with mode: 0644]
pcap-septel.c [new file with mode: 0644]
pcap-septel.h [new file with mode: 0644]
pcap-sita.c [new file with mode: 0644]
pcap-sita.h [new file with mode: 0644]
pcap-sita.html [new file with mode: 0644]
pcap-snf.c [new file with mode: 0644]
pcap-snf.h [new file with mode: 0644]
pcap-snit.c [new file with mode: 0644]
pcap-snoop.c [new file with mode: 0644]
pcap-stdinc.h [new file with mode: 0644]
pcap-tstamp.manmisc.in [new file with mode: 0644]
pcap-usb-linux.c [new file with mode: 0644]
pcap-usb-linux.h [new file with mode: 0644]
pcap-win32.c [new file with mode: 0644]
pcap.3pcap.in [new file with mode: 0644]
pcap.c [new file with mode: 0644]
pcap.h [new file with mode: 0644]
pcap/bluetooth.h [new file with mode: 0644]
pcap/bpf.h [new file with mode: 0644]
pcap/ipnet.h [new file with mode: 0644]
pcap/namedb.h [new file with mode: 0644]
pcap/pcap.h [new file with mode: 0644]
pcap/sll.h [new file with mode: 0644]
pcap/usb.h [new file with mode: 0644]
pcap/vlan.h [new file with mode: 0644]
pcap_activate.3pcap [new file with mode: 0644]
pcap_breakloop.3pcap [new file with mode: 0644]
pcap_can_set_rfmon.3pcap [new file with mode: 0644]
pcap_close.3pcap [new file with mode: 0644]
pcap_compile.3pcap.in [new file with mode: 0644]
pcap_create.3pcap [new file with mode: 0644]
pcap_datalink.3pcap.in [new file with mode: 0644]
pcap_datalink_name_to_val.3pcap [new file with mode: 0644]
pcap_datalink_val_to_name.3pcap [new file with mode: 0644]
pcap_dump.3pcap [new file with mode: 0644]
pcap_dump_close.3pcap [new file with mode: 0644]
pcap_dump_file.3pcap [new file with mode: 0644]
pcap_dump_flush.3pcap [new file with mode: 0644]
pcap_dump_ftell.3pcap [new file with mode: 0644]
pcap_dump_open.3pcap.in [new file with mode: 0644]
pcap_file.3pcap [new file with mode: 0644]
pcap_fileno.3pcap [new file with mode: 0644]
pcap_findalldevs.3pcap [new file with mode: 0644]
pcap_freecode.3pcap [new file with mode: 0644]
pcap_get_selectable_fd.3pcap [new file with mode: 0644]
pcap_geterr.3pcap [new file with mode: 0644]
pcap_inject.3pcap [new file with mode: 0644]
pcap_is_swapped.3pcap [new file with mode: 0644]
pcap_lib_version.3pcap [new file with mode: 0644]
pcap_list_datalinks.3pcap.in [new file with mode: 0644]
pcap_list_tstamp_types.3pcap.in [new file with mode: 0644]
pcap_lookupdev.3pcap [new file with mode: 0644]
pcap_lookupnet.3pcap [new file with mode: 0644]
pcap_loop.3pcap [new file with mode: 0644]
pcap_major_version.3pcap [new file with mode: 0644]
pcap_next_ex.3pcap [new file with mode: 0644]
pcap_offline_filter.3pcap [new file with mode: 0644]
pcap_open_dead.3pcap.in [new file with mode: 0644]
pcap_open_live.3pcap [new file with mode: 0644]
pcap_open_offline.3pcap.in [new file with mode: 0644]
pcap_set_buffer_size.3pcap [new file with mode: 0644]
pcap_set_datalink.3pcap [new file with mode: 0644]
pcap_set_promisc.3pcap [new file with mode: 0644]
pcap_set_rfmon.3pcap [new file with mode: 0644]
pcap_set_snaplen.3pcap [new file with mode: 0644]
pcap_set_timeout.3pcap [new file with mode: 0644]
pcap_set_tstamp_type.3pcap.in [new file with mode: 0644]
pcap_setdirection.3pcap [new file with mode: 0644]
pcap_setfilter.3pcap [new file with mode: 0644]
pcap_setnonblock.3pcap [new file with mode: 0644]
pcap_snapshot.3pcap [new file with mode: 0644]
pcap_stats.3pcap [new file with mode: 0644]
pcap_statustostr.3pcap [new file with mode: 0644]
pcap_strerror.3pcap [new file with mode: 0644]
pcap_tstamp_type_name_to_val.3pcap [new file with mode: 0644]
pcap_tstamp_type_val_to_name.3pcap [new file with mode: 0644]
ppp.h [new file with mode: 0644]
runlex.sh [new file with mode: 0755]
savefile.c [new file with mode: 0644]
scanner.l [new file with mode: 0644]
sf-pcap-ng.c [new file with mode: 0644]
sf-pcap-ng.h [new file with mode: 0644]
sf-pcap.c [new file with mode: 0644]
sf-pcap.h [new file with mode: 0644]
sunatmpos.h [new file with mode: 0644]
tests/filtertest.c [new file with mode: 0644]
tests/findalldevstest.c [new file with mode: 0644]
tests/nonblocktest.c [new file with mode: 0644]
tests/opentest.c [new file with mode: 0644]
tests/reactivatetest.c [new file with mode: 0644]
tests/selpolltest.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..4f7fa35
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,672 @@
+Friday  March 30, 2012.  mcr@sandelman.ca
+Summary for 1.3.0 libpcap release
+        Handle DLT_PFSYNC in {FreeBSD, other *BSD+Mac OS X, other}.
+        Linux: Don't fail if netfilter isn't enabled in the kernel.
+        Add new link-layer type for NFC Forum LLCP.
+        Put the CANUSB stuff into EXTRA_DIST, so it shows up in the release tarball.
+        Add LINKTYPE_NG40/DLT_NG40.
+        Add DLT_MPEG_2_TS/LINKTYPE_MPEG_2_TS for MPEG-2 transport streams.
+        [PATCH] Fix AIX-3.5 crash with read failure during stress
+        AIX fixes.
+        Introduce --disable-shared configure option.
+        Added initial support for canusb devices.
+        Include the pcap(3PCAP) additions as 1.2.1 changes.
+        many updates to documentation: pcap.3pcap.in
+        Improve 'inbound'/'outbound' capture filters under Linux.
+        Note the cleanup of handling of new DLT_/LINKTYPE_ values.
+        On Lion, don't build for PPC.
+        For mac80211 devices we need to clean up monitor mode on exit.
+
+Friday  December 9, 2011.  guy@alum.mit.edu.
+Summary for 1.2.1 libpcap release
+       Update README file.
+       Fix typoes in README.linux file.
+       Clean up some compiler warnings.
+       Fix Linux compile problems and tests for ethtool.h.
+       Treat Debian/kFreeBSD and GNU/Hurd as systems with GNU
+        toolchains.
+       Support 802.1 QinQ as a form of VLAN in filters.
+       Treat "carp" as equivalent to "vrrp" in filters.
+       Fix code generated for "ip6 protochain".
+       Add some new link-layer header types.
+       Support capturing NetFilter log messages on Linux.
+       Clean up some error messages.
+       Turn off monitor mode on exit for mac80211 interfaces on Linux.
+       Fix problems turning monitor mode on for non-mac80211 interfaces
+        on Linux.
+       Properly fail if /sys/class/net or /proc/net/dev exist but can't
+        be opened.
+       Fail if pcap_activate() is called on an already-activated
+        pcap_t, and add a test program for that.
+       Fix filtering in pcap-ng files.
+       Don't build for PowerPC on Mac OS X Lion.
+       Simplify handling of new DLT_/LINKTYPE_ values.
+       Expand pcap(3PCAP) man page.
+
+Sunday  July 24, 2011.  mcr@sandelman.ca.
+Summary for 1.2 libpcap release
+        All of the changes listed below for 1.1.1 and 1.1.2.
+        Changes to error handling for pcap_findalldevs().
+        Fix the calculation of the frame size in memory-mapped captures.
+        Add a link-layer header type for STANAG 5066 D_PDUs.
+        Add a link-layer type for a variant of 3GPP TS 27.010.
+        Noted real nature of LINKTYPE_ARCNET.
+        Add a link-layer type for DVB-CI.
+        Fix configure-script discovery of VLAN acceleration support.
+         see http://netoptimizer.blogspot.com/2010/09/tcpdump-vs-vlan-tags.html
+        Linux, HP-UX, AIX, NetBSD and OpenBSD compilation/conflict fixes.
+        Protect against including AIX 5.x's <net/bpf.h> having been included.
+        Add DLT_DBUS, for raw D-Bus messages.
+        Treat either EPERM or EACCES as "no soup for you".
+        Changes to permissions on DLPI systems.
+        Add DLT_IEEE802_15_4_NOFCS for 802.15.4 interfaces.
+
+Fri.    August 6, 2010.  guy@alum.mit.edu.
+Summary for 1.1.2 libpcap release
+       Return DLT_ values, not raw LINKTYPE_ values from
+         pcap_datalink() when reading pcap-ng files
+       Add support for "wlan ra" and "wlan ta", to check the RA and TA
+         of WLAN frames that have them
+       Don't crash if "wlan addr{1,2,3,4}" are used without 802.11
+         headers
+       Do filtering on USB and Bluetooth capturing
+       On FreeBSD/SPARC64, use -fPIC - it's apparently necessary
+       Check for valid port numbers (fit in a 16-bit unsigned field) in
+         "port" filters
+       Reject attempts to put savefiles into non-blocking mode
+       Check for "no such device" for the "get the media types" ioctl
+         in *BSD
+       Improve error messages from bpf_open(), and let it do the error
+         handling
+       Return more specific errors from pcap_can_set_rfmon(); fix
+         documentation
+       Update description fetching code for FreeBSD, fix code for
+         OpenBSD
+       Ignore /sys/net/dev files if we get ENODEV for them, not just
+         ENXIO; fixes handling of bonding devices on Linux
+       Fix check for a constant 0 argument to BPF_DIV
+       Use the right version of ar when cross-building
+       Free any filter set on a savefile when the savefile is closed
+       Include the CFLAGS setting when configure was run in the
+         compiler flags
+       Add support for 802.15.4 interfaces on Linux
+
+Thu.    April 1, 2010.  guy@alum.mit.edu.
+Summary for 1.1.1 libpcap release
+       Update CHANGES to reflect more of the changes in 1.1.0.
+       Fix build on RHEL5.
+       Fix shared library build on AIX.
+
+Thu.   March 11, 2010.  ken@netfunctional.ca/guy@alum.mit.edu.
+Summary for 1.1.0 libpcap release
+       Add SocketCAN capture support
+       Add Myricom SNF API support
+       Update Endace DAG and ERF support
+       Add support for shared libraries on Solaris, HP-UX, and AIX
+       Build, install, and un-install shared libraries by default;
+         don't build/install shared libraries on platforms we don't support
+       Fix building from a directory other than the source directory
+       Fix compiler warnings and builds on some platforms
+       Update config.guess and config.sub
+       Support monitor mode on mac80211 devices on Linux
+       Fix USB memory-mapped capturing on Linux; it requires a new DLT_
+         value
+       On Linux, scan /sys/class/net for devices if we have it; scan
+         it, or /proc/net/dev if we don't have /sys/class/net, even if
+         we have getifaddrs(), as it'll find interfaces with no
+         addresses
+       Add limited support for reading pcap-ng files
+       Fix BPF driver-loading error handling on AIX
+       Support getting the full-length interface description on FreeBSD
+       In the lexical analyzer, free up any addrinfo structure we got back
+         from getaddrinfo().
+       Add support for BPF and libdlpi in OpenSolaris (and SXCE)
+       Hyphenate "link-layer" everywhere
+       Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations
+       In pcap_read_linux_mmap(), if there are no frames available, call
+         poll() even if we're in non-blocking mode, so we pick up
+         errors, and check for the errors in question.
+       Note that poll() works on BPF devices is Snow Leopard
+       If an ENXIO or ENETDOWN is received, it may mean the device has
+         gone away.  Deal with it.
+       For BPF, raise the default capture buffer size to from 32k to 512k
+       Support ps_ifdrop on Linux
+       Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile
+        under cygwin.
+       Changes to Linux mmapped captures.
+       Fix bug where create_ring would fail for particular snaplen and
+         buffer size combinations
+       Update pcap-config so that it handles libpcap requiring
+         additional libraries
+       Add workaround for threadsafeness on Windows
+       Add missing mapping for DLT_ENC <-> LINKTYPE_ENC
+       DLT: Add DLT_CAN_SOCKETCAN
+       DLT: Add Solaris ipnet
+       Don't check for DLT_IPNET if it's not defined
+       Add link-layer types for Fibre Channel FC-2
+       Add link-layer types for Wireless HART
+       Add link-layer types for AOS
+       Add link-layer types for DECT
+       Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups)
+       Install headers unconditionally, and include vlan.h/bluetooth.h if
+         enabled
+       Autoconf fixes+cleanup
+       Support enabling/disabling bluetooth (--{en,dis}able-bluetooth)
+       Support disabling SITA support (--without-sita)
+       Return -1 on failure to create packet ring (if supported but
+         creation failed)
+       Fix handling of 'any' device, so that it can be opened, and no longer
+         attempt to open it in Monitor mode
+       Add support for snapshot length for USB Memory-Mapped Interface
+       Fix configure and build on recent Linux kernels
+       Fix memory-mapped Linux capture to support pcap_next() and
+         pcap_next_ex()
+       Fixes for Linux USB capture
+       DLT: Add DLT_LINUX_EVDEV
+       DLT: Add DLT_GSMTAP_UM
+       DLT: Add DLT_GSMTAP_ABIS
+
+Mon.    October 27, 2008.  ken@netfunctional.ca.  Summary for 1.0.0 libpcap release
+       Compile with IPv6 support by default
+       Compile with large file support on by default
+       Add pcap-config script, which deals with -I/-L flags for compiling
+       DLT: Add IPMB
+       DLT: Add LAPD
+       DLT: Add AX25 (AX.25 w/KISS header)
+       DLT: Add JUNIPER_ST
+       802.15.4 support
+       Variable length 802.11 header 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
+       Support for setting buffer size when opening devices
+       Support for setting monitor mode when opening 802.11 devices
+       Better support for dealing with VLAN tagging/stripping on Linux
+       Fix dynamic library support on OSX
+       Return PCAP_ERROR_IFACE_NOT_UP if the interface isn't 'UP', so applications
+        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 
+        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
+       On Solaris, support 'passive mode' on systems that support it
+       Fixes to autoconf and general build environment
+       Man page reorganization + cleanup
+       Autogenerate VERSION numbers better
+
+Mon.    September 10, 2007.  ken@xelerance.com.  Summary for 0.9.8 libpcap release
+        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 
+         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 
+        backwards compatibility.
+       Add Bluetooth support
+       Add USB capturing support on Linux
+       Add support for the binary USB sniffing interface in Linux
+       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 
+        all the DLT_ and LINKTYPE_ values that the main branch does
+       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 
+        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 
+        ".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 
+        switching to libtool.
+       Add support for new DAG ERF types.
+        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. 
+
+Tue.   September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release
+
+       Support for LAPD frames with vISDN
+       Support for ERF on channelized T1/E1 cards via DAG API
+       Fix capitalization that caused issues crossc compiling on Linux
+       Better failure detection on PacketGetAdapterNames()
+       Fixes for MPLS packet generation (link layer)
+       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  
+       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 
+        PF_PACKET sockets.
+       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 
+        MingW32.
+
+Mon.   September 5, 2005.  ken@xelerance.com. Summary for 0.9.4 libpcap release
+
+       Support for radiotap on Linux (Mike Kershaw)
+       Fixes for HP-UX
+       Support for additional Juniper link-layer types
+       Fixes for filters on MPLS-encapsulated packets
+       "vlan" filter fixed
+       "pppoed" and "pppoes" filters added; the latter modifies later
+       parts of the filter expression to look at the PPP headers and
+       headers in the PPP payload
+
+Tue.   July 5, 2005.  ken@xelerance.com. Summary for 0.9.3 libpcap release
+
+       Fixes for compiling on nearly every platform,
+               including improved 64bit support
+       MSDOS Support
+       Add support for sending packets
+       OpenBSD pf format support
+       IrDA capture (Linux only)
+
+Tue.   March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release
+
+       Fixed minor problem in gencode.c that would appear on 64-bit
+       platforms.
+       Version number is now sane.
+
+Mon.   March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release
+
+       updates for autoconf 2.5
+       fixes for ppp interfaces for freebsd 4.1
+       pcap gencode can generate code for 802.11, IEEE1394, and pflog.
+
+Wed.   November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release
+
+       added pcap_findalldevs()
+       Win32 patches from NetGroup, Politecnico di Torino (Italy)
+       OpenBSD pf, DLT_PFLOG added
+       Many changes to ATM support.
+       lookup pcap_lookupnet()
+       Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM,
+               DLT_IP_OVER_FC, DLT_FRELAY, others.
+       Sigh.  More AIX wonderfulness.
+       Document updates.
+       Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(),
+                       pcap_list_datalinks(), pcap_set_datalink(),
+                       pcap_lib_version(), pcap_datalink_val_to_name(),
+                       pcap_datalink_name_to_val(), new error returns.
+
+Tuesday, February 25, 2003. fenner@research.att.com.  0.7.2 release
+
+       Support link types that use 802.2 always, never, and sometimes.
+       Don't decrease the size of the BPF buffer from the default.
+       Support frame relay.
+       Handle 32-bit timestamps in DLPI, and pass the right buffer size.
+       Handle Linux systems with modern kernel but without
+        SOL_PACKET in the userland headers.
+       Linux support for ARPHRD_RAWHDLC.
+       Handle 32-bit timestamps in snoop.
+       Support eg (Octane/O2xxx/O3xxx Gigabit) devices.
+       Add new reserved DLT types.
+
+Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release
+
+       Added pcap_findalldevs() call to get list of interfaces in a MI way.
+
+       pcap_stats() has been documented as to what its counters mean on
+       each platform.
+
+Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release
+
+       New Linux libpcap implementation, which, in 2.2 and later
+       kernels, uses PF_PACKET sockets and supports kernel packet
+       filtering (if compiled into the kernel), and supports the "any"
+       device for capturing on all interfaces.  Cleans up promiscuous
+       mode better on pre-2.2 kernels, and has various other fixes
+       (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better,
+       doesn't show duplicate packets on loopback interface, etc.).
+
+       Fixed HP-UX libpcap implementation to correctly get the PPA for
+       an interface, to allow interfaces to be opened by interface name.
+
+       libpcap savefiles have system-independent link-layer type values
+       in the header, rather than sometimes platform-dependent DLT_
+       values, to make it easier to exchange capture files between
+       different OSes.
+
+       Non-standard capture files produced by some Linux tcpdumps, e.g.
+       the one from Red Hat Linux 6.2 and later, can now be read.
+
+       Updated autoconf stock files.
+
+       Filter expressions can filter on VLAN IDs and various OSI
+       protocols, and work on Token Ring (with non-source-routed
+       packets).
+
+       "pcap_open_dead()" added to allow compiling filter expressions
+       to pcap code without opening a capture device or capture file.
+
+       Header files fixed to allow use in C++ programs.
+
+       Removed dependancy on native headers for packet layout.
+       Removed Linux specific headers that were shipped.
+
+       Security fixes: Strcpy replaced with strlcpy, sprintf replaced
+       with snprintf.
+
+       Fixed bug that could cause subsequent "pcap_compile()"s to fail
+       erroneously after one compile failed.
+
+       Assorted other bug fixes.
+
+       README.aix and README.linux files added to describe
+       platform-specific issues.
+
+       "getifaddrs()" rather than SIOCGIFCONF used, if available.
+
+v0.5 Sat Jun 10 11:09:15 PDT 2000
+
+itojun@iijlab.net
+- Brought in KAME IPv6/IPsec bpf compiler.
+- Fixes for NetBSD.
+- Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC),
+  and changes to work around different BSDs having different DLT_ types
+  with the same numeric value.
+
+Assar Westerlund  <assar@sics.se>
+- Building outside the source code tree fixed.
+- Changed to write out time stamps with 32-bit seconds and microseconds
+  fields, regardless of whether those fields are 32 bits or 64 bits in
+  the OS's native "struct timeval".
+- Changed "pcap_lookupdev()" to dynamically grow the buffer into which
+  the list of interfaces is read as necessary in order to hold the
+  entire list.
+
+Greg Troxel <gdt@ir.bbn.com>
+- Added a new "pcap_compile_nopcap()", which lets you compile a filter
+  expression into a BPF program without having an open live capture or
+  capture file.
+
+v0.4 Sat Jul 25 12:40:09 PDT 1998
+
+- Fix endian problem with DLT_NULL devices. From FreeBSD via Bill
+  Fenner (fenner@parc.xerox.com)
+
+- Fix alignment problem with FDDI under DLPI. This was causing core
+  dumps under Solaris.
+
+- Added configure options to disable flex and bison. Resulted from a
+  bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added
+  options to disable gcc and to force a particular packet capture type.
+
+- Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks
+  to John Hawkinson (jhawk@mit.edu)
+
+- Change Linux PPP and SLIP to use DLT_RAW since the kernel does not
+  supply any "link layer" data.
+
+- Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type.
+  Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch)
+
+- Change IRIX PPP to use DLT_RAW since the kernel does not supply any
+  "link layer" data.
+
+- Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header
+  formats.
+
+- Added some new SGI snoop interface types. Thanks to Steve Alexander
+  (sca@refugee.engr.sgi.com)
+
+- Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to
+  Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no)
+
+- Fddi supports broadcast as reported by Jeff Macdonald
+  (jeff@iacnet.com). Also correct ieee802 and arcnet.
+
+- Determine Linux pcap buffer size at run time or else it might not be
+  big enough for some interface types (e.g. FDDI). Thanks to Jes
+  Sorensen (Jes.Sorensen@cern.ch)
+
+- Fix some linux alignment problems.
+
+- Document promisc argument to pcap_open_live(). Reported by Ian Marsh
+  (ianm@sics.se)
+
+- Support Metricom radio packets under Linux. Thanks to Kevin Lai
+  (laik@gunpowder.stanford.edu)
+
+- Bind to interface name under Linux to avoid packets from multiple
+  interfaces on multi-homed hosts. Thanks to Kevin Lai
+  (laik@gunpowder.stanford.edu)
+
+- Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts
+  (rroberts@muller.com)
+
+- Fixed an uninitialized memory reference found by Kent Vander Velden
+  (graphix@iastate.edu)
+
+- Fixed lex pattern for IDs to allow leading digits. As reported by
+  Theo de Raadt (deraadt@cvs.openbsd.org)
+
+- Fixed Linux include file problems when using GNU libc.
+
+- Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it.
+  Reported reported by Eric Jacksch (jacksch@tenebris.ca)
+
+- Fixed bug in pcap_dispatch() that kept it from returning on packet
+  timeouts.
+
+- Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check
+  for "lo" followed by an eos or digit (newer versions of Linux
+  apparently call the loopback "lo" instead of "lo0").
+
+- Fixed Linux networking include files to use ints instead of longs to
+  avoid problems with 64 bit longs on the alpha. Thanks to Cristian
+  Gafton (gafton@redhat.com)
+
+v0.3 Sat Nov 30 20:56:27 PST 1996
+
+- Added Linux support.
+
+- Fixed savefile bugs.
+
+- Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl)
+
+- Add support for bpf kernel port filters.
+
+- Remove duplicate atalk protocol table entry. Thanks to Christian
+  Hopps (chopps@water.emich.edu)
+
+- Fixed pcap_lookupdev() to ignore nonexistent devices. This was
+  reported to happen under BSD/OS by David Vincenzetti
+  (vince@cryptonet.it)
+
+- Avoid solaris compiler warnings. Thanks to Bruce Barnett
+  (barnett@grymoire.crd.ge.com)
+
+v0.2.1 Sun Jul 14 03:02:26 PDT 1996
+
+- Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram
+  (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com)
+
+- Added support for SINIX. Thanks to Andrej Borsenkow
+  (borsenkow.msk@sni.de)
+
+- Fixes for AIX (although this system is not yet supported). Thanks to
+  John Hawkinson (jhawk@mit.edu)
+
+- Use autoconf's idea of the top level directory in install targets.
+  Thanks to John Hawkinson.
+
+- Add missing autoconf packet capture result message. Thanks to Bill
+  Fenner (fenner@parc.xerox.com)
+
+- Fixed padding problems in the pf module.
+
+- Fixed some more alignment problems on the alpha.
+
+- Added explicit netmask support. Thanks to Steve Nuchia
+  (steve@research.oknet.com)
+
+- Fixed to handle raw ip addresses such as 0.0.0.1 without "left
+  justifing"
+
+- Add "sca" keyword (for DEC cluster services) as suggested by Terry
+  Kennedy (terry@spcvxa.spc.edu)
+
+- Add "atalk" keyword as suggested by John Hawkinson.
+
+- Add "igrp" keyword.
+
+- Fixed HID definition in grammar.y to be a string, not a value.
+
+- Use $CC when checking gcc version. Thanks to Carl Lindberg
+  (carl_lindberg@blacksmith.com)
+
+- Removed obsolete reference to pcap_immediate() from the man page.
+  Michael Stolarchuk (mts@terminator.rs.itd.umich.edu)
+
+- DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig
+  (jch@bsdi.com)
+
+v0.2 Sun Jun 23 02:28:42 PDT 1996
+
+- Add support for HP-UX. Resulted from code contributed by Tom Murray
+  (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville
+  (philipp@res.enst.fr)
+
+- Update INSTALL with a reminder to install include files. Thanks to
+  Mark Andrews (mandrews@aw.sgi.com)
+
+- Fix bpf compiler alignment bug on the alpha.
+
+- Use autoconf to detect architectures that can't handle misaligned
+  accesses.
+
+- Added loopback support for snoop. Resulted from report Steve
+  Alexander (sca@engr.sgi.com)
+
+v0.1 Fri Apr 28 18:11:03 PDT 1995
+
+- Fixed compiler and optimizer bugs.  The BPF filter engine uses unsigned
+  comparison operators, while the code generator and optimizer assumed
+  signed semantics in several places.  Thanks to Charlie Slater
+  (cslater@imatek.com) for pointing this out.
+
+- Removed FDDI ifdef's, they aren't really needed. Resulted from report
+  by Gary Veum (veum@boa.gsfc.nasa.gov).
+
+- Add pcap-null.c which allows offline use of libpcap on systems that
+  don't support live package capture. This feature resulting from a
+  request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl).
+
+- Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin
+  (Pascal.Hennequin@hugo.int-evry.fr).
+
+- Port to GNU autoconf.
+
+- Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming
+  Johansen (fsj@csd.cri.dk).
+
+- Handle multi-digit interface unit numbers (aka ppa's) under dlpi.
+  Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu).
+
+- Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report
+  by Jeff Murphy (jcmurphy@acsu.buffalo.edu).
+
+- Add support for "long jumps". Thanks to Jeffrey Mogul
+  (mogul@pa.dec.com).
+
+- Fix minor problems when compiling with BDEBUG as noticed by Scott
+  Bertilson (scott@unet.umn.edu).
+
+- Declare sys_errlist "const char *const" to avoid problems under
+  FreeBSD. Resulted from report by jher@eden.com.
+
+v0.0.6 Fri Apr 28 04:07:13 PDT 1995
+
+- Add missing variable declaration missing from 0.0.6
+
+v0.0.5 Fri Apr 28 00:22:21 PDT 1995
+
+- Workaround for problems when pcap_read() returns 0 due to the timeout
+  expiring.
+
+v0.0.4 Thu Apr 20 20:41:48 PDT 1995
+
+- Change configuration to not use gcc v2 flags with gcc v1.
+
+- Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next()
+  should also return 0. Thanks to Richard Stevens (rstevens@noao.edu).
+
+- Fixed configure to test for snoop before dlpi to avoid problems under
+  IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com).
+
+- Hack around deficiency in Ultrix's make.
+
+- Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle
+  savefiles that have more than snapshot bytes of data in them (so we
+  can read old savefiles) and avoid writing such files.
+
+- Added checkioctl which is used with gcc to check that the
+  "fixincludes" script has been run.
+
+v0.0.3 Tue Oct 18 18:13:46 PDT 1994
+
+- Fixed configure to test for snoop before dlpi to avoid problems under
+  IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com).
+
+v0.0.2 Wed Oct 12 20:56:37 PDT 1994
+
+- Implement timeout in the dlpi pcap_open_live(). Thanks to Richard
+  Stevens.
+
+- Determine pcap link type from dlpi media type. Resulted from report
+  by Mahesh Jethanandani (mahesh@npix.com).
+
+v0.0.1 Fri Jun 24 14:50:57 PDT 1994
+
+- Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout
+  wasn't being initialized sometimes resulting in an "NIOCSFLAGS:
+  Invalid argument" error under OSF/1. Reported by Matt Day
+  (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com).
+
+- Turn on FDDI support by default.
+
+v0.0 Mon Jun 20 19:20:16 PDT 1994
+
+- Initial release.
+
+- Fixed bug with greater/less keywords, reported by Mark Andrews
+  (mandrews@alias.com).
+
+- Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported
+  by Elan Amir (elan@leeb.cs.berkeley.edu).
+
+- Machines with little-endian byte ordering are supported thanks to
+  Jeff Mogul.
+
+- Add hack for version 2.3 savefiles which don't have caplen and len
+  swapped thanks to Vern Paxson.
+
+- Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson.
+
+- Added length, inbound and outbound keywords.
diff --git a/CREDITS b/CREDITS
new file mode 100644 (file)
index 0000000..cfe84ba
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,155 @@
+This file lists people who have contributed to libpcap:
+
+The current maintainers:
+    Bill Fenner                   <fenner at research dot att dot com>
+    Fulvio Risso                  <risso at polito dot it>
+    Guy Harris                    <guy at alum dot mit dot edu>
+    Hannes Gredler                <hannes at juniper dot net>
+    Michael Richardson            <mcr at sandelman dot ottawa dot on dot ca>
+
+Additional people who have contributed patches:
+
+    Alan Bawden                   <Alan at LCS dot MIT dot EDU>
+    Albert Chin                   <china at thewrittenword dot com>
+    Alexander 'Leo' Bergolth      <Leo dot Bergolth at wu-wien dot ac dot at>
+    Alexey Kuznetsov              <kuznet at ms2 dot inr dot ac dot ru>
+    Alon Bar-Lev                  <alonbl at sourceforge dot net>
+    Andrew Brown                  <atatat at atatdot dot net>
+                                  <andy-1 at sourceforge dot net>
+    Antti Kantee                  <pooka at netbsd dot org>
+    Arien Vijn                    <arienvijn at sourceforge dot net>
+    Arkadiusz Miskiewicz          <misiek at pld dot org dot pl>
+    Armando L. Caro Jr.           <acaro at mail dot eecis dot udel dot edu>
+    Assar Westerlund              <assar at sics dot se>
+    Brian Ginsbach                <ginsbach at cray dot com>
+    Charles M. Hannum             <mycroft at netbsd dot org>
+    Chris G. Demetriou            <cgd at netbsd dot org>
+    Chris Lightfoot               <cwrl at users dot sourceforge dot net>
+    Chris Maynard                 <Chris dot Maynard at gtech dot com>
+    Chris Pepper                  <pepper at mail dot reppep dot com>
+    Christian Bell                <csbell at myri dot com>
+    Christian Peron               <csjp at freebsd dot org>
+    Daniele Orlandi               <daniele at orlandi dot com>
+    Darren Reed                   <darrenr at sun dot com>
+    David Kaelbling               <drk at sgi dot com>
+    David Young                   <dyoung at ojctech dot com>
+    Dean Gaudet                   <dean at arctic dot org>
+    dhruv                         <rsrivat at sourceforge dot net>
+    Don Ebright                   <Don dot Ebright at compuware dot com> 
+    Dug Song                      <dugsong at monkey dot org>
+    Dustin Spicuzza               <dustin at virtualroadside dot com>
+    Eric Anderson                 <anderse at hpl dot hp dot com>
+    Erik de Castro Lopo           <erik dot de dot castro dot lopo at sensorynetworks dot com>
+    Felix Obenhuber               <felix at obenhuber dot de>
+    Florent Drouin                <Florent dot Drouin at alcatel-lucent dot fr>
+    Franz Schaefer                <schaefer at mond dot at>
+    frederich                     <frederich at sourceforge dot net>
+    Fulko Hew                     <fulko dot hew at gmail dot com>
+    Fumiyuki Shimizu              <fumifumi at abacustech dot jp>
+    Garrett Cooper                <yaberauneya at sourceforge dot net>
+    Gianluca Varenni              <gianluca dot varenni at gmail dot com>
+    Gilbert Hoyek                 <gil_hoyek at hotmail dot com>
+    Gisle Vanem                   <gvanem at broadpark dot no>
+    Graeme Hewson                 <ghewson at cix dot compulink dot co dot uk>
+    Greg Stark                    <gsstark at mit dot edu>
+    Greg Troxel                   <gdt at ir dot bbn dot com>
+    Gregor Maier                  <gregor at net dot in dot tum dot de>
+    Guillaume Pelat               <endymion_ at users dot sourceforge dot net>
+    Hagen Paul Pfeifer            <hagen at jauu dot net>
+    Henri Doreau                  <hdoreau at sourceforge dot net>
+    Hyung Sik Yoon                <hsyn at kr dot ibm dot com>
+    Igor Khristophorov            <igor at atdot dot org>
+    Jan-Philip Velders            <jpv at veldersjes dot net>
+    Jason R. Thorpe               <thorpej at netbsd dot org>
+    Javier Achirica               <achirica at ttd dot net>
+    Jean Tourrilhes               <jt at hpl dot hp dot com>
+    Jean-Louis Charton            <Jean-Louis.CHARTON at oikialog dot com>
+    Jefferson Ogata               <jogata at nodc dot noaa dot gov>
+    Jesper Dangaard Brouer        <hawk at comx dot dk>
+    Jesper Peterson               <jesper at endace dot com>
+    Joerg Mayer                   <jmayer at loplof dot de>
+    John Bankier                  <jbankier at rainfinity dot com>
+    Jon Lindgren                  <jonl at yubyub dot net>
+    Jon Smirl                     <jonsmirl at gmail dot com>
+    Juergen Schoenwaelder         <schoenw at ibr dot cs dot tu-bs dot de>
+    Julien Moutinho               <julm at savines dot alpes dot fr dot eu dot org>
+    Jung-uk Kim                   <jkim at FreeBSD dot org>
+    Kazushi Sugyo                 <sugyo at pb dot jp dot nec dot com>
+    Klaus Klein                   <kleink at netbsd dot org>
+    Koryn Grant                   <koryn at endace dot com>
+    Kris Katterjohn               <katterjohn at gmail dot com>
+    Krzysztof Halasa              <khc at pm dot waw dot pl>
+    Lorenzo Cavallaro             <sullivan at sikurezza dot org>
+    Loris Degioanni               <loris at netgroup-serv dot polito dot it>
+    Love Hörnquist-Ã…strand        <lha at stacken dot kth dot se>
+    Luis MartinGarcia             <luis dot mgarc at gmail dot com>
+    Maciej W. Rozycki             <macro at ds2 dot pg dot gda dot pl>
+    Marcus Felipe Pereira         <marcus at task dot com dot br>
+    Mark C. Brown                 <mbrown at hp dot com>
+    Mark Pizzolato                <List-tcpdump-workers at subscriptions dot pizzolato dot net>
+    Markus Mayer                  <markus_mayer at sourceforge dot net>
+    Martin Husemann               <martin at netbsd dot org>
+    Márton Németh                 <nm127 at freemail dot hu>
+    Matthew Luckie                <mjl at luckie dot org dot nz>
+    Max Laier                     <max at love2party dot net>
+    Mike Frysinger                <vapier at gmail dot com>
+    Mike Kershaw                  <dragorn at kismetwireless dot net>
+    Mike Wiacek                   <mike at iroot dot net>
+    Miroslav Lichvar              <mlichvar at redhat dot com>
+    Monroe Williams               <monroe at pobox dot com>
+                                  <nvercamm at sourceforge dot net>
+    N. Leiten                     <nleiten at sourceforge dot net>
+    Nicolas Dade                  <ndade at nsd dot dyndns dot org>
+    Octavian Cerna                <tavy at ylabs dot com>
+    Olaf Kirch                    <okir at caldera dot de>
+    Ollie Wild                    <aaw at users dot sourceforge dot net>
+    Onno van der Linden           <onno at simplex dot nl>
+    Paolo Abeni                   <paolo dot abeni at email dot it>
+    Patrick Marie                 <mycroft at virgaria dot org>
+    Patrick McHardy               <kaber at trash not net>
+    Paul Mundt                    <lethal at linux-sh dot org>
+    Pavel Kankovsky               <kan at dcit dot cz>
+    Pawel Pokrywka                <publicpp at gmail dot com>
+    Peter Fales                   <peter at fales-lorenz dot net>
+    Peter Jeremy                  <peter dot jeremy at alcatel dot com dot au>
+    Peter Volkov                  <pva at gentoo dot org>
+    Phil Wood                     <cpw at lanl dot gov>
+    Rafal Maszkowski              <rzm at icm dot edu dot pl>
+                                  <rcb-isis at users dot sourceforge dot net>
+    Richard Stearn                <richard at rns-stearn dot demon dot co dot uk>
+    Rick Jones                    <raj at cup dot hp dot com>
+    Robert Edmonds                <stu-42 at sourceforge dot net>
+    Roberto Mariani               <jelot-tcpdump at jelot dot it>
+    Romain Francoise              <rfrancoise at debian dot org>
+    Sagun Shakya                  <sagun dot shakya at sun dot com>
+    Scott Barron                  <sb125499 at ohiou dot edu>
+    Scott Gifford                 <sgifford at tir dot com>
+    Scott Mcmillan                <scott dot a dot mcmillan at intel dot com>
+    Sebastian Krahmer             <krahmer at cs dot uni-potsdam dot de>
+    Sebastien Roy                 <Sebastien dot Roy at Sun dot COM>
+    Sepherosa Ziehau              <sepherosa at gmail dot com>
+    Shaun Clowes                  <delius at progsoc dot uts dot edu dot au>
+    Solomon Peachy                <pizza at shaftnet dot org>
+    Stefan Hudson                 <hudson at mbay dot net>
+    Stephen Donnelly              <stephen at endace dot com>
+    Takashi Yamamoto              <yamt at mwd dot biglobe dot ne dot jp>
+    Tanaka Shin-ya                <zstanaka at archer dot livedoor dot com>
+    Tobias Poschwatta             <posch at sourceforge dot net>
+    Tony Li                       <tli at procket dot com>
+    Torsten Landschoff            <torsten at debian dot org>
+    Uns Lider                     <unslider at miranda dot org>
+    Uwe Girlich                   <Uwe dot Girlich at philosys dot de>
+    Wesley Shields                <wxs at FreeBSD dot org>
+    Xianjie Zhang                 <xzhang at cup dot hp dot com>
+    Xin Li                        <delphij at FreeBSD dot org>
+    Yen Yen Lim
+    Yvan Vanhullebus              <vanhu at sourceforge dot net>
+    Yoann Vandoorselaere          <yoann at prelude-ids dot org>
+
+The original LBL crew:
+    Steve McCanne
+    Craig Leres
+    Van Jacobson
+
+Past maintainers:
+    Jun-ichiro itojun Hagino         <itojun at iijlab dot net>
diff --git a/ChmodBPF/ChmodBPF b/ChmodBPF/ChmodBPF
new file mode 100755 (executable)
index 0000000..ee37121
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+. /etc/rc.common
+
+StartService ()
+{
+       #
+       # Unfortunately, Mac OS X's devfs is based on the old FreeBSD
+       # one, not the current one, so there's no way to configure it
+       # to create BPF devices with particular owners or groups.
+       # This startup item will make it owned by the admin group,
+       # with permissions rw-rw----, so that anybody in the admin
+       # group can use programs that capture or send raw packets.
+       #
+       # Change this as appropriate for your site, e.g. to make
+       # it owned by a particular user without changing the permissions,
+       # so only that user and the super-user can capture or send raw
+       # packets, or give it the permissions rw-r-----, so that
+       # only the super-user can send raw packets but anybody in the
+       # admin group can capture packets.
+       #
+       chgrp admin /dev/bpf*
+       chmod g+rw /dev/bpf*
+}
+
+StopService ()
+{
+       return 0;
+}
+
+RestartService () { StartService; }
+
+RunService "$1"
diff --git a/ChmodBPF/StartupParameters.plist b/ChmodBPF/StartupParameters.plist
new file mode 100644 (file)
index 0000000..cba2166
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  Description     = "Change BPF permissions";
+  Provides        = ("ChmodBPF");
+}
diff --git a/INSTALL.txt b/INSTALL.txt
new file mode 100644 (file)
index 0000000..58d8e3c
--- /dev/null
@@ -0,0 +1,403 @@
+@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.29 2008-06-12 20:21:51 guy Exp $ (LBL)
+
+To build libpcap, run "./configure" (a shell script). The configure
+script will determine your system attributes and generate an
+appropriate Makefile from Makefile.in. Next run "make". If everything
+goes well you can su to root and run "make install". However, you need
+not install libpcap if you just want to build tcpdump; just make sure
+the tcpdump and libpcap directory trees have the same parent
+directory.
+
+If configure says:
+
+    configure: warning: cannot determine packet capture interface
+    configure: warning: (see INSTALL for more info)
+
+then your system either does not support packet capture or your system
+does support packet capture but libpcap does not support that
+particular type. (If you have HP-UX, see below.) If your system uses a
+packet capture not supported by libpcap, please send us patches; don't
+forget to include an autoconf fragment suitable for use in
+configure.in.
+
+It is possible to override the default packet capture type, although
+the circumstance where this works are limited. For example if you have
+installed bpf under SunOS 4 and wish to build a snit libpcap:
+
+    ./configure --with-pcap=snit
+
+Another example is to force a supported packet capture type in the case
+where the configure scripts fails to detect it.
+
+You will need an ANSI C compiler to build libpcap. The configure script
+will abort if your compiler is not ANSI compliant. If this happens, use
+the GNU C compiler, available via anonymous ftp:
+
+       ftp://ftp.gnu.org/pub/gnu/gcc/
+
+If you use flex, you must use version 2.4.6 or higher. The configure
+script automatically detects the version of flex and will not use it
+unless it is new enough. You can use "flex -V" to see what version you
+have (unless it's really old). The current version of flex is available
+via anonymous ftp:
+
+       ftp://ftp.ee.lbl.gov/flex-*.tar.Z
+
+As of this writing, the current version is 2.5.4.
+
+If you use bison, you must use flex (and visa versa). The configure
+script automatically falls back to lex and yacc if both flex and bison
+are not found.
+
+Sometimes the stock C compiler does not interact well with flex and
+bison. The list of problems includes undefined references for alloca.
+You can get around this by installing gcc or manually disabling flex
+and bison with:
+
+    ./configure --without-flex --without-bison
+
+If your system only has AT&T lex, this is okay unless your libpcap
+program uses other lex/yacc generated code. (Although it's possible to
+map the yy* identifiers with a script, we use flex and bison so we
+don't feel this is necessary.)
+
+Some systems support the Berkeley Packet Filter natively; for example
+out of the box OSF and BSD/OS have bpf. If your system does not support
+bpf, you will need to pick up:
+
+       ftp://ftp.ee.lbl.gov/bpf-*.tar.Z
+
+Note well: you MUST have kernel source for your operating system in
+order to install bpf. An exception is SunOS 4; the bpf distribution
+includes replacement kernel objects for some of the standard SunOS 4
+network device drivers. See the bpf INSTALL document for more
+information.
+
+If you use Solaris, there is a bug with bufmod(7) that is fixed in
+Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the
+broken bufmod(7) results in data be truncated from the FRONT of the
+packet instead of the end.  The work around is to not set a snapshot
+length but this results in performance problems since the entire packet
+is copied to user space. If you must run an older version of Solaris,
+there is a patch available from Sun; ask for bugid 1149065. After
+installing the patch, use "setenv BUFMOD_FIXED" to enable use of
+bufmod(7). However, we recommend you run a more current release of
+Solaris.
+
+If you use the SPARCompiler, you must be careful to not use the
+/usr/ucb/cc interface. If you do, you will get bogus warnings and
+perhaps errors. Either make sure your path has /opt/SUNWspro/bin
+before /usr/ucb or else:
+
+    setenv CC /opt/SUNWspro/bin/cc
+
+before running configure. (You might have to do a "make distclean"
+if you already ran configure once).
+
+Also note that "make depend" won't work; while all of the known
+universe uses -M, the SPARCompiler uses -xM to generate makefile
+dependencies.
+
+If you are trying to do packet capture with a FORE ATM card, you may or
+may not be able to. They usually only release their driver in object
+code so unless their driver supports packet capture, there's not much
+libpcap can do.
+
+If you get an error like:
+
+    tcpdump: recv_ack: bind error 0x???
+
+when using DLPI, look for the DL_ERROR_ACK error return values, usually
+in /usr/include/sys/dlpi.h, and find the corresponding value.
+
+Under {DEC OSF/1, Digital UNIX, Tru64 UNIX}, packet capture must be
+enabled before it can be used.  For instructions on how to enable packet
+filter support, see:
+
+       ftp://ftp.digital.com/pub/Digital/dec-faq/Digital-UNIX
+
+Look for the "How do I configure the Berkeley Packet Filter and capture
+tcpdump traces?" item.
+
+Once you enable packet filter support, your OSF system will support bpf
+natively.
+
+Under Ultrix, packet capture must be enabled before it can be used. For
+instructions on how to enable packet filter support, see:
+
+       ftp://ftp.digital.com/pub/Digital/dec-faq/ultrix
+
+If you use HP-UX, you must have at least version 9 and either the
+version of cc that supports ANSI C (cc -Aa) or else use the GNU C
+compiler. You must also buy the optional streams package. If you don't
+have:
+
+    /usr/include/sys/dlpi.h
+    /usr/include/sys/dlpi_ext.h
+
+then you don't have the streams package. In addition, we believe you
+need to install the "9.X LAN and DLPI drivers cumulative" patch
+(PHNE_6855) to make the version 9 DLPI work with libpcap.
+
+The DLPI streams package is standard starting with HP-UX 10.
+
+The HP implementation of DLPI is a little bit eccentric. Unlike
+Solaris, you must attach /dev/dlpi instead of the specific /dev/*
+network pseudo device entry in order to capture packets. The PPA is
+based on the ifnet "index" number. Under HP-UX 9, it is necessary to
+read /dev/kmem and the kernel symbol file (/hp-ux). Under HP-UX 10,
+DLPI can provide information for determining the PPA. It does not seem
+to be possible to trace the loopback interface. Unlike other DLPI
+implementations, PHYS implies MULTI and SAP and you get an error if you
+try to enable more than one promiscuous mode at a time.
+
+It is impossible to capture outbound packets on HP-UX 9.  To do so on
+HP-UX 10, you will, apparently, need a late "LAN products cumulative
+patch" (at one point, it was claimed that this would be PHNE_18173 for
+s700/10.20; at another point, it was claimed that the required patches
+were PHNE_20892, PHNE_20725 and PHCO_10947, or newer patches), and to do
+so on HP-UX 11 you will, apparently, need the latest lancommon/DLPI
+patches and the latest driver patch for the interface(s) in use on HP-UX
+11 (at one point, it was claimed that patches PHNE_19766, PHNE_19826,
+PHNE_20008, and PHNE_20735 did the trick).
+
+Furthermore, on HP-UX 10, you will need to turn on a kernel switch by
+doing
+
+       echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem
+
+You would have to arrange that this happen on reboots; the right way to
+do that would probably be to put it into an executable script file
+"/sbin/init.d/outbound_promisc" and making
+"/sbin/rc2.d/S350outbound_promisc" a symbolic link to that script.
+
+Finally, testing shows that there can't be more than one simultaneous
+DLPI user per network interface.
+
+If you use Linux, this version of libpcap is known to compile and run
+under Red Hat 4.0 with the 2.0.25 kernel.  It may work with earlier 2.X
+versions but is guaranteed not to work with 1.X kernels.  Running more
+than one libpcap program at a time, on a system with a 2.0.X kernel, can
+cause problems since promiscuous mode is implemented by twiddling the
+interface flags from the libpcap application; the packet capture
+mechanism in the 2.2 and later kernels doesn't have this problem.  Also,
+packet timestamps aren't very good.  This appears to be due to haphazard
+handling of the timestamp in the kernel.
+
+Note well: there is rumoured to be a version of tcpdump floating around
+called 3.0.3 that includes libpcap and is supposed to support Linux. 
+You should be advised that neither the Network Research Group at LBNL
+nor the Tcpdump Group ever generated a release with this version number. 
+The LBNL Network Research Group notes with interest that a standard
+cracker trick to get people to install trojans is to distribute bogus
+packages that have a version number higher than the current release. 
+They also noted with annoyance that 90% of the Linux related bug reports
+they got are due to changes made to unofficial versions of their page. 
+If you are having trouble but aren't using a version that came from
+tcpdump.org, please try that before submitting a bug report!
+
+On Linux, libpcap will not work if the kernel does not have the packet
+socket option enabled; see the README.linux file for information about
+this.
+
+If you use AIX, you may not be able to build libpcap from this release.
+We do not have an AIX system in house so it's impossible for us to test
+AIX patches submitted to us.  We are told that you must link against
+/lib/pse.exp, that you must use AIX cc or a GNU C compiler newer than
+2.7.2, and that you may need to run strload before running a libpcap
+application.
+
+Read the README.aix file for information on installing libpcap and
+configuring your system to be able to support libpcap.
+
+If you use NeXTSTEP, you will not be able to build libpcap from this
+release.
+
+If you use SINIX, you should be able to build libpcap from this
+release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS
+V1.0 or V1.1 compiler. But note that in some releases of SINIX, yacc
+emits incorrect code; if grammar.y fails to compile, change every
+occurence of:
+
+       #ifdef YYDEBUG
+
+to:
+       #if YYDEBUG
+
+Another workaround is to use flex and bison.
+
+If you use SCO, you might have trouble building libpcap from this
+release. We do not have a machine running SCO and have not had reports
+of anyone successfully building on it; the current release of libpcap
+does not compile on SCO OpenServer 5.  Although SCO apparently supports
+DLPI to some extent, the DLPI in OpenServer 5 is very non-standard, and
+it appears that completely new code would need to be written to capture
+network traffic.  SCO do not appear to provide tcpdump binaries for
+OpenServer 5 or OpenServer 6 as part of SCO Skunkware:
+
+       http://www.sco.com/skunkware/
+
+If you use UnixWare, you might be able to build libpcap from this
+release, or you might not.  We do not have a machine running UnixWare,
+so we have not tested it; however, SCO provide packages for libpcap
+0.6.2 and tcpdump 3.7.1 in the UnixWare 7/Open UNIX 8 part of SCO
+Skunkware, and the source package for libpcap 0.6.2 is not changed from
+the libpcap 0.6.2 source release, so this release of libpcap might also
+build without changes on UnixWare 7.
+
+If linking tcpdump fails with "Undefined: _alloca" when using bison on
+a Sun4, your version of bison is broken. In any case version 1.16 or
+higher is recommended (1.14 is known to cause problems 1.16 is known to
+work). Either pick up a current version from:
+
+       ftp://ftp.gnu.org/pub/gnu/bison
+
+or hack around it by inserting the lines:
+
+       #ifdef __GNUC__
+       #define alloca __builtin_alloca
+       #else
+       #ifdef sparc
+       #include <alloca.h>
+       #else
+       char *alloca ();
+       #endif
+       #endif
+
+right after the (100 line!) GNU license comment in bison.simple, remove
+grammar.[co] and fire up make again.
+
+If you use SunOS 4, your kernel must support streams NIT. If you run a
+libpcap program and it dies with:
+
+    /dev/nit: No such device
+
+You must add streams NIT support to your kernel configuration, run
+config and boot the new kernel.
+
+If you are running a version of SunOS earlier than 4.1, you will need
+to replace the Sun supplied /sys/sun{3,4,4c}/OBJ/nit_if.o with the
+appropriate version from this distribution's SUNOS4 subdirectory and
+build a new kernel:
+
+       nit_if.o.sun3-sunos4            (any flavor of sun3)
+       nit_if.o.sun4c-sunos4.0.3c      (SS1, SS1+, IPC, SLC, etc.)
+       nit_if.o.sun4-sunos4            (Sun4's not covered by
+                                           nit_if.o.sun4c-sunos4.0.3c)
+
+These nit replacements fix a bug that makes nit essentially unusable in
+pre-SunOS 4.1.  In addition, our sun4c-sunos4.0.3c nit gives you
+timestamps to the resolution of the SS-1 clock (1 us) rather than the
+lousy 20ms timestamps Sun gives you  (tcpdump will print out the full
+timestamp resolution if it finds it's running on a SS-1).
+
+FILES
+-----
+CHANGES                - description of differences between releases
+ChmodBPF/*     - Mac OS X startup item to set ownership and permissions
+                 on /dev/bpf*
+CREDITS                - people that have helped libpcap along
+INSTALL.txt    - this file
+LICENSE                - the license under which tcpdump is distributed
+Makefile.in    - compilation rules (input to the configure script)
+README         - description of distribution
+README.aix     - notes on using libpcap on AIX
+README.dag     - notes on using libpcap to capture on Endace DAG devices
+README.hpux    - notes on using libpcap on HP-UX
+README.linux   - notes on using libpcap on Linux
+README.macosx  - notes on using libpcap on Mac OS X
+README.septel   - notes on using libpcap to capture on Intel/Septel devices
+README.sita    - notes on using libpcap to capture on SITA devices
+README.tru64   - notes on using libpcap on Digital/Tru64 UNIX
+README.Win32   - notes on using libpcap on Win32 systems (with WinPcap)
+SUNOS4         - pre-SunOS 4.1 replacement kernel nit modules
+VERSION                - version of this release
+acconfig.h     - support for post-2.13 autoconf
+aclocal.m4     - autoconf macros
+arcnet.h       - ARCNET definitions
+atmuni31.h     - ATM Q.2931 definitions
+bpf/net                - copy of bpf_filter.c
+bpf_dump.c     - BPF program printing routines
+bpf_filter.c   - symlink to bpf/net/bpf_filter.c
+bpf_image.c    - BPF disassembly routine
+config.guess   - autoconf support
+config.h.in    - autoconf input
+config.sub     - autoconf support
+configure      - configure script (run this first)
+configure.in   - configure script source
+dlpisubs.c     - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
+dlpisubs.h     - DLPI-related function declarations
+etherent.c     - /etc/ethers support routines
+ethertype.h    - Ethernet protocol types and names definitions
+fad-getad.c    - pcap_findalldevs() for systems with getifaddrs()
+fad-gifc.c     - pcap_findalldevs() for systems with only SIOCGIFLIST
+fad-glifc.c    - pcap_findalldevs() for systems with SIOCGLIFCONF
+fad-null.c     - pcap_findalldevs() for systems without capture support
+fad-sita.c     - pcap_findalldevs() for systems with SITA support
+fad-win32.c    - pcap_findalldevs() for WinPcap
+filtertest.c   - test program for BPF compiler
+findalldevstest.c - test program for pcap_findalldevs()
+gencode.c      - BPF code generation routines
+gencode.h      - BPF code generation definitions
+grammar.y      - filter string grammar
+ieee80211.h    - 802.11 definitions
+inet.c         - network routines
+install-sh     - BSD style install script
+lbl/os-*.h     - OS-dependent defines and prototypes
+llc.h          - 802.2 LLC SAP definitions
+missing/*      - replacements for missing library functions
+mkdep          - construct Makefile dependency list
+msdos/*                - drivers for MS-DOS capture support
+nametoaddr.c   - hostname to address routines
+nlpid.h                - OSI network layer protocol identifier definitions
+net            - symlink to bpf/net
+optimize.c     - BPF optimization routines
+packaging      - packaging information for building libpcap RPMs
+pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
+pcap/bpf.h     - BPF definitions
+pcap/namedb.h  - public libpcap name database definitions
+pcap/pcap.h    - public libpcap definitions
+pcap/sll.h     - public definition of DLT_LINUX_SLL header
+pcap/usb.h     - public definition of DLT_USB header
+pcap-bpf.c     - BSD Packet Filter support
+pcap-bpf.h     - header for backwards compatibility
+pcap-bt-linux.c        - Bluetooth capture support for Linux
+pcap-bt-linux.h        - Bluetooth capture support for Linux
+pcap-dag.c     - Endace DAG device capture support
+pcap-dag.h     - Endace DAG device capture support
+pcap-dlpi.c    - Data Link Provider Interface support
+pcap-dos.c     - MS-DOS capture support
+pcap-dos.h     - headers for MS-DOS capture support
+pcap-enet.c    - enet support
+pcap-int.h     - internal libpcap definitions
+pcap-libdlpi.c - Data Link Provider Interface support for systems with libdlpi
+pcap-linux.c   - Linux packet socket support
+pcap-namedb.h  - header for backwards compatibility
+pcap-nit.c     - SunOS Network Interface Tap support
+pcap-nit.h     - SunOS Network Interface Tap definitions
+pcap-null.c    - dummy monitor support (allows offline use of libpcap)
+pcap-pf.c      - Ultrix and Digital/Tru64 UNIX Packet Filter support
+pcap-pf.h      - Ultrix and Digital/Tru64 UNIX Packet Filter definitions
+pcap-septel.c   - Intel/Septel device capture support
+pcap-septel.h   - Intel/Septel device capture support
+pcap-sita.c    - SITA device capture support
+pcap-sita.h    - SITA device capture support
+pcap-sita.html - SITA device capture documentation
+pcap-stdinc.h  - includes and #defines for compiling on Win32 systems
+pcap-snit.c    - SunOS 4.x STREAMS-based Network Interface Tap support
+pcap-snoop.c   - IRIX Snoop network monitoring support
+pcap-usb-linux.c - USB capture support for Linux
+pcap-usb-linux.h - USB capture support for Linux
+pcap-win32.c   - WinPcap capture support
+pcap.3pcap     - manual entry for the library
+pcap.c         - pcap utility routines
+pcap.h         - header for backwards compatibility
+pcap_*.3pcap   - manual entries for library functions
+pcap-filter.4  - manual entry for filter syntax
+pcap-linktype.4        - manual entry for link-layer header types
+ppp.h          - Point to Point Protocol definitions
+runlex.sh      - wrapper for Lex/Flex
+savefile.c     - offline support
+scanner.l      - filter string scanner
+sunatmpos.h    - definitions for SunATM capturing
+Win32          - headers and routines for building on Win32 systems
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..dea5f7d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+License: BSD
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+  
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..772cc7d
--- /dev/null
@@ -0,0 +1,735 @@
+#  Copyright (c) 1993, 1994, 1995, 1996
+#      The Regents of the University of California.  All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that: (1) source code distributions
+#  retain the above copyright notice and this paragraph in its entirety, (2)
+#  distributions including binary code include the above copyright notice and
+#  this paragraph in its entirety in the documentation or other materials
+#  provided with the distribution, and (3) all advertising materials mentioning
+#  features or use of this software display the following acknowledgement:
+#  ``This product includes software developed by the University of California,
+#  Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+#  the University nor the names of its contributors may be used to endorse
+#  or promote products derived from this software without specific prior
+#  written permission.
+#  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+#  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.142 2008-11-22 17:30:24 guy Exp $ (LBL)
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir =  @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+CCOPT = @V_CCOPT@
+INCLS = -I. @V_INCLS@
+DEFS = @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+PROG=libpcap
+
+# Standard CFLAGS
+FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+RANLIB = @RANLIB@
+
+#
+# Flex and bison allow you to specify the prefixes of the global symbols
+# used by the generated parser.  This allows programs to use lex/yacc
+# and link against libpcap.  If you don't have flex or bison, get them.
+#
+LEX = @V_LEX@
+YACC = @V_YACC@
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+       @rm -f $@
+       $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@
+FSRC =  fad-@V_FINDALLDEVS@.c
+SSRC =  @SSRC@
+CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
+       savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
+       bpf_image.c bpf_dump.c
+GENSRC = scanner.c grammar.c bpf_filter.c version.c
+LIBOBJS = @LIBOBJS@
+
+SRC =  $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
+
+# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+# hack the extra indirection
+OBJ =  $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
+PUBHDR = \
+       pcap.h \
+       pcap-bpf.h \
+       pcap-namedb.h \
+       pcap/bpf.h \
+       pcap/bluetooth.h \
+       pcap/ipnet.h \
+       pcap/namedb.h \
+       pcap/pcap.h \
+       pcap/sll.h \
+       pcap/vlan.h \
+       pcap/usb.h
+
+HDR = $(PUBHDR) \
+       arcnet.h \
+       atmuni31.h \
+       ethertype.h \
+       gencode.h \
+       ieee80211.h \
+       llc.h \
+       nlpid.h \
+       pcap-common.h \
+       pcap-int.h \
+       pcap-stdinc.h \
+       ppp.h \
+       sf-pcap.h \
+       sf-pcap-ng.h \
+       sunatmpos.h
+
+TESTS = \
+       filtertest \
+       findalldevstest \
+       nonblocktest \
+       opentest \
+       selpolltest
+
+TESTS_SRC = \
+       tests/filtertest.c \
+       tests/findalldevstest.c \
+       tests/nonblocktest.c \
+       tests/opentest.c \
+       tests/reactivatetest.c \
+       tests/selpolltest.c
+
+GENHDR = \
+       scanner.h tokdefs.h version.h
+
+TAGFILES = \
+       $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) libpcap.* $(TESTS) \
+       $(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
+       lex.yy.c pcap-config
+
+MAN1 = pcap-config.1
+
+MAN3PCAP_EXPAND = \
+       pcap.3pcap.in \
+       pcap_compile.3pcap.in \
+       pcap_datalink.3pcap.in \
+       pcap_dump_open.3pcap.in \
+       pcap_list_datalinks.3pcap.in \
+       pcap_list_tstamp_types.3pcap.in \
+       pcap_open_dead.3pcap.in \
+       pcap_open_offline.3pcap.in \
+       pcap_set_tstamp_type.3pcap.in
+
+MAN3PCAP_NOEXPAND = \
+       pcap_activate.3pcap \
+       pcap_breakloop.3pcap \
+       pcap_can_set_rfmon.3pcap \
+       pcap_close.3pcap \
+       pcap_create.3pcap \
+       pcap_datalink_name_to_val.3pcap \
+       pcap_datalink_val_to_name.3pcap \
+       pcap_dump.3pcap \
+       pcap_dump_close.3pcap \
+       pcap_dump_file.3pcap \
+       pcap_dump_flush.3pcap \
+       pcap_dump_ftell.3pcap \
+       pcap_file.3pcap \
+       pcap_fileno.3pcap \
+       pcap_findalldevs.3pcap \
+       pcap_freecode.3pcap \
+       pcap_get_selectable_fd.3pcap \
+       pcap_geterr.3pcap \
+       pcap_inject.3pcap \
+       pcap_is_swapped.3pcap \
+       pcap_lib_version.3pcap \
+       pcap_lookupdev.3pcap \
+       pcap_lookupnet.3pcap \
+       pcap_loop.3pcap \
+       pcap_major_version.3pcap \
+       pcap_next_ex.3pcap \
+       pcap_offline_filter.3pcap \
+       pcap_open_live.3pcap \
+       pcap_set_buffer_size.3pcap \
+       pcap_set_datalink.3pcap \
+       pcap_set_promisc.3pcap \
+       pcap_set_rfmon.3pcap \
+       pcap_set_snaplen.3pcap \
+       pcap_set_timeout.3pcap \
+       pcap_setdirection.3pcap \
+       pcap_setfilter.3pcap \
+       pcap_setnonblock.3pcap \
+       pcap_snapshot.3pcap \
+       pcap_stats.3pcap \
+       pcap_statustostr.3pcap \
+       pcap_strerror.3pcap \
+       pcap_tstamp_type_name_to_val.3pcap \
+       pcap_tstamp_type_val_to_name.3pcap
+
+MAN3PCAP = $(MAN3PCAP_NOEXPAND) $(MAN3PCAP_EXPAND:.in=)
+
+MANFILE = \
+       pcap-savefile.manfile.in
+
+MANMISC = \
+       pcap-filter.manmisc.in \
+       pcap-linktype.manmisc.in \
+       pcap-tstamp.manmisc.in
+
+EXTRA_DIST = \
+       $(TESTS_SRC) \
+       CHANGES \
+       ChmodBPF/ChmodBPF \
+       ChmodBPF/StartupParameters.plist \
+       CREDITS \
+       INSTALL.txt \
+       LICENSE \
+       Makefile.in \
+       README \
+       README.aix \
+       README.dag \
+       README.hpux \
+       README.linux \
+       README.macosx \
+       README.septel \
+       README.sita \
+       README.tru64 \
+       README.Win32 \
+       SUNOS4/nit_if.o.sparc \
+       SUNOS4/nit_if.o.sun3 \
+       SUNOS4/nit_if.o.sun4c.4.0.3c \
+       TODO \
+       VERSION \
+       aclocal.m4 \
+       bpf/net/bpf_filter.c \
+       chmod_bpf \
+       config.guess \
+       config.h.in \
+       config.sub \
+       configure \
+       configure.in \
+       dlpisubs.c \
+       dlpisubs.h \
+       fad-getad.c \
+       fad-gifc.c \
+       fad-glifc.c \
+       fad-null.c \
+       fad-sita.c \
+       fad-win32.c \
+       grammar.y \
+       install-sh \
+       lbl/os-aix4.h \
+       lbl/os-hpux11.h \
+       lbl/os-osf4.h \
+       lbl/os-osf5.h \
+       lbl/os-solaris2.h \
+       lbl/os-sunos4.h \
+       lbl/os-ultrix4.h \
+       missing/snprintf.c \
+       mkdep \
+       msdos/bin2c.c \
+       msdos/common.dj \
+       msdos/makefile \
+       msdos/makefile.dj \
+       msdos/makefile.wc \
+       msdos/ndis2.c \
+       msdos/ndis2.h \
+       msdos/ndis_0.asm \
+       msdos/pkt_rx0.asm \
+       msdos/pkt_rx1.s \
+       msdos/pktdrvr.c \
+       msdos/pktdrvr.h \
+       msdos/readme.dos \
+       org.tcpdump.chmod_bpf.plist \
+       packaging/pcap.spec.in \
+       pcap-bpf.c \
+       pcap-bt-linux.c \
+       pcap-bt-linux.h \
+       pcap-can-linux.c \
+       pcap-can-linux.h \
+       pcap-canusb-linux.c \
+       pcap-canusb-linux.h \
+       pcap-config.in \
+       pcap-dag.c \
+       pcap-dag.h \
+       pcap-dlpi.c \
+       pcap-dos.c \
+       pcap-dos.h \
+       pcap-enet.c \
+       pcap-int.h \
+       pcap-libdlpi.c \
+       pcap-linux.c \
+       pcap-namedb.h \
+       pcap-netfilter-linux.c \
+       pcap-netfilter-linux.h \
+       pcap-nit.c \
+       pcap-null.c \
+       pcap-pf.c \
+       pcap-septel.c \
+       pcap-septel.h \
+       pcap-sita.h \
+       pcap-sita.c \
+       pcap-sita.html \
+       pcap-snf.c \
+       pcap-snf.h \
+       pcap-snit.c \
+       pcap-snoop.c \
+       pcap-usb-linux.c \
+       pcap-usb-linux.h \
+       pcap-win32.c \
+       runlex.sh \
+       scanner.l \
+       Win32/Include/Gnuc.h \
+       Win32/Include/addrinfo.h \
+       Win32/Include/bittypes.h \
+       Win32/Include/cdecl_ext.h \
+       Win32/Include/inetprivate.h \
+       Win32/Include/ip6_misc.h \
+       Win32/Include/sockstorage.h \
+       Win32/Include/arpa/nameser.h \
+       Win32/Include/net/if.h \
+       Win32/Include/net/netdb.h \
+       Win32/Include/net/paths.h \
+       Win32/Prj/libpcap.dsp \
+       Win32/Prj/libpcap.dsw \
+       Win32/Src/ffs.c \
+       Win32/Src/gai_strerror.c \
+       Win32/Src/getaddrinfo.c \
+       Win32/Src/getnetbynm.c \
+       Win32/Src/getnetent.c \
+       Win32/Src/getopt.c \
+       Win32/Src/getservent.c \
+       Win32/Src/inet_aton.c \
+       Win32/Src/inet_net.c \
+       Win32/Src/inet_pton.c
+
+all: libpcap.a shared pcap-config
+
+libpcap.a: $(OBJ)
+       @rm -f $@
+       $(AR) rc $@ $(OBJ) $(ADDLARCHIVEOBJS)
+       $(RANLIB) $@
+
+shared: libpcap.$(DYEXT)
+
+libpcap.so: $(OBJ)
+       @rm -f $@
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       @V_SHLIB_CMD@ @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER $(LDFLAGS) \
+           -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# The following rule succeeds, but the result is untested.
+#
+# In Mac OS X, the libpcap dylib has the name "libpcap.A.dylib", with
+# its full path as the install_name, and with the compatibility and
+# current version both set to 1.  The compatibility version is set to
+# 1 so that programs built with a newer version of the library will run
+# against older versions; multi-platform software probably will fail if
+# it uses APIs added in the newer version, but Mac OS X-specific software
+# will use weak linking and check at run time whether those APIs are
+# available.
+#
+# We also use "A" as the major version, and 1 as the compatibility version,
+# but set the current version to the value in VERSION, with any non-numeric
+# stuff stripped off (the compatibility and current version must be of the
+# form X[.Y[.Z]], with Y and Z possibly absent, and with all components
+# numeric).
+#
+libpcap.dylib: $(OBJ)
+       rm -f libpcap*.dylib
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=A; \
+       COMPAT_VER=1; \
+       CURRENT_VER=`sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`; \
+       $(CC) -dynamiclib -undefined error $(LDFLAGS) \
+           -o libpcap.$$VER.dylib $(OBJ) $(ADDLOBJS) $(LIBS) \
+           -install_name $(libdir)/libpcap.$$MAJOR_VER.dylib \
+           -compatibility_version $$COMPAT_VER \
+           -current_version $$CURRENT_VER
+
+#
+# The HP-UX linker manual says that the convention for a versioned library
+# is libXXX.{number}, not libXXX.sl.{number}.  That appears to be the case
+# on at least one HP-UX 11.00 system; libXXX.sl is a symlink to
+# libXXX.{number}.
+#
+# The manual also says "library-level versioning" (think "sonames") was
+# added in HP-UX 10.0.
+#
+# XXX - this assumes we're using the HP linker, rather than the GNU
+# linker, even with GCC.
+#
+libpcap.sl: $(OBJ)
+       @MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       rm -f libpcap.$$MAJOR_VER
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       ld -b $(LDFLAGS) -o libpcap.$$MAJOR_VER +h libpcap.$$MAJOR_VER \
+           $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# AIX is different from everybody else.  A shared library is an archive
+# library with one or more shared-object components.  We still build a
+# normal static archive library on AIX, for the benefit of the traditional
+# scheme of building libpcap and tcpdump in subdirectories of the
+# same directory, with tcpdump statically linked with the libpcap
+# in question, but we also build a shared library as "libpcap.shareda"
+# and install *it*, rather than the static library, as "libpcap.a".
+#
+libpcap.shareda: $(OBJ)
+       @rm -f $@ shr.o
+       $(CC) @V_SHLIB_OPT@ -o shr.o $(OBJ) $(ADDLOBJS) $(LDFLAGS) $(LIBS)
+       $(AR) rc $@ shr.o
+
+#
+# For platforms that don't support shared libraries (or on which we
+# don't support shared libraries).
+#
+libpcap.none:
+
+scanner.c: $(srcdir)/scanner.l
+       @rm -f $@
+       $(srcdir)/runlex.sh $(LEX) -o$@ $<
+
+scanner.o: scanner.c tokdefs.h
+       $(CC) $(FULL_CFLAGS) -c scanner.c
+
+pcap.o: version.h
+
+tokdefs.h: grammar.c
+grammar.c: $(srcdir)/grammar.y
+       @rm -f grammar.c tokdefs.h
+       $(YACC) -d $<
+       mv y.tab.c grammar.c
+       mv y.tab.h tokdefs.h
+
+grammar.o: grammar.c
+       @rm -f $@
+       $(CC) $(FULL_CFLAGS) -Dyylval=pcap_lval -c grammar.c
+
+version.o: version.c
+       $(CC) $(FULL_CFLAGS) -c version.c
+
+snprintf.o: $(srcdir)/missing/snprintf.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
+
+version.c: $(srcdir)/VERSION
+       @rm -f $@
+       if grep GIT ${srcdir}/VERSION >/dev/null; then \
+               read ver <${srcdir}/VERSION; \
+               echo $$ver | tr -d '\012'; \
+               date +_%Y_%m_%d; \
+       else \
+               cat ${srcdir}/VERSION; \
+       fi | sed -e 's/.*/char pcap_version[] = "&";/' > $@
+
+#
+# NOTE: this really is supposed to be static; importing a string
+# from a shared library does not work very well on many
+# versions of UNIX (Solaris, Linux, and the BSDs, for example),
+# so we make the version string static and return it from
+# a function, which does work.
+#
+version.h: $(srcdir)/VERSION
+       @rm -f $@
+       if grep GIT ${srcdir}/VERSION >/dev/null; then \
+               read ver <${srcdir}/VERSION; \
+               echo $$ver | tr -d '\012'; \
+               date +_%Y_%m_%d; \
+       else \
+               cat ${srcdir}/VERSION; \
+       fi | sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' > $@
+
+bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
+       rm -f bpf_filter.c
+       ln -s $(srcdir)/bpf/net/bpf_filter.c bpf_filter.c
+
+bpf_filter.o: bpf_filter.c
+       $(CC) $(FULL_CFLAGS) -c bpf_filter.c
+
+#
+# Generate the pcap-config script.
+#
+# Some Makes, e.g. AIX Make and Solaris Make, can't handle "--file=$@.tmp:$<";
+# for example, the Solaris 9 make man page says
+#
+#      Because make assigns $< and $* as it would for implicit rules
+#      (according to the suffixes list and the directory contents),
+#      they may be unreliable when used within explicit target entries.
+#
+# and this is an explicit target entry.
+#
+# Therefore, instead of using $<, we explicitly put in $(srcdir)/pcap-config.in.
+#
+pcap-config: $(srcdir)/pcap-config.in ./config.status
+       @rm -f $@ $@.tmp
+       ./config.status --file=$@.tmp:$(srcdir)/pcap-config.in
+       mv $@.tmp $@
+       chmod a+x $@
+
+#
+# Test programs - not built by default, and not installed.
+#
+tests: $(TESTS)
+
+filtertest: tests/filtertest.c libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/tests/filtertest.c libpcap.a $(LIBS)
+
+findalldevstest: tests/findalldevstest.c libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/tests/findalldevstest.c libpcap.a $(LIBS)
+
+nonblocktest: tests/nonblocktest.c libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o nonblocktest $(srcdir)/tests/nonblocktest.c libpcap.a $(LIBS)
+
+opentest: tests/opentest.c libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/tests/opentest.c libpcap.a $(LIBS)
+
+selpolltest: tests/selpolltest.c libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/tests/selpolltest.c libpcap.a $(LIBS)
+
+install: install-shared install-archive pcap-config
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       [ -d $(DESTDIR)$(includedir) ] || \
+           (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
+       [ -d $(DESTDIR)$(includedir)/pcap ] || \
+           (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap)
+       [ -d $(DESTDIR)$(mandir)/man1 ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
+       [ -d $(DESTDIR)$(mandir)/man3 ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
+       [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+       [ -d $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@ ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@)
+       for i in $(PUBHDR); do \
+               $(INSTALL_DATA) $(srcdir)/$$i \
+                   $(DESTDIR)$(includedir)/$$i; done
+       [ -d $(DESTDIR)$(bindir) ] || \
+           (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
+       $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+       for i in $(MAN1); do \
+               $(INSTALL_DATA) $(srcdir)/$$i \
+                   $(DESTDIR)$(mandir)/man1/$$i; done
+       for i in $(MAN3PCAP_NOEXPAND); do \
+               $(INSTALL_DATA) $(srcdir)/$$i \
+                   $(DESTDIR)$(mandir)/man3/$$i; done
+       for i in $(MAN3PCAP_EXPAND:.in=); do \
+               $(INSTALL_DATA) $$i \
+                   $(DESTDIR)$(mandir)/man3/$$i; done
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_name.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_dump_open.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_findalldevs.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_geterr.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_inject.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_list_datalinks.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_list_tstamp_types.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_loop.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_major_version.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_next_ex.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_open_offline.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+       ln $(DESTDIR)$(mandir)/man3/pcap_setnonblock.3pcap \
+                $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+       for i in $(MANFILE); do \
+               $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+                   $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+       for i in $(MANMISC); do \
+               $(INSTALL_DATA) `echo $$i | sed 's/.manmisc.in/.manmisc/'` \
+                   $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+install-shared: install-shared-$(DYEXT)
+install-shared-so: libpcap.so
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       $(INSTALL_PROGRAM) libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+       ln -sf libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+       ln -sf libpcap.so.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.so
+install-shared-dylib: libpcap.dylib
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=A; \
+       $(INSTALL_PROGRAM) libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+       ln -sf libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+       ln -sf libpcap.$$MAJOR_VER.dylib $(DESTDIR)$(libdir)/libpcap.dylib
+install-shared-sl: libpcap.sl
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       $(INSTALL_PROGRAM) libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)
+       ln -sf libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.sl
+install-shared-shareda: libpcap.shareda
+       #
+       # AIX shared libraries are weird.  They're archive libraries
+       # with one or more shared object components.
+       #
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       $(INSTALL_PROGRAM) libpcap.shareda $(DESTDIR)$(libdir)/libpcap.a
+install-shared-none:
+
+install-archive: install-archive-$(DYEXT)
+install-archive-so install-archive-dylib install-archive-sl install-archive-none: libpcap.a
+       #
+       # Most platforms have separate suffixes for shared and
+       # archive libraries, so we install both.
+       #
+       [ -d $(DESTDIR)$(libdir) ] || \
+           (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+       $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
+       $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a
+install-archive-shareda:
+       #
+       # AIX, however, doesn't, so we don't install the archive
+       # library on AIX.
+       #
+
+uninstall: uninstall-shared
+       rm -f $(DESTDIR)$(libdir)/libpcap.a
+       for i in $(PUBHDR); do \
+               rm -f $(DESTDIR)$(includedir)/$$i; done
+       -rmdir $(DESTDIR)$(includedir)/pcap
+       rm -f $(DESTDIR)/$(bindir)/pcap-config
+       for i in $(MAN1); do \
+               rm -f $(DESTDIR)$(mandir)/man1/$$i; done
+       for i in $(MAN3PCAP); do \
+               rm -f $(DESTDIR)$(mandir)/man3/$$i; done
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+       rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+       for i in $(MANFILE); do \
+               rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+       for i in $(MANMISC); do \
+               rm -f $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+uninstall-shared: uninstall-shared-$(DYEXT)
+uninstall-shared-so:
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.so
+uninstall-shared-dylib:
+       VER=`cat $(srcdir)/VERSION`; \
+       MAJOR_VER=A; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.dylib
+uninstall-shared-sl:
+       MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER; \
+       rm -f $(DESTDIR)$(libdir)/libpcap.sl
+uninstall-shared-shareda:
+       rm -f $(DESTDIR)$(libdir)/libpcap.a
+uninstall-shared-none:
+
+clean:
+       rm -f $(CLEANFILES)
+
+distclean: clean
+       rm -f Makefile config.cache config.log config.status \
+           config.h gnuc.h net os-proto.h bpf_filter.c pcap-config \
+           stamp-h stamp-h.in
+       rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
+       rm -rf autom4te.cache
+
+tags: $(TAGFILES)
+       ctags -wtd $(TAGFILES)
+
+packaging/pcap.spec: packaging/pcap.spec.in VERSION
+       RPMVERSION=`cat VERSION | sed s/-.*//g`; \
+               sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $<   > $@
+
+releasetar: 
+       @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
+          mkdir $$name; \
+          tar cf - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
+             $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
+             (cd $$name; tar xf -); \
+          tar -c -z -f $$name.tar.gz $$name; \
+          rm -rf $$name
+
+depend:        $(GENSRC) $(GENHDR) bpf_filter.c
+       ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
+
+Makefile: Makefile.in config.status
+       ./config.status
+       @echo your Makefile was out of date, now run $(MAKE) again
+       exit 1
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a206474
--- /dev/null
+++ b/README
@@ -0,0 +1,105 @@
+@(#) $Header: /tcpdump/master/libpcap/README,v 1.34 2008-12-14 19:44:14 guy Exp $ (LBL)
+
+LIBPCAP 1.x.y
+
+www.tcpdump.org
+
+Please send inquiries/comments/reports to:
+       tcpdump-workers@lists.tcpdump.org
+
+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 against the master copy to the libpcap project on
+sourceforge.net.
+
+formerly from  Lawrence Berkeley National Laboratory
+               Network Research Group <libpcap@ee.lbl.gov>
+               ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4)
+
+This directory contains source code for libpcap, a system-independent
+interface for user-level packet capture.  libpcap provides a portable
+framework for low-level network monitoring.  Applications include
+network statistics collection, security monitoring, network debugging,
+etc.  Since almost every system vendor provides a different interface
+for packet capture, and since we've developed several tools that
+require this functionality, we've created this system-independent API
+to ease in porting and to alleviate the need for several
+system-dependent packet capture modules in each application.
+
+For some platforms there are README.{system} files that discuss issues
+with the OS's interface for packet capture on those platforms, such as
+how to enable support for that interface in the OS, if it's not built in
+by default.
+
+The libpcap interface supports a filtering mechanism based on the
+architecture in the BSD packet filter.  BPF is described in the 1993
+Winter Usenix paper ``The BSD Packet Filter: A New Architecture for
+User-level Packet Capture''.  A compressed PostScript version can be
+found at
+
+       ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z
+
+or
+
+       http://www.tcpdump.org/papers/bpf-usenix93.ps.Z
+
+and a gzipped version can be found at
+
+       http://www.tcpdump.org/papers/bpf-usenix93.ps.gz
+
+A PDF version can be found at
+
+       http://www.tcpdump.org/papers/bpf-usenix93.pdf
+
+Although most packet capture interfaces support in-kernel filtering,
+libpcap utilizes in-kernel filtering only for the BPF interface.
+On systems that don't have BPF, all packets are read into user-space
+and the BPF filters are evaluated in the libpcap library, incurring
+added overhead (especially, for selective filters).  Ideally, libpcap
+would translate BPF filters into a filter program that is compatible
+with the underlying kernel subsystem, but this is not yet implemented.
+
+BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, OpenBSD, DragonFly
+BSD, and Mac OS X; an older, modified and undocumented version is
+standard in AIX.  {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the
+packetfilter interface but has been extended to accept BPF filters
+(which libpcap utilizes).  Also, you can add BPF filter support to
+Ultrix using the kernel source and/or object patches available in:
+
+       http://www.tcpdump.org/other/bpfext42.tar.Z
+
+Linux, in the 2.2 kernel and later kernels, has a "Socket Filter"
+mechanism that accepts BPF filters; see the README.linux file for
+information on configuring that option.
+
+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 
+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 
+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 
+a particular release of libpcap.
+
+Problems, bugs, questions, desirable enhancements, etc. should be sent
+to the address "tcpdump-workers@lists.tcpdump.org".  Bugs, support
+requests, and feature requests may also be submitted on the SourceForge
+site for libpcap at
+
+       http://sourceforge.net/projects/libpcap/
+
+Source code contributions, etc. should be sent to the email address
+submitted as patches on the SourceForge site for libpcap.
+
+Current versions can be found at www.tcpdump.org, or the SourceForge
+site for libpcap.
+
+ - The TCPdump team
diff --git a/README.Win32 b/README.Win32
new file mode 100644 (file)
index 0000000..503836e
--- /dev/null
@@ -0,0 +1,46 @@
+Under Win32, libpcap is integrated in the WinPcap packet capture system. 
+WinPcap provides a framework that allows libpcap to capture the packets 
+under Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000 
+and Windows XP.
+WinPcap binaries and source code can be found at http://winpcap.polito.it: 
+they include also a developer's pack with all the necessary to compile 
+libpcap-based applications under Windows.
+
+How to compile libpcap with Visual Studio
+-----------------------------------------
+
+In order to compile libpcap you will need:
+
+- version 6 (or higher) of Microsoft Visual Studio
+- The November 2001 (or later) edition of Microsoft Platform 
+Software Development Kit (SDK), that contains some necessary includes 
+for IPv6 support. You can download it from http://www.microsoft.com/sdk
+- the latest WinPcap sources from http://winpcap.polito.it/install 
+
+The WinPcap source code already contains a recent (usually the latest 
+stable) version of libpcap. If you need to compile a different one, 
+simply download it from www.tcpdump.org and copy the sources in the 
+winpcap\wpcap\libpcap folder of the WinPcap distribution. If you want to
+compile a libpcap source retrieved from the tcpdump.org Git, you will 
+have to create the scanner and the grammar by hand (with lex and yacc) 
+or with the cygnus makefile, since The Visual Studio project is not able
+to build them.
+
+Open the project file winpcap\wpcap\prj\wpcap.dsw with Visual Studio and 
+build wpcap.dll. wpcap.lib, the library file to link with the applications, 
+will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in 
+winpcap\wpcap\prj\release or winpcap\wpcap\prj\debug depending on the type 
+of binary that is being created.
+
+How to compile libpcap with Cygnus
+----------------------------------
+
+To build wpcap.dll, cd to the directory WPCAP/PRJ of the WinPcap source code 
+distribution and type "make". libwpcap.a, the library file to link with the 
+applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be 
+generated in winpcap\wpcap\prj.
+
+Remember, you CANNOT use the MSVC-generated .lib files with gcc, use 
+libwpcap.a instead.
+
+"make install" installs wpcap.dll in the Windows system folder.
diff --git a/README.aix b/README.aix
new file mode 100644 (file)
index 0000000..b32fa58
--- /dev/null
@@ -0,0 +1,81 @@
+Using BPF:
+
+(1) AIX 4.x's version of BPF is undocumented and somewhat unstandard; the
+    current BPF support code includes changes that should work around
+    that; it appears to compile and work on at least one AIX 4.3.3
+    machine.
+
+    Note that the BPF driver and the "/dev/bpf" devices might not exist
+    on your machine; AIX's tcpdump loads the driver and creates the
+    devices if they don't already exist.  Our libpcap should do the
+    same, and the configure script should detect that it's on an AIX
+    system and choose BPF even if the devices aren't there.
+
+(2) If libpcap doesn't compile on your machine when configured to use
+    BPF, or if the workarounds fail to make it work correctly, you
+    should send to tcpdump-workers@lists.tcpdump.org a detailed bug
+    report (if the compile fails, send us the compile error messages;
+    if it compiles but fails to work correctly, send us as detailed as
+    possible a description of the symptoms, including indications of the
+    network link-layer type being wrong or time stamps being wrong).
+
+    If you fix the problems yourself, please submit a patch to
+
+       http://sourceforge.net/projects/libpcap/
+
+    so we can incorporate them into the next release.
+
+    If you don't fix the problems yourself, you can, as a workaround,
+    make libpcap use DLPI instead of BPF.
+
+    This can be done by specifying the flag:
+
+       --with-pcap=dlpi
+
+    to the "configure" script for libpcap.
+
+If you use DLPI:
+
+(1) It is a good idea to have the latest version of the DLPI driver on
+    your system, since certain versions may be buggy and cause your AIX
+    system to crash.  DLPI is included in the fileset bos.rte.tty.  I
+    found that the DLPI driver that came with AIX 4.3.2 was buggy, and
+    had to upgrade to bos.rte.tty 4.3.2.4:
+
+           lslpp -l bos.rte.tty
+
+           bos.rte.tty     4.3.2.4  COMMITTED  Base TTY Support and Commands
+
+    Updates for AIX filesets can be obtained from:
+    ftp://service.software.ibm.com/aix/fixes/
+
+    These updates can be installed with the smit program.
+
+(2) After compiling libpcap, you need to make sure that the DLPI driver
+    is loaded.  Type:
+
+           strload -q -d dlpi
+
+    If the result is:
+
+           dlpi: yes
+
+    then the DLPI driver is loaded correctly.
+
+    If it is:
+
+           dlpi: no
+
+    Then you need to type:
+
+           strload -f /etc/dlpi.conf
+    Check again with strload -q -d dlpi that the dlpi driver is loaded.  
+
+    Alternatively, you can uncomment the lines for DLPI in
+    /etc/pse.conf and reboot the machine; this way DLPI will always
+    be loaded when you boot your system.
+
+(3) There appears to be a problem in the DLPI code in some versions of
+    AIX, causing a warning about DL_PROMISC_MULTI failing; this might
+    be responsible for DLPI not being able to capture outgoing packets.
diff --git a/README.dag b/README.dag
new file mode 100644 (file)
index 0000000..acf97ed
--- /dev/null
@@ -0,0 +1,114 @@
+
+The following instructions apply if you have a Linux or FreeBSD platform and
+want libpcap to support the DAG range of passive network monitoring cards from
+Endace (http://www.endace.com, see below for further contact details).
+
+1) Install and build the DAG software distribution by following the
+instructions supplied with that package. Current Endace customers can download
+the DAG software distibution from https://www.endace.com
+
+2) Configure libcap. To allow the 'configure' script to locate the DAG
+software distribution use the '--with-dag' option:
+
+        ./configure --with-dag=DIR
+
+Where DIR is the root of the DAG software distribution, for example
+/var/src/dag. If the DAG software is correctly detected 'configure' will
+report:
+
+        checking whether we have DAG API... yes
+
+If 'configure' reports that there is no DAG API, the directory may have been
+incorrectly specified or the DAG software was not built before configuring
+libpcap.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+Building libpcap at this stage will include support for both the native packet
+capture stream (linux or bpf) and for capturing from DAG cards. To build
+libpcap with only DAG support specify the capture type as 'dag' when
+configuring libpcap:
+
+        ./configure --with-dag=DIR --with-pcap=dag
+
+Applications built with libpcap configured in this way will only detect DAG
+cards and will not capture from the native OS packet stream.
+
+----------------------------------------------------------------------
+
+Libpcap when built for DAG cards against dag-2.5.1 or later releases:
+
+Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds
+regardless of how many packets are received. If to_ms is zero pcap_dispatch()
+will block waiting for data indefinitely.
+
+pcap_dispatch() will block on and process a minimum of 64kB of data (before
+filtering) for efficiency. This can introduce high latencies on quiet
+interfaces unless a timeout value is set. The timeout expiring will override
+the 64kB minimum causing pcap_dispatch() to process any available data and
+return.
+
+pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will
+check once for available data, process any data available up to count, then
+return immediately.
+
+pcap_findalldevs() is supported, e.g. dag0, dag1...
+
+Some DAG cards can provide more than one 'stream' of received data.
+This can be data from different physical ports, or separated by filtering
+or load balancing mechanisms. Receive streams have even numbers, e.g.
+dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported.
+
+pcap_setfilter() is supported, BPF programs run in userspace.
+
+pcap_setdirection() is not supported. Only received traffic is captured.
+DAG cards normally do not have IP or link layer addresses assigned as
+they are used to passively monitor links.
+
+pcap_breakloop() is supported.
+
+pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does
+not attempt to set the correct datalink type automatically where more than
+one type is possible.
+
+pcap_stats() is supported. ps_drop is the number of packets dropped due to
+RX stream buffer overflow, this count is before filters are applied (it will
+include packets that would have been dropped by the filter). The RX stream
+buffer size is user configurable outside libpcap, typically 16-512MB.
+
+pcap_get_selectable_fd() is not supported, as DAG cards do not support
+poll/select methods.
+
+pcap_inject() and pcap_sendpacket() are not supported.
+
+Some DAG cards now support capturing to multiple virtual interfaces, called
+streams. Capture streams have even numbers. These are available via libpcap
+as separate interfaces, e.g. dag0:0, dag0:2, dag0:4 etc. dag0:0 is the same
+as dag0. These are visible via pcap_findalldevs().
+
+libpcap now does NOT set the card's hardware snaplen (slen). This must now be
+set using the appropriate DAG coniguration program, e.g. dagthree, dagfour,
+dagsix, dagconfig. This is because the snaplen is currently shared between
+all of the streams. In future this may change if per-stream slen is
+implemented.
+
+DAG cards by default capture entire packets including the L2
+CRC/FCS. If the card is not configured to discard the CRC/FCS, this
+can confuse applications that use libpcap if they're not prepared for
+packets to have an FCS. Libpcap now reads the environment variable
+ERF_FCS_BITS to determine how many bits of CRC/FCS to strip from the
+end of the captured frame. This defaults to 32 for use with
+Ethernet. If the card is configured to strip the CRC/FCS, then set
+ERF_FCS_BITS=0. If used with a HDLC/PoS/PPP/Frame Relay link with 16
+bit CRC/FCS, then set ERF_FCS_BITS=16.
+
+----------------------------------------------------------------------
+
+Please submit bug reports via <support@endace.com>.
+
+Please also visit our Web site at:
+
+        http://www.endace.com/
+
+For more information about Endace DAG cards contact <sales@endace.com>.
diff --git a/README.hpux b/README.hpux
new file mode 100644 (file)
index 0000000..88c27f8
--- /dev/null
@@ -0,0 +1,254 @@
+For HP-UX 11i (11.11) and later, there are no known issues with
+promiscuous mode under HP-UX.  If you are using a earlier version of
+HP-UX and cannot upgrade, please continue reading.
+
+HP-UX patches to fix packet capture problems
+
+Note that packet-capture programs such as tcpdump may, on HP-UX, not be
+able to see packets sent from the machine on which they're running. 
+Some articles on groups.google.com discussing this are:
+
+       http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
+
+which says:
+
+  Newsgroups: comp.sys.hp.hpux 
+  Subject:  Re: Did someone made tcpdump working on 10.20 ?
+  Date: 12/08/1999
+  From: Lutz Jaenicke <jaenicke@emserv1.ee.TU-Berlin.DE>
+
+  In article <82ks5i$5vc$1@news1.dti.ne.jp>, mtsat <mtsat@iris.dti.ne.jp>
+  wrote:
+   >Hello,
+   >
+   >I downloaded and compiled tcpdump3.4 a couple of week ago. I tried to use
+   >it, but I can only see incoming data, never outgoing.
+   >Someone (raj) explained me that a patch was missing, and that this patch
+   >must me "patched" (poked) in order to see outbound data in promiscuous mode.
+   >Many things to do .... So the question is : did someone has already this
+   >"ready to use" PHNE_**** patch ?
+  
+   Two things:
+   1. You do need a late "LAN products cumulative patch" (e.g.  PHNE_18173
+  for   s700/10.20).
+   2. You must use
+echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
+     You can insert this e.g. into /sbin/init.d/lan
+  
+   Best regards,
+   Lutz
+
+and
+
+       http://groups.google.com/groups?selm=88cf4t%24p03%241%40web1.cup.hp.com
+
+which says:
+
+  Newsgroups: comp.sys.hp.hpux 
+  Subject: Re: tcpdump only shows incoming packets
+  Date: 02/15/2000
+  From: Rick Jones <foo@bar.baz.invalid>
+
+  Harald Skotnes <harald@cc.uit.no> wrote:
+  > I am running HPUX 11.0 on a C200 hanging on a 100Mb switch. I have
+  > compiled libpcap-0.4 an tcpdump-3.4 and it seems to work. But at a
+  > closer look I only get to see the incoming packets not the
+  > outgoing. I have tried tcpflow-0.12 which also uses libpcap and the
+  > same thing happens.  Could someone please give me a hint on how to
+  > get this right?
+  
+  Search/Read the archives ?-)
+  
+  What you are seeing is expected, un-patched, behaviour for an HP-UX
+  system.  On 11.00, you need to install the latest lancommon/DLPI
+  patches, and then the latest driver patch for the interface(s) in use. 
+  At that point, a miracle happens and you should start seeing outbound
+  traffic.
+
+[That article also mentions the patch that appears below.]
+
+and
+
+       http://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no
+
+which says:
+
+  Newsgroups: comp.sys.hp.hpux
+  Subject: Re: tcpdump only shows incoming packets
+  Date: 02/16/2000
+  From: Harald Skotnes <harald@cc.uit.no>
+
+  Rick Jones wrote:
+  
+       ...
+
+  > What you are seeing is expected, un-patched, behaviour for an HP-UX
+  > system. On 11.00, you need to install the latest lancommon/DLPI
+  > patches, and then the latest driver patch for the interface(s) in
+  > use. At that point, a miracle happens and you should start seeing
+  > outbound traffic.
+  
+  Thanks a lot.  I have this problem on several machines running HPUX
+  10.20 and 11.00.  The machines where patched up before y2k so did not
+  know what to think.  Anyway I have now installed PHNE_19766,
+  PHNE_19826, PHNE_20008, PHNE_20735 on the C200 and now I can see the
+  outbound traffic too.  Thanks again.
+
+(although those patches may not be the ones to install - there may be
+later patches).
+
+And another message to tcpdump-workers@tcpdump.org, from Rick Jones:
+
+  Date: Mon, 29 Apr 2002 15:59:55 -0700
+  From: Rick Jones
+  To: tcpdump-workers@tcpdump.org 
+  Subject: Re: [tcpdump-workers] I Can't Capture the Outbound Traffic
+
+       ...
+
+  http://itrc.hp.com/ would be one place to start in a search for the most
+  up-to-date patches for DLPI and the lan driver(s) used on your system (I
+  cannot guess because 9000/800 is too generic - one hs to use the "model"
+  command these days and/or an ioscan command (see manpage) to guess what
+  the drivers (btlan[3456], gelan, etc) might be involved in addition to
+  DLPI.
+
+  Another option is to upgrade to 11i as outbound promiscuous mode support
+  is there in the base OS, no patches required.
+
+Another posting:
+
+       http://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com
+
+indicates that you need to install the optional STREAMS product to do
+captures on HP-UX 9.x:
+
+  Newsgroups: comp.sys.hp.hpux
+  Subject:  Re: tcpdump HP/UX 9.x
+  Date: 03/22/1999
+  From: Rick Jones <foo@bar.baz>
+
+  Dave Barr (barr@cis.ohio-state.edu) wrote:
+  : Has anyone ported tcpdump (or something similar) to HP/UX 9.x?
+  
+  I'm reasonably confident that any port of tcpdump to 9.X would require
+  the (then optional) STREAMS product.  This would bring DLPI, which is
+  what one uses to access interfaces in promiscuous mode.
+  
+  I'm not sure that HP even sells the 9.X STREAMS product any longer,
+  since HP-UX 9.X is off the pricelist (well, maybe 9.10 for the old 68K
+  devices). 
+  
+  Your best bet is to be up on 10.20 or better if that is at all
+  possible.  If your hardware is supported by it, I'd go with HP-UX 11. 
+  If you want to see the system's own outbound traffic, you'll never get
+  that functionality on 9.X, but it might happen at some point for 10.20
+  and 11.X. 
+  
+  rick jones
+
+(as per other messages cited here, the ability to see the system's own
+outbound traffic did happen).
+
+Rick Jones reports that HP-UX 11i needs no patches for outbound
+promiscuous mode support.
+
+An additional note, from Jost Martin, for HP-UX 10.20:
+
+       Q: How do I get ethereral on HPUX to capture the _outgoing_ packets
+          of an interface
+       A: You need to get PHNE_20892,PHNE_20725 and PHCO_10947 (or
+          newer, this is as of 4.4.00) and its dependencies.  Then you can
+          enable the feature as descibed below:
+
+       Patch Name: PHNE_20892
+       Patch Description: s700 10.20 PCI 100Base-T cumulative patch
+               To trace the outbound packets, please do the following
+               to turn on a global promiscuous switch before running
+               the promiscuous applications like snoop or tcpdump:
+
+               adb -w /stand/vmunix /dev/mem
+               lanc_outbound_promisc_flag/W 1
+               (adb will echo the result showing that the flag has
+               been changed)
+               $quit
+       (Thanks for this part to HP-support, Ratingen)
+
+               The attached hack does this and some security-related stuff
+       (thanks to hildeb@www.stahl.bau.tu-bs.de (Ralf Hildebrandt) who
+       posted the security-part some time ago)
+
+                <<hack_ip_stack>> 
+
+               (Don't switch IP-forwarding off, if you need it !)
+               Install the hack as /sbin/init.d/hacl_ip_stack (adjust
+       permissions !) and make a sequencing-symlink
+       /sbin/rc2.d/S350hack_ip_stack pointing to this script. 
+               Now all this is done on every reboot.
+
+According to Rick Jones, the global promiscuous switch also has to be
+turned on for HP-UX 11.00, but not for 11i - and, in fact, the switch
+doesn't even exist on 11i.
+
+Here's the "hack_ip_stack" script:
+
+-----------------------------------Cut Here-------------------------------------
+#!/sbin/sh
+#
+# nettune:  hack kernel parms for safety
+
+OKAY=0
+ERROR=-1
+
+# /usr/contrib/bin fuer nettune auf Pfad
+PATH=/sbin:/usr/sbin:/usr/bin:/usr/contrib/bin
+export PATH
+
+
+##########
+#  main  #
+##########
+
+case $1 in
+   start_msg)
+      print "Tune IP-Stack for security"
+      exit $OKAY
+      ;;
+
+   stop_msg)
+      print "This action is not applicable"
+      exit $OKAY
+      ;;
+
+   stop)
+      exit $OKAY
+      ;;
+
+   start)
+      ;;  # fall through
+
+   *)
+      print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2
+      exit $ERROR
+      ;;
+   esac
+
+###########
+#  start  #
+###########
+
+#
+# tcp-Sequence-Numbers nicht mehr inkrementieren sondern random
+# Syn-Flood-Protection an
+# ip_forwarding aus
+# Source-Routing aus
+# Ausgehende Packets an ethereal/tcpdump etc.
+
+/usr/contrib/bin/nettune -s tcp_random_seq 2 || exit $ERROR
+/usr/contrib/bin/nettune -s hp_syn_protect 1 || exit $ERROR
+/usr/contrib/bin/nettune -s ip_forwarding 0 || exit $ERROR
+echo 'ip_block_source_routed/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem || exit $ERROR
+echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem  || exit $ERROR
+
+exit $OKAY
+-----------------------------------Cut Here-------------------------------------
diff --git a/README.linux b/README.linux
new file mode 100644 (file)
index 0000000..f92cd22
--- /dev/null
@@ -0,0 +1,108 @@
+In order for libpcap to be able to capture packets on a Linux system,
+the "packet" protocol must be supported by your kernel.  If it is not,
+you may get error messages such as
+
+       modprobe: can't locate module net-pf-17
+
+in "/var/adm/messages", or may get messages such as
+
+       socket: Address family not supported by protocol
+
+from applications using libpcap.
+
+You must configure the kernel with the CONFIG_PACKET option for this
+protocol; the following note is from the Linux "Configure.help" file for
+the 2.0[.x] kernel:
+
+       Packet socket
+       CONFIG_PACKET
+         The Packet protocol is used by applications which communicate
+         directly with network devices without an intermediate network
+         protocol implemented in the kernel, e.g. tcpdump. If you want them
+         to work, choose Y. 
+
+         This driver is also available as a module called af_packet.o ( =
+         code which can be inserted in and removed from the running kernel
+         whenever you want). If you want to compile it as a module, say M
+         here and read Documentation/modules.txt; if you use modprobe or
+         kmod, you may also want to add "alias net-pf-17 af_packet" to 
+         /etc/modules.conf.
+
+and the note for the 2.2[.x] kernel says:
+
+       Packet socket
+       CONFIG_PACKET
+         The Packet protocol is used by applications which communicate
+         directly with network devices without an intermediate network
+         protocol implemented in the kernel, e.g. tcpdump. If you want them
+         to work, choose Y. This driver is also available as a module called
+         af_packet.o ( = code which can be inserted in and removed from the
+         running kernel whenever you want). If you want to compile it as a
+         module, say M here and read Documentation/modules.txt.  You will
+         need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules
+         file for the module version to function automatically.  If unsure,
+         say Y.
+
+In addition, there is an option that, in 2.2 and later kernels, will
+allow packet capture filters specified to programs such as tcpdump to be
+executed in the kernel, so that packets that don't pass the filter won't
+be copied from the kernel to the program, rather than having all packets
+copied to the program and libpcap doing the filtering in user mode. 
+
+Copying packets from the kernel to the program consumes a significant
+amount of CPU, so filtering in the kernel can reduce the overhead of
+capturing packets if a filter has been specified that discards a
+significant number of packets.  (If no filter is specified, it makes no
+difference whether the filtering isn't performed in the kernel or isn't
+performed in user mode. :-))
+
+The option for this is the CONFIG_FILTER option; the "Configure.help"
+file says:
+
+       Socket filtering
+       CONFIG_FILTER
+         The Linux Socket Filter is derived from the Berkeley Packet Filter.
+         If you say Y here, user-space programs can attach a filter to any
+         socket and thereby tell the kernel that it should allow or disallow
+         certain types of data to get through the socket. Linux Socket
+         Filtering works on all socket types except TCP for now. See the text
+         file linux/Documentation/networking/filter.txt for more information.
+         If unsure, say N.
+
+Note that, by default, libpcap will, if libnl is present, build with it;
+it uses libnl to support monitor mode on mac80211 devices.  There is a
+configuration option to disable building with libnl, but, if that option
+is chosen, the monitor-mode APIs (as used by tcpdump's "-I" flag, and as
+will probably be used by other applications in the future) won't work
+properly on mac80211 devices.
+
+Linux's run-time linker allows shared libraries to be linked with other
+shared libraries, which means that if an older version of a shared
+library doesn't require routines from some other shared library, and a
+later version of the shared library does require those routines, the
+later version of the shared library can be linked with that other shared
+library and, if it's otherwise binary-compatible with the older version,
+can replace that older version without breaking applications built with
+the older version, and without breaking configure scripts or the build
+procedure for applications whose configure script doesn't use the
+pcap-config script if they build with the shared library.  (The build
+procedure for applications whose configure scripts use the pcap-config
+script if present will not break even if they build with the static
+library.)
+
+Statistics:
+Statistics reported by pcap are platform specific.  The statistics
+reported by pcap_stats on Linux are as follows:
+
+2.2.x
+=====
+ps_recv   Number of packets that were accepted by the pcap filter
+ps_drop   Always 0, this statistic is not gatherd on this platform
+
+2.4.x
+=====
+ps_recv   Number of packets that were accepted by the pcap filter
+ps_drop   Number of packets that had passed filtering but were not
+          passed on to pcap due to things like buffer shortage, etc.
+          This is useful because these are packets you are interested in
+          but won't be reported by, for example, tcpdump output.
diff --git a/README.macosx b/README.macosx
new file mode 100644 (file)
index 0000000..3dc9211
--- /dev/null
@@ -0,0 +1,74 @@
+As with other systems using BPF, Mac OS X allows users with read access
+to the BPF devices to capture packets with libpcap and allows users with
+write access to the BPF devices to send packets with libpcap.
+
+On some systems that use BPF, the BPF devices live on the root file
+system, and the permissions and/or ownership on those devices can be
+changed to give users other than root permission to read or write those
+devices.
+
+On newer versions of FreeBSD, the BPF devices live on devfs, and devfs
+can be configured to set the permissions and/or ownership of those
+devices to give users other than root permission to read or write those
+devices.
+
+On Mac OS X, the BPF devices live on devfs, but the OS X version of
+devfs is based on an older (non-default) FreeBSD devfs, and that version
+of devfs cannot be configured to set the permissions and/or ownership of
+those devices.
+
+Therefore, we supply:
+
+       a "startup item" for older versions of Mac OS X;
+
+       a launchd daemon for Tiger and later versions of Mac OS X;
+
+Both of them will change the ownership of the BPF devices so that the
+"admin" group owns them, and will change the permission of the BPF
+devices to rw-rw----, so that all users in the "admin" group - i.e., all
+users with "Allow user to administer this computer" turned on - have
+both read and write access to them.
+
+The startup item is in the ChmodBPF directory in the source tree.  A
+/Library/StartupItems directory should be created if it doesn't already
+exist, and the ChmodBPF directory should be copied to the
+/Library/StartupItems directory (copy the entire directory, so that
+there's a /Library/StartupItems/ChmodBPF directory, containing all the
+files in the source tree's ChmodBPF directory; don't copy the individual
+items in that directory to /Library/StartupItems).  The ChmodBPF
+directory, and all files under it, must be owned by root.  Installing
+the files won't immediately cause the startup item to be executed; it
+will be executed on the next reboot.  To change the permissions before
+the reboot, run
+
+       sudo SystemStarter start ChmodBPF
+
+The launchd daemon is the chmod_bpf script, plus the
+org.tcpdump.chmod_bpf.plist launchd plist file.  chmod_bpf should be
+installed in /usr/local/bin/chmod_bpf, and org.tcpdump.chmod_bpf.plist
+should be installed in /Library/LaunchDaemons.  chmod_bpf, and
+org.tcpdump.chmod_bpf.plist, must be owned by root.  Installing the
+script and plist file won't immediately cause the script to be executed;
+it will be executed on the next reboot.  To change the permissions
+before the reboot, run
+
+       sudo /usr/local/bin/chmod_bpf
+
+or
+
+       sudo launchctl load /Library/LaunchDaemons/org.tcpdump.chmod_bpf.plist
+
+If you want to give a particular user permission to access the BPF
+devices, rather than giving all administrative users permission to
+access them, you can have the ChmodBPF/ChmodBPF script change the
+ownership of /dev/bpf* without changing the permissions.  If you want to
+give a particular user permission to read and write the BPF devices and
+give the administrative users permission to read but not write the BPF
+devices, you can have the script change the owner to that user, the
+group to "admin", and the permissions to rw-r-----.  Other possibilities
+are left as an exercise for the reader.
+
+(NOTE: due to a bug in Snow Leopard, if you change the permissions not
+to grant write permission to everybody who should be allowed to capture
+traffic, non-root users who cannot open the BPF devices for writing will
+not be able to capture outgoing packets.)
diff --git a/README.septel b/README.septel
new file mode 100644 (file)
index 0000000..fbc88df
--- /dev/null
@@ -0,0 +1,50 @@
+The following instructions apply if you have a Linux platform and want
+libpcap to support the Septel range of passive network monitoring cards
+from Intel (http://www.intel.com)
+
+1) Install and build the Septel software distribution by following the
+instructions supplied with that package.
+
+2) Configure libcap. To allow the 'configure' script to locate the Septel
+software distribution use the '--with-septel' option:
+
+        ./configure --with-septel=DIR
+
+where DIR is the root of the Septel software distribution, for example
+/var/src/septel.
+
+By default (if you write only ./configure --with-septel) it takes
+./../septel as argument for DIR. 
+
+If the Septel software is correctly detected 'configure' will
+report:
+
+        checking whether we have Septel API... yes
+
+If 'configure' reports that there is no Septel API, the directory may have been
+incorrectly specified or the Septel software was not built before configuring
+libpcap.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+Building libpcap at this stage will include support for both the native
+packet capture stream and for capturing from Septel cards.  To build
+libpcap with only Septel support specify the capture type as 'septel'
+when configuring libpcap:
+
+        ./configure --with-septel=DIR --with-pcap=septel
+
+Applications built with libpcap configured in this way will only detect Septel
+cards and will not capture from the native OS packet stream.
+
+Note: As mentioned in pcap-septel.c we should first edit the system.txt
+file to change the user part example (UPE) module id to 0xdd instead of
+0x2d for technical reason.  So this change in system.txt is crutial and
+things will go wrong if it's not done.  System.txt along with config.txt
+are configuration files that are edited by the user before running the
+gctload program that uses these files for initialising modules and
+configuring parameters.
+
+----------------------------------------------------------------------
+for more information please contact me : gil_hoyek@hotmail.com
diff --git a/README.sita b/README.sita
new file mode 100644 (file)
index 0000000..ee7a426
--- /dev/null
@@ -0,0 +1,64 @@
+The following instructions apply if you have a Linux platform and want
+libpcap to support the 'ACN' WAN/LAN router product from from SITA
+(http://www.sita.aero)
+
+This might also work on non-Linux Unix-compatible platforms, but that
+has not been tested.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+These additions/extensions have been made to PCAP to allow it to
+capture packets from a SITA ACN device (and potentially others).
+
+To enable its support you need to ensure that the distribution has
+a correct configure.in file; that can be created if neccessay by
+using the normal autoconf procedure of:
+
+aclocal
+autoconf
+autoheader
+automake
+
+Then run configure with the 'sita' option:
+
+./configure --with-sita
+
+Applications built with libpcap configured in this way will only detect SITA
+ACN interfaces and will not capture from the native OS packet stream.
+
+The SITA extension provides a remote datascope operation for capturing
+both WAN and LAN protocols.  It effectively splits the operation of
+PCAP into two halves.  The top layer performs the majority of the
+work, but interfaces via a TCP session to remote agents that
+provide the lower layer functionality of actual sniffing and
+filtering. More detailed information regarding the functions and
+inter-device protocol and naming conventions are described in detail
+in 'pcap-sita.html'.
+
+pcap_findalldevs() reads the local system's /etc/hosts file looking
+for host names that match the format of IOP type devices.  ie.  aaa_I_x_y
+and then queries each associated IP address for a list of its WAN and
+LAN devices.  The local system the aggregates the lists obtained from
+each IOP, sorts it, and provides it (to Wireshark et.al) as the
+list of monitorable interfaces.
+
+Once a valid interface has been selected, pcap_open() is called
+which opens a TCP session (to a well known port) on the target IOP
+and tells it to start monitoring.
+
+All captured packets are then forwarded across that TCP session
+back to the local 'top layer' for forwarding to the actual
+sniffing program (wireshark...)
+
+Note that the DLT_SITA link-layer type includes a proprietary header
+that is documented as part of the SITA dissector of Wireshark and is
+also described in 'pcap-sita.html' for posterity sake.
+
+That header provides:
+- Packet direction (in/out) (1 octet)
+- Link layer hardware signal status (1 octet)
+- Transmit/Receive error status (2 octets)
+- Encapsulated WAN protocol ID (1 octet)
+
+
diff --git a/README.tru64 b/README.tru64
new file mode 100644 (file)
index 0000000..7fe1ef0
--- /dev/null
@@ -0,0 +1,49 @@
+The following instructions are applicable to Tru64 UNIX 
+(formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and
+probably to later versions as well; at least some options apply to
+Digital UNIX 3.2 - perhaps all do.
+
+In order to use kernel packet filtering on this system, you have
+to configure it in such a way:
+
+Kernel configuration
+--------------------
+
+The packet filtering kernel option must be enabled at kernel
+installation.  If it was not the case, you can rebuild the kernel with
+"doconfig -c" after adding the following line in the kernel
+configuration file (/sys/conf/<HOSTNAME>):
+
+       option PACKETFILTER
+
+or use "doconfig" without any arguments to add the packet filter driver
+option via the kernel option menu (see the system administration
+documentation for information on how to do this).
+
+Device configuration
+--------------------
+
+Devices used for packet filtering must be created thanks to
+the following command (executed in the /dev directory):
+
+       ./MAKEDEV pfilt
+
+Interface configuration
+-----------------------
+
+In order to capture all packets on a network, you may want to allow
+applications to put the interface on that network into "local copy"
+mode, so that tcpdump can see packets sent by the host on which it's
+running as well as packets received by that host, and to put the
+interface into "promiscuous" mode, so that tcpdump can see packets on
+the network segment not sent to the host on which it's running, by using
+the pfconfig(1) command:
+
+       pfconfig +c +p <network_device>
+
+or allow application to put any interface into "local copy" or
+"promiscuous" mode by using the command:
+
+       pfconfig +c +p -a
+
+Note: all instructions given require root privileges.
diff --git a/SUNOS4/nit_if.o.sparc b/SUNOS4/nit_if.o.sparc
new file mode 100644 (file)
index 0000000..d05073e
Binary files /dev/null and b/SUNOS4/nit_if.o.sparc differ
diff --git a/SUNOS4/nit_if.o.sun3 b/SUNOS4/nit_if.o.sun3
new file mode 100644 (file)
index 0000000..c393fc6
Binary files /dev/null and b/SUNOS4/nit_if.o.sun3 differ
diff --git a/SUNOS4/nit_if.o.sun4c.4.0.3c b/SUNOS4/nit_if.o.sun4c.4.0.3c
new file mode 100644 (file)
index 0000000..ef01039
Binary files /dev/null and b/SUNOS4/nit_if.o.sun4c.4.0.3c differ
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..73325e1
--- /dev/null
+++ b/TODO
@@ -0,0 +1,35 @@
+ TODO list for libpcap
+=======================
+
+Important stuff (to be done before the next release)
+---------------
+
+General
+
+- configure should not be in Git. Most open source projects have an 
+  autogen.sh script to run autoconf etc. after checkout. I think we 
+  should stick to the standard. 
+
+- The source files should be better documented. There is no official 
+  design guideline for what is done where. There should be a common coding
+  style (okay, you can guess that by looking at the code) and a guide for
+  what needs to be documented.
+
+Less urgent items
+-----------------
+
+- Better documentation and cleanup of the interface. I am seeing a few  
+  problems at the first glance which needs fixing:
+  + pcap_lookupnet makes little to no sense with protocols != IPv4
+  + not very well suited for interactive programs (think ethereal). There
+    should be a way for the application to get a file descriptor which it
+    has to monitor and a callback in pcap which has to be called on
+    activity (XXX - "pcap_fileno()" handles the first part, although
+    "select()" and "poll()" don't work on BPF devices on most BSDs, and
+    you can call "pcap_dispatch()" as the dispatch routine after putting
+    the descriptor into non-blocking mode)
+  + too many functions. There are a lot of functions for everything which
+    violates the KISS principle. Why do we need pcap_strerror, pcap_perror
+    and pcap_geterr?
+  + the manpage has a brief description of each function but where is the
+    big picture? Seems like you need to buy UNP for that...
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..f0bb29e
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.3.0
diff --git a/Win32/Include/Gnuc.h b/Win32/Include/Gnuc.h
new file mode 100644 (file)
index 0000000..0bf4b73
--- /dev/null
@@ -0,0 +1,46 @@
+/* @(#) $Header: /tcpdump/master/libpcap/Win32/Include/Gnuc.h,v 1.1 2002-08-01 08:33:05 risso Exp $ (LBL) */
+
+/* Define __P() macro, if necessary */
+
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifndef __cplusplus
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+#endif
+
+/*
+ * Handle new and old "dead" routine prototypes
+ *
+ * For example:
+ *
+ *     __dead void foo(void) __attribute__((volatile));
+ *
+ */
+#ifdef __GNUC__
+#ifndef __dead
+#define __dead volatile
+#endif
+#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
+#else
+#ifndef __dead
+#define __dead
+#endif
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
diff --git a/Win32/Include/addrinfo.h b/Win32/Include/addrinfo.h
new file mode 100644 (file)
index 0000000..8cb2e65
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: addrinfo.h,v 1.1 2002-08-01 08:33:05 risso Exp $ */
+
+#ifndef HAVE_ADDRINFO
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#define        EAI_ADDRFAMILY   1      /* address family for hostname not supported */
+#define        EAI_AGAIN        2      /* temporary failure in name resolution */
+#define        EAI_BADFLAGS     3      /* invalid value for ai_flags */
+#define        EAI_FAIL         4      /* non-recoverable failure in name resolution */
+#define        EAI_FAMILY       5      /* ai_family not supported */
+#define        EAI_MEMORY       6      /* memory allocation failure */
+#define        EAI_NODATA       7      /* no address associated with hostname */
+#define        EAI_NONAME       8      /* hostname nor servname provided, or not known */
+#define        EAI_SERVICE      9      /* servname not supported for ai_socktype */
+#define        EAI_SOCKTYPE    10      /* ai_socktype not supported */
+#define        EAI_SYSTEM      11      /* system error returned in errno */
+#define EAI_BADHINTS   12
+#define EAI_PROTOCOL   13
+#define EAI_MAX                14
+
+/* internal error */
+#define        NETDB_INTERNAL  -1      /* see errno */
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define        AI_PASSIVE      0x00000001 /* get address to use bind() */
+#define        AI_CANONNAME    0x00000002 /* fill ai_canonname */
+#define        AI_NUMERICHOST  0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define        AI_MASK         (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define        AI_ALL          0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define        AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define        AI_ADDRCONFIG   0x00000400 /* only if any address is assigned */
+#define        AI_V4MAPPED     0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define        AI_DEFAULT      (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+
+extern void freeaddrinfo (struct addrinfo *);
+extern void freehostent (struct hostent *);
+extern char *gai_strerror (int);
+extern int getaddrinfo (const char *, const char *,
+                           const struct addrinfo *, struct addrinfo **);
+extern int getnameinfo (const struct sockaddr *, size_t, char *,
+                           size_t, char *, size_t, int);
+extern struct hostent *getipnodebyaddr (const void *, size_t, int, int *);
+extern struct hostent *getipnodebyname (const char *, int, int, int *);
+extern int inet_pton (int, const char *, void *);
+extern const char *inet_ntop (int, const void *, char *, size_t);
+#else
+
+#ifndef EAI_BADHINTS
+#define EAI_BADHINTS   12
+#endif 
+
+#ifndef EAI_PROTOCOL   
+#define EAI_PROTOCOL   13
+#endif
+
+#ifndef EAI_MAX        
+#define EAI_MAX                14
+#endif
+
+#ifndef NETDB_INTERNAL
+#define        NETDB_INTERNAL  -1      /* see errno */
+#endif
+
+#ifndef AI_MASK
+/* valid flags for addrinfo */
+#define        AI_MASK         (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+#endif
+
+#endif /* HAVE_ADDRINFO */
+
+/*
+ * Constants for getnameinfo()
+ */
+#ifndef NI_MAXHOST
+#define        NI_MAXHOST      1025
+#endif
+#ifndef NI_MAXSERV
+#define        NI_MAXSERV      32
+#endif
+
+/*
+ * Flag values for getnameinfo()
+ */
+#ifndef NI_NOFQDN
+#define        NI_NOFQDN       0x00000001
+#endif
+#ifndef NI_NUMERICHOST
+#define        NI_NUMERICHOST  0x00000002
+#endif
+#ifndef NI_NAMEREQD
+#define        NI_NAMEREQD     0x00000004
+#endif
+#ifndef NI_NUMERICSERV
+#define        NI_NUMERICSERV  0x00000008
+#endif
+#ifndef NI_DGRAM
+#define        NI_DGRAM        0x00000010
+#endif
+
diff --git a/Win32/Include/arpa/nameser.h b/Win32/Include/arpa/nameser.h
new file mode 100644 (file)
index 0000000..18f185c
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * ++Copyright++ 1983, 1989, 1993
+ * -
+ * Copyright (c) 1983, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ *      @(#)nameser.h  8.1 (Berkeley) 6/2/93
+ *     nameser.h,v 1.2 1995/05/06 14:23:54 hjl Exp
+ */
+
+#ifndef _NAMESER_H_
+#define        _NAMESER_H_
+
+#ifndef WIN32
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+#include <sys/cdefs.h>
+#else 
+#include <pcap-stdinc.h>
+#define __LITTLE_ENDIAN 1
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+/*
+ * revision information.  this is the release date in YYYYMMDD format.
+ * it can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__BIND > 19931104)".  do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define        __BIND          19940417        /* interface version stamp */
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ       512             /* maximum packet size */
+#define MAXDNAME       256             /* maximum domain name */
+#define MAXCDNAME      255             /* maximum compressed domain name */
+#define MAXLABEL       63              /* maximum length of domain label */
+#define        HFIXEDSZ        12              /* #/bytes of fixed data in header */
+#define QFIXEDSZ       4               /* #/bytes of fixed data in query */
+#define RRFIXEDSZ      10              /* #/bytes of fixed data in r record */
+#define        INT32SZ         4               /* for systems without 32-bit ints */
+#define        INT16SZ         2               /* for systems without 16-bit ints */
+#define        INADDRSZ        4               /* for sizeof(struct inaddr) != 4 */
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT        53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY          0x0             /* standard query */
+#define IQUERY         0x1             /* inverse query */
+#define STATUS         0x2             /* nameserver status query */
+/*#define xxx          0x3             *//* 0x3 reserved */
+#define        NS_NOTIFY_OP    0x4             /* notify secondary of SOA change */
+#ifdef ALLOW_UPDATES
+       /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */
+# define UPDATEA       0x9             /* add resource record */
+# define UPDATED       0xa             /* delete a specific resource record */
+# define UPDATEDA      0xb             /* delete all named resource record */
+# define UPDATEM       0xc             /* modify a specific resource record */
+# define UPDATEMA      0xd             /* modify all named resource record */
+# define ZONEINIT      0xe             /* initial zone transfer */
+# define ZONEREF       0xf             /* incremental zone referesh */
+#endif
+
+/*
+ * Currently defined response codes
+ */
+#ifdef HAVE_ADDRINFO
+#define NOERROR                0               /* no error */
+#endif /* HAVE_ADDRINFO */
+#define FORMERR                1               /* format error */
+#define SERVFAIL       2               /* server failure */
+#define NXDOMAIN       3               /* non existent domain */
+#define NOTIMP         4               /* not implemented */
+#define REFUSED                5               /* query refused */
+#ifdef ALLOW_UPDATES
+       /* non standard */
+# define NOCHANGE      0xf             /* update failed to change db */
+#endif
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A            1               /* host address */
+#define T_NS           2               /* authoritative server */
+#define T_MD           3               /* mail destination */
+#define T_MF           4               /* mail forwarder */
+#define T_CNAME                5               /* canonical name */
+#define T_SOA          6               /* start of authority zone */
+#define T_MB           7               /* mailbox domain name */
+#define T_MG           8               /* mail group member */
+#define T_MR           9               /* mail rename name */
+#define T_NULL         10              /* null resource record */
+#define T_WKS          11              /* well known service */
+#define T_PTR          12              /* domain name pointer */
+#define T_HINFO                13              /* host information */
+#define T_MINFO                14              /* mailbox information */
+#define T_MX           15              /* mail routing information */
+#define T_TXT          16              /* text strings */
+#define        T_RP            17              /* responsible person */
+#define T_AFSDB                18              /* AFS cell database */
+#define T_X25          19              /* X_25 calling address */
+#define T_ISDN         20              /* ISDN calling address */
+#define T_RT           21              /* router */
+#define T_NSAP         22              /* NSAP address */
+#define T_NSAP_PTR     23              /* reverse NSAP lookup (deprecated) */
+#define        T_SIG           24              /* security signature */
+#define        T_KEY           25              /* security key */
+#define        T_PX            26              /* X.400 mail mapping */
+#define        T_GPOS          27              /* geographical position (withdrawn) */
+#define        T_AAAA          28              /* IP6 Address */
+#define        T_LOC           29              /* Location Information */
+       /* non standard */
+#define T_UINFO                100             /* user (finger) information */
+#define T_UID          101             /* user ID */
+#define T_GID          102             /* group ID */
+#define T_UNSPEC       103             /* Unspecified format (binary data) */
+       /* Query type values which do not appear in resource records */
+#define T_AXFR         252             /* transfer zone of authority */
+#define T_MAILB                253             /* transfer mailbox records */
+#define T_MAILA                254             /* transfer mail agent records */
+#define T_ANY          255             /* wildcard match */
+
+/*
+ * Values for class field
+ */
+
+#define C_IN           1               /* the arpa internet */
+#define C_CHAOS                3               /* for chaos net (MIT) */
+#define C_HS           4               /* for Hesiod name server (MIT) (XXX) */
+       /* Query class values which do not appear in resource records */
+#define C_ANY          255             /* wildcard match */
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS   0
+#define CONV_OVERFLOW  (-1)
+#define CONV_BADFMT    (-2)
+#define CONV_BADCKSUM  (-3)
+#define CONV_BADBUFLEN (-4)
+
+#ifndef __BYTE_ORDER
+#if (BSD >= 199103)
+# include <machine/endian.h>
+#else
+#ifdef linux
+# include <endian.h>
+#else
+#define        __LITTLE_ENDIAN 1234    /* least-significant byte first (vax, pc) */
+#define        __BIG_ENDIAN    4321    /* most-significant byte first (IBM, net) */
+#define        __PDP_ENDIAN    3412    /* LSB first in word, MSW first in long (pdp)*/
+
+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
+    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+    defined(__alpha__) || defined(__alpha)
+#define __BYTE_ORDER   __LITTLE_ENDIAN
+#endif
+
+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
+    defined(apollo) || defined(__convex__) || defined(_CRAY) || \
+    defined(__hppa) || defined(__hp9000) || \
+    defined(__hp9000s300) || defined(__hp9000s700) || \
+    defined (BIT_ZERO_ON_LEFT) || defined(m68k)
+#define __BYTE_ORDER   __BIG_ENDIAN
+#endif
+#endif /* linux */
+#endif /* BSD */
+#endif /* __BYTE_ORDER */
+
+#if !defined(__BYTE_ORDER) || \
+    (__BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN && \
+    __BYTE_ORDER != __PDP_ENDIAN)
+       /* you must determine what the correct bit order is for
+        * your compiler - the next line is an intentional error
+        * which will force your compiles to bomb until you fix
+        * the above macros.
+        */
+  error "Undefined or invalid __BYTE_ORDER";
+#endif
+
+/*
+ * Structure for query header.  The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields.  We use bit fields only in int variables, as this
+ * is all ANSI requires.  This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+       unsigned        id :16;         /* query identification number */
+#if __BYTE_ORDER == __BIG_ENDIAN
+                       /* fields in third byte */
+       unsigned        qr: 1;          /* response flag */
+       unsigned        opcode: 4;      /* purpose of message */
+       unsigned        aa: 1;          /* authoritive answer */
+       unsigned        tc: 1;          /* truncated message */
+       unsigned        rd: 1;          /* recursion desired */
+                       /* fields in fourth byte */
+       unsigned        ra: 1;          /* recursion available */
+       unsigned        pr: 1;          /* primary server req'd (!standard) */
+       unsigned        unused :2;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        rcode :4;       /* response code */
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
+                       /* fields in third byte */
+       unsigned        rd :1;          /* recursion desired */
+       unsigned        tc :1;          /* truncated message */
+       unsigned        aa :1;          /* authoritive answer */
+       unsigned        opcode :4;      /* purpose of message */
+       unsigned        qr :1;          /* response flag */
+                       /* fields in fourth byte */
+       unsigned        rcode :4;       /* response code */
+       unsigned        unused :2;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        pr :1;          /* primary server req'd (!standard) */
+       unsigned        ra :1;          /* recursion available */
+#endif
+                       /* remaining bytes */
+       unsigned        qdcount :16;    /* number of question entries */
+       unsigned        ancount :16;    /* number of answer entries */
+       unsigned        nscount :16;    /* number of authority entries */
+       unsigned        arcount :16;    /* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK     0xc0
+
+/*
+ * Structure for passing resource records around.
+ */
+struct rrec {
+       int16_t         r_zone;                 /* zone number */
+       int16_t         r_class;                /* class number */
+       int16_t         r_type;                 /* type number */
+       u_int32_t       r_ttl;                  /* time to live */
+       int             r_size;                 /* size of data area */
+       char            *r_data;                /* pointer to data */
+};
+
+//extern       u_int16_t       _getshort __P((const u_char *));
+//extern       u_int32_t       _getlong __P((const u_char *));
+
+/*
+ * Inline versions of get/put short/long.  Pointer is advanced.
+ *
+ * These macros demonstrate the property of C whereby it can be
+ * portable or it can be elegant but rarely both.
+ */
+#define GETSHORT(s, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (s) = ((u_int16_t)t_cp[0] << 8) \
+           | ((u_int16_t)t_cp[1]) \
+           ; \
+       (cp) += INT16SZ; \
+}
+
+#define GETLONG(l, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (l) = ((u_int32_t)t_cp[0] << 24) \
+           | ((u_int32_t)t_cp[1] << 16) \
+           | ((u_int32_t)t_cp[2] << 8) \
+           | ((u_int32_t)t_cp[3]) \
+           ; \
+       (cp) += INT32SZ; \
+}
+
+#define PUTSHORT(s, cp) { \
+       register u_int16_t t_s = (u_int16_t)(s); \
+       register u_char *t_cp = (u_char *)(cp); \
+       *t_cp++ = t_s >> 8; \
+       *t_cp   = t_s; \
+       (cp) += INT16SZ; \
+}
+
+#define PUTLONG(l, cp) { \
+       register u_int32_t t_l = (u_int32_t)(l); \
+       register u_char *t_cp = (u_char *)(cp); \
+       *t_cp++ = t_l >> 24; \
+       *t_cp++ = t_l >> 16; \
+       *t_cp++ = t_l >> 8; \
+       *t_cp   = t_l; \
+       (cp) += INT32SZ; \
+}
+
+#endif /* !_NAMESER_H_ */
diff --git a/Win32/Include/bittypes.h b/Win32/Include/bittypes.h
new file mode 100644 (file)
index 0000000..7c0cbde
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _BITTYPES_H
+#define _BITTYPES_H
+
+#ifndef HAVE_U_INT8_T
+typedef unsigned char u_int8_t;
+typedef signed char int8_t;
+#endif /* HAVE_U_INT8_T */
+
+#ifndef HAVE_U_INT16_T 
+typedef unsigned short u_int16_t;
+typedef signed short int16_t;
+#endif /* HAVE_U_INT16_T */
+
+#ifndef HAVE_U_INT32_T
+typedef unsigned int u_int32_t;
+typedef signed int int32_t;
+#endif /* HAVE_U_INT32_T */
+
+#ifndef HAVE_U_INT64_T
+#ifdef _MSC_EXTENSIONS
+typedef unsigned _int64 u_int64_t;
+typedef _int64 int64_t;
+#else /* _MSC_EXTENSIONS */
+typedef unsigned long long u_int64_t;
+typedef long long int64_t;
+#endif /* _MSC_EXTENSIONS */
+#endif /* HAVE_U_INT64_T */
+
+#ifndef PRId64
+#ifdef _MSC_EXTENSIONS
+#define PRId64 "I64d"
+#else /* _MSC_EXTENSIONS */
+#define PRId64 "lld"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRId64 */
+
+#ifndef PRIo64
+#ifdef _MSC_EXTENSIONS
+#define PRIo64 "I64o"
+#else /* _MSC_EXTENSIONS */
+#define PRIo64 "llo"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIo64 */
+
+#ifndef PRIx64
+#ifdef _MSC_EXTENSIONS
+#define PRIx64 "I64x"
+#else /* _MSC_EXTENSIONS */
+#define PRIx64 "llx"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIx64 */
+
+#ifndef PRIu64
+#ifdef _MSC_EXTENSIONS
+#define PRIu64 "I64u"
+#else /* _MSC_EXTENSIONS */
+#define PRIu64 "llu"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIu64 */
+
+#endif /* _BITTYPES_H */
diff --git a/Win32/Include/cdecl_ext.h b/Win32/Include/cdecl_ext.h
new file mode 100644 (file)
index 0000000..9591db2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef HAVE_PORTABLE_PROTOTYPE
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* full-blown ANSI C */
+#else
+#define        __P(protos)     ()              /* traditional C preprocessor */
+#endif
+
+#endif /* !HAVE_PORTABLE_PROTOTYPE */
diff --git a/Win32/Include/inetprivate.h b/Win32/Include/inetprivate.h
new file mode 100644 (file)
index 0000000..e25ed3d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <net/netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <arpa/nameser.h>
+
+extern void _sethtent(int f);
+extern void _endhtent(void);
+extern struct hostent *_gethtent(void);
+extern struct hostent *_gethtbyname(const char *name);
+extern struct hostent *_gethtbyaddr(const char *addr, int len,
+                int type);
+extern int _validuser(FILE *hostf, const char *rhost,
+                const char *luser, const char *ruser, int baselen);
+extern int _checkhost(const char *rhost, const char *lhost, int len);
+#if 0
+extern void putlong(u_long l, u_char *msgp);
+extern void putshort(u_short l, u_char *msgp);
+extern u_int32_t _getlong(register const u_char *msgp);
+extern u_int16_t _getshort(register const u_char *msgp);
+extern void p_query(char *msg);
+extern void fp_query(char *msg, FILE *file);
+extern char *p_cdname(char *cp, char *msg, FILE *file);
+extern char *p_rr(char *cp, char *msg, FILE *file);
+extern char *p_type(int type);
+extern char * p_class(int class);
+extern char *p_time(u_long value);
+#endif
+extern char * hostalias(const char *name);
+extern void sethostfile(char *name);
+extern void _res_close (void);
+extern void ruserpass(const char *host, char **aname, char **apass);
diff --git a/Win32/Include/ip6_misc.h b/Win32/Include/ip6_misc.h
new file mode 100644 (file)
index 0000000..562fa61
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1993, 1994, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.5 2006-01-22 18:02:18 gianluca Exp $ (LBL)
+ */
+
+/*
+ * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
+ */
+
+#include <winsock2.h>
+
+#include <ws2tcpip.h>
+
+#ifndef __MINGW32__
+#define        IN_MULTICAST(a)         IN_CLASSD(a)
+#endif
+
+#define        IN_EXPERIMENTAL(a)      ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
+
+#define        IN_LOOPBACKNET          127
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+       u_int8_t                u6_addr8[16];
+       u_int16_t       u6_addr16[8];
+       u_int32_t       u6_addr32[4];
+      } in6_u;
+#define s6_addr                        in6_u.u6_addr8
+#define s6_addr16              in6_u.u6_addr16
+#define s6_addr32              in6_u.u6_addr32
+#define s6_addr64              in6_u.u6_addr64
+  };
+
+#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+#endif /* __MINGW32__ */
+
+
+#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
+typedef unsigned short sa_family_t;
+#endif
+
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+
+#define        __SOCKADDR_COMMON(sa_prefix) \
+  sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6.  */
+struct sockaddr_in6
+  {
+    __SOCKADDR_COMMON (sin6_);
+    u_int16_t sin6_port;               /* Transport layer port # */
+    u_int32_t sin6_flowinfo;   /* IPv6 flow information */
+    struct in6_addr sin6_addr; /* IPv6 address */
+  };
+
+#define IN6_IS_ADDR_V4MAPPED(a) \
+       ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
+        (((u_int32_t *) (a))[2] == htonl (0xffff)))
+
+#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+       ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
+
+#define IN6_IS_ADDR_LOOPBACK(a) \
+       (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
+        ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
+#endif /* __MINGW32__ */
+
+#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
+#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define nd_rd_type               nd_rd_hdr.icmp6_type
+#define nd_rd_code               nd_rd_hdr.icmp6_code
+#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
+
+/*
+ *     IPV6 extension headers
+ */
+#define IPPROTO_HOPOPTS                0       /* IPv6 hop-by-hop options      */
+#define IPPROTO_IPV6           41  /* IPv6 header.  */
+#define IPPROTO_ROUTING                43      /* IPv6 routing header          */
+#define IPPROTO_FRAGMENT       44      /* IPv6 fragmentation header    */
+#define IPPROTO_ESP            50      /* encapsulating security payload */
+#define IPPROTO_AH             51      /* authentication header        */
+#define IPPROTO_ICMPV6         58      /* ICMPv6                       */
+#define IPPROTO_NONE           59      /* IPv6 no next header          */
+#define IPPROTO_DSTOPTS                60      /* IPv6 destination options     */
+#define IPPROTO_PIM                    103 /* Protocol Independent Multicast.  */
+
+#define         IPV6_RTHDR_TYPE_0 0
+
+/* Option types and related macros */
+#define IP6OPT_PAD1            0x00    /* 00 0 00000 */
+#define IP6OPT_PADN            0x01    /* 00 0 00001 */
+#define IP6OPT_JUMBO           0xC2    /* 11 0 00010 = 194 */
+#define IP6OPT_JUMBO_LEN       6
+#define IP6OPT_ROUTER_ALERT    0x05    /* 00 0 00101 */
+
+#define IP6OPT_RTALERT_LEN     4
+#define IP6OPT_RTALERT_MLD     0       /* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP    1       /* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET  2       /* contains an Active Networks msg */
+#define IP6OPT_MINLEN          2
+
+#define IP6OPT_BINDING_UPDATE  0xc6    /* 11 0 00110 */
+#define IP6OPT_BINDING_ACK     0x07    /* 00 0 00111 */
+#define IP6OPT_BINDING_REQ     0x08    /* 00 0 01000 */
+#define IP6OPT_HOME_ADDRESS    0xc9    /* 11 0 01001 */
+#define IP6OPT_EID             0x8a    /* 10 0 01010 */
+
+#define IP6OPT_TYPE(o)         ((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP       0x00
+#define IP6OPT_TYPE_DISCARD    0x40
+#define IP6OPT_TYPE_FORCEICMP  0x80
+#define IP6OPT_TYPE_ICMP       0xC0
+
+#define IP6OPT_MUTABLE         0x20
+
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif
+#endif /* __MINGW32__ */
diff --git a/Win32/Include/net/if.h b/Win32/Include/net/if.h
new file mode 100644 (file)
index 0000000..bf926b6
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)if.h        8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/net/if.h,v 1.49.2.1 1999/08/29 16:28:15 peter Exp $
+ */
+
+#ifndef _NET_IF_H_
+#define        _NET_IF_H_
+/*
+ * <net/if.h> does not depend on <sys/time.h> on most other systems.  This
+ * helps userland compatability.  (struct timeval ifi_lastchange)
+ */
+#ifndef KERNEL
+#include <pcap-stdinc.h>
+#endif
+
+/*
+ * Structure describing information about an interface
+ * which may be of interest to management entities.
+ */
+struct if_data {
+       /* generic interface information */
+       u_char  ifi_type;               /* ethernet, tokenring, etc */
+       u_char  ifi_physical;           /* e.g., AUI, Thinnet, 10base-T, etc */
+       u_char  ifi_addrlen;            /* media address length */
+       u_char  ifi_hdrlen;             /* media header length */
+       u_char  ifi_recvquota;          /* polling quota for receive intrs */
+       u_char  ifi_xmitquota;          /* polling quota for xmit intrs */
+       u_long  ifi_mtu;                /* maximum transmission unit */
+       u_long  ifi_metric;             /* routing metric (external only) */
+       u_long  ifi_baudrate;           /* linespeed */
+       /* volatile statistics */
+       u_long  ifi_ipackets;           /* packets received on interface */
+       u_long  ifi_ierrors;            /* input errors on interface */
+       u_long  ifi_opackets;           /* packets sent on interface */
+       u_long  ifi_oerrors;            /* output errors on interface */
+       u_long  ifi_collisions;         /* collisions on csma interfaces */
+       u_long  ifi_ibytes;             /* total number of octets received */
+       u_long  ifi_obytes;             /* total number of octets sent */
+       u_long  ifi_imcasts;            /* packets received via multicast */
+       u_long  ifi_omcasts;            /* packets sent via multicast */
+       u_long  ifi_iqdrops;            /* dropped on input, this interface */
+       u_long  ifi_noproto;            /* destined for unsupported protocol */
+       u_long  ifi_recvtiming;         /* usec spent receiving when timing */
+       u_long  ifi_xmittiming;         /* usec spent xmitting when timing */
+       struct  timeval ifi_lastchange; /* time of last administrative change */
+};
+
+/* ws2tcpip.h has interface flags: IFF_* */
+#if 0
+#define        IFF_UP          0x1             /* interface is up */
+#define        IFF_BROADCAST   0x2             /* broadcast address valid */
+#define        IFF_DEBUG       0x4             /* turn on debugging */
+#define        IFF_LOOPBACK    0x8             /* is a loopback net */
+#define        IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
+/*#define IFF_NOTRAILERS 0x20           * obsolete: avoid use of trailers */
+#define        IFF_RUNNING     0x40            /* resources allocated */
+#define        IFF_NOARP       0x80            /* no address resolution protocol */
+#define        IFF_PROMISC     0x100           /* receive all packets */
+#define        IFF_ALLMULTI    0x200           /* receive all multicast packets */
+#define        IFF_OACTIVE     0x400           /* transmission in progress */
+#define        IFF_SIMPLEX     0x800           /* can't hear own transmissions */
+#define        IFF_LINK0       0x1000          /* per link layer defined bit */
+#define        IFF_LINK1       0x2000          /* per link layer defined bit */
+#define        IFF_LINK2       0x4000          /* per link layer defined bit */
+#define        IFF_ALTPHYS     IFF_LINK2       /* use alternate physical connection */
+#define        IFF_MULTICAST   0x8000          /* supports multicast */
+#endif /* 0 */
+
+/* flags set internally only: */
+#define        IFF_CANTCHANGE \
+       (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
+           IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
+
+#define        IFQ_MAXLEN      50
+#define        IFNET_SLOWHZ    1               /* granularity is 1 second */
+
+/*
+ * Message format for use in obtaining information about interfaces
+ * from getkerninfo and the routing socket
+ */
+struct if_msghdr {
+       u_short ifm_msglen;     /* to skip over non-understood messages */
+       u_char  ifm_version;    /* future binary compatability */
+       u_char  ifm_type;       /* message type */
+       int     ifm_addrs;      /* like rtm_addrs */
+       int     ifm_flags;      /* value of if_flags */
+       u_short ifm_index;      /* index for associated ifp */
+       struct  if_data ifm_data;/* statistics and other data about if */
+};
+
+/*
+ * Message format for use in obtaining information about interface addresses
+ * from getkerninfo and the routing socket
+ */
+struct ifa_msghdr {
+       u_short ifam_msglen;    /* to skip over non-understood messages */
+       u_char  ifam_version;   /* future binary compatability */
+       u_char  ifam_type;      /* message type */
+       int     ifam_addrs;     /* like rtm_addrs */
+       int     ifam_flags;     /* value of ifa_flags */
+       u_short ifam_index;     /* index for associated ifp */
+       int     ifam_metric;    /* value of ifa_metric */
+};
+
+/*
+ * Message format for use in obtaining information about multicast addresses
+ * from the routing socket
+ */
+struct ifma_msghdr {
+       u_short ifmam_msglen;   /* to skip over non-understood messages */
+       u_char  ifmam_version;  /* future binary compatability */
+       u_char  ifmam_type;     /* message type */
+       int     ifmam_addrs;    /* like rtm_addrs */
+       int     ifmam_flags;    /* value of ifa_flags */
+       u_short ifmam_index;    /* index for associated ifp */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's.  All interface ioctl's must have parameter
+ * definitions which begin with ifr_name.  The
+ * remainder may be interface specific.
+ */
+struct ifreq {
+#define        IFNAMSIZ        16
+       char    ifr_name[IFNAMSIZ];             /* if name, e.g. "en0" */
+       union {
+               struct  sockaddr ifru_addr;
+               struct  sockaddr ifru_dstaddr;
+               struct  sockaddr ifru_broadaddr;
+               short   ifru_flags;
+               int     ifru_metric;
+               int     ifru_mtu;
+               int     ifru_phys;
+               int     ifru_media;
+               caddr_t ifru_data;
+       } ifr_ifru;
+#define        ifr_addr        ifr_ifru.ifru_addr      /* address */
+#define        ifr_dstaddr     ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
+#define        ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address */
+#define        ifr_flags       ifr_ifru.ifru_flags     /* flags */
+#define        ifr_metric      ifr_ifru.ifru_metric    /* metric */
+#define        ifr_mtu         ifr_ifru.ifru_mtu       /* mtu */
+#define ifr_phys       ifr_ifru.ifru_phys      /* physical wire */
+#define ifr_media      ifr_ifru.ifru_media     /* physical media */
+#define        ifr_data        ifr_ifru.ifru_data      /* for use by interface */
+};
+
+#define        _SIZEOF_ADDR_IFREQ(ifr) \
+       ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
+        (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
+         (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
+
+struct ifaliasreq {
+       char    ifra_name[IFNAMSIZ];            /* if name, e.g. "en0" */
+       struct  sockaddr ifra_addr;
+       struct  sockaddr ifra_broadaddr;
+       struct  sockaddr ifra_mask;
+};
+
+struct ifmediareq {
+       char    ifm_name[IFNAMSIZ];     /* if name, e.g. "en0" */
+       int     ifm_current;            /* current media options */
+       int     ifm_mask;               /* don't care mask */
+       int     ifm_status;             /* media status */
+       int     ifm_active;             /* active options */
+       int     ifm_count;              /* # entries in ifm_ulist array */
+       int     *ifm_ulist;             /* media words */
+};
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+struct ifconf {
+       int     ifc_len;                /* size of associated buffer */
+       union {
+               caddr_t ifcu_buf;
+               struct  ifreq *ifcu_req;
+       } ifc_ifcu;
+#define        ifc_buf ifc_ifcu.ifcu_buf       /* buffer address */
+#define        ifc_req ifc_ifcu.ifcu_req       /* array of structures returned */
+};
+
+#ifdef KERNEL
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_IFADDR);
+MALLOC_DECLARE(M_IFMADDR);
+#endif
+#endif
+
+/* XXX - this should go away soon */
+#ifdef KERNEL
+#include <net/if_var.h>
+#endif
+
+#endif /* !_NET_IF_H_ */
diff --git a/Win32/Include/net/netdb.h b/Win32/Include/net/netdb.h
new file mode 100644 (file)
index 0000000..b9d45ac
--- /dev/null
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)netdb.h     8.1 (Berkeley) 6/2/93
+ *      netdb.h,v 1.4 1995/08/14 04:05:04 hjl Exp
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
+#include <stdio.h>
+#include <netinet/in.h>
+#endif
+
+#include <winsock2.h>
+#include <net/paths.h>
+
+#define _PATH_HEQUIV   __PATH_ETC_INET"/hosts.equiv"
+#define _PATH_HOSTS    __PATH_ETC_INET"/hosts"
+#define _PATH_NETWORKS __PATH_ETC_INET"/networks"
+#define _PATH_PROTOCOLS        __PATH_ETC_INET"/protocols"
+#define _PATH_SERVICES __PATH_ETC_INET"/services"
+#define _PATH_RESCONF  __PATH_ETC_INET"/resolv.conf"
+#define _PATH_RPC      __PATH_ETC_INET"/rpc"
+
+struct rpcent {
+       char    *r_name;        /* name of server for this rpc program */
+       char    **r_aliases;    /* alias list */
+       int     r_number;       /* rpc program number */
+};
+
+#ifndef WIN32
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
+
+#define __NETDB_MAXALIASES     35
+#define __NETDB_MAXADDRS       35
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+#define h_errno                (*__h_errno_location ())
+#else
+extern int h_errno;
+#endif
+#endif
+
+#define        NETDB_INTERNAL -1 /* see errno */
+#define        NETDB_SUCCESS   0 /* no problem */
+
+//#include <features.h>
+
+void           endhostent (void);
+void           endnetent (void);
+void           endprotoent (void);
+void           endservent (void);
+void           endrpcent (void);
+struct hostent *gethostent (void);
+struct netent  *getnetbyaddr (long, int); /* u_long? */
+struct netent  *getnetbyname (const char *);
+struct netent  *getnetent (void);
+struct protoent        *getprotoent (void);
+struct servent *getservent (void);
+struct rpcent  *getrpcent (void);
+struct rpcent  *getrpcbyname (const char *);
+struct rpcent  *getrpcbynumber (int);
+void           herror (const char *);
+void           sethostent (int);
+/* void                sethostfile (const char *); */
+void           setnetent (int);
+void           setprotoent (int);
+void           setservent (int);
+void           setrpcent (int);
+
+#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
+struct hostent *gethostbyaddr_r (const char *__addr,
+                       int __length, int __type,
+                       struct hostent *__result,
+                       char *__buffer, int __buflen, int *__h_errnop);
+struct hostent *gethostbyname_r (const char * __name,
+                       struct hostent *__result, char *__buffer,
+                       int __buflen, int *__h_errnop);
+struct hostent *gethostent_r (struct hostent *__result,
+                       char *__buffer, int __buflen, int *__h_errnop);
+struct netent  *getnetbyaddr_r (long __net, int __type,
+                       struct netent *__result, char *__buffer,
+                       int __buflen);
+struct netent  *getnetbyname_r (const char * __name,
+                       struct netent *__result, char *__buffer,
+                       int __buflen);
+struct netent  *getnetent_r (struct netent *__result,
+                       char *__buffer, int __buflen);
+struct protoent        *getprotobyname_r (const char * __name,
+                       struct protoent *__result, char *__buffer,
+                       int __buflen);
+struct protoent        *getprotobynumber_r (int __proto,
+                       struct protoent *__result, char *__buffer,
+                       int __buflen);
+struct protoent        *getprotoent_r (struct protoent *__result,
+                       char *__buffer, int __buflen);
+struct servent *getservbyname_r (const char * __name,
+                       const char *__proto, struct servent *__result,
+                       char *__buffer, int __buflen);
+struct servent *getservbyport_r (int __port,
+                       const char *__proto, struct servent *__result,
+                       char *__buffer, int __buflen);
+struct servent *getservent_r (struct servent *__result,
+                       char *__buffer, int __buflen);
+
+int *__h_errno_location (void);
+
+#endif
+
+#endif /* !_NETDB_H_ */
diff --git a/Win32/Include/net/paths.h b/Win32/Include/net/paths.h
new file mode 100644 (file)
index 0000000..987de4f
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)paths.h     5.15 (Berkeley) 5/29/91
+ */
+
+#ifndef _PATHS_H_
+#define        _PATHS_H_
+
+#if 0
+#define        __PATH_ETC_INET "/usr/etc/inet"
+#else
+#define        __PATH_ETC_INET "/etc"
+#endif
+
+/* Default search path. */
+#define        _PATH_DEFPATH           "/usr/local/bin:/usr/bin:/bin:."
+#define _PATH_DEFPATH_ROOT     "/sbin:/bin:/usr/sbin:/usr/bin"
+
+#define        _PATH_BSHELL    "/bin/sh"
+#define        _PATH_CONSOLE   "/dev/console"
+#define        _PATH_CSHELL    "/bin/csh"
+#define        _PATH_DEVDB     "/var/run/dev.db"
+#define        _PATH_DEVNULL   "/dev/null"
+#define        _PATH_DRUM      "/dev/drum"
+#define        _PATH_HEQUIV    __PATH_ETC_INET"/hosts.equiv"
+#define        _PATH_KMEM      "/dev/kmem"
+#define        _PATH_MAILDIR   "/var/spool/mail"
+#define        _PATH_MAN       "/usr/man"
+#define        _PATH_MEM       "/dev/mem"
+#define        _PATH_LOGIN     "/bin/login"
+#define        _PATH_NOLOGIN   "/etc/nologin"
+#define        _PATH_SENDMAIL  "/usr/sbin/sendmail"
+#define        _PATH_SHELLS    "/etc/shells"
+#define        _PATH_TTY       "/dev/tty"
+#define        _PATH_UNIX      "/vmlinux"
+#define        _PATH_VI        "/usr/bin/vi"
+
+/* Provide trailing slash, since mostly used for building pathnames. */
+#define        _PATH_DEV       "/dev/"
+#define        _PATH_TMP       "/tmp/"
+#define        _PATH_VARRUN    "/var/run/"
+#define        _PATH_VARTMP    "/var/tmp/"
+
+#define _PATH_KLOG     "/proc/kmsg"
+#define _PATH_LOGCONF  __PATH_ETC_INET"/syslog.conf"
+#if 0
+#define _PATH_LOGPID   __PATH_ETC_INET"/syslog.pid"
+#else
+#define _PATH_LOGPID   "/var/run/syslog.pid"
+#endif
+#define _PATH_LOG      "/dev/log"
+#define _PATH_CONSOLE  "/dev/console"
+
+#if 0
+#define _PATH_UTMP     "/var/adm/utmp"
+#define _PATH_WTMP     "/var/adm/wtmp"
+#define _PATH_LASTLOG  "/var/adm/lastlog"
+#else
+#define _PATH_UTMP     "/var/run/utmp"
+#define _PATH_WTMP     "/var/log/wtmp"
+#define _PATH_LASTLOG  "/var/log/lastlog"
+#endif
+
+#define _PATH_LOCALE   "/usr/lib/locale"
+
+#define _PATH_RWHODIR  "/var/spool/rwho"
+
+#if _MIT_POSIX_THREADS
+/* For the MIT pthreads */
+#define _PATH_PTY      "/dev/"
+#define _PATH_TZDIR    "/usr/lib/zoneinfo"
+#define _PATH_TZFILE   "/usr/lib/zoneinfo/localtime"
+#endif
+
+#endif /* !_PATHS_H_ */
diff --git a/Win32/Include/sockstorage.h b/Win32/Include/sockstorage.h
new file mode 100644 (file)
index 0000000..557eb4d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+struct sockaddr_storage {
+#ifdef HAVE_SOCKADDR_SA_LEN
+       u_int8_t __ss_len;
+       u_int8_t __ss_family;
+       u_int8_t fill[126];
+#else
+       u_int8_t __ss_family;
+       u_int8_t fill[127];
+#endif /* HAVE_SOCKADDR_SA_LEN */
+};
diff --git a/Win32/Prj/libpcap.dsp b/Win32/Prj/libpcap.dsp
new file mode 100644 (file)
index 0000000..17e5a70
--- /dev/null
@@ -0,0 +1,168 @@
+# Microsoft Developer Studio Project File - Name="libpcap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libpcap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libpcap.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libpcap.mak" CFG="libpcap - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libpcap - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libpcap - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libpcap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "NDEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "libpcap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "_DEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libpcap - Win32 Release"
+# Name "libpcap - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\bpf_dump.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\bpf\net\bpf_filter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\bpf_image.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\etherent.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\fad-win32.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\ffs.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\gencode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\getnetbynm.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\getnetent.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\getservent.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\grammar.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\inet.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\inet_aton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\inet_net.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\Src\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\nametoaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\optimize.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\Pcap-win32.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\pcap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\savefile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\scanner.c
+# End Source File
+# End Target
+# End Project
diff --git a/Win32/Prj/libpcap.dsw b/Win32/Prj/libpcap.dsw
new file mode 100644 (file)
index 0000000..8cdff2d
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libpcap"=".\libpcap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Win32/Src/ffs.c b/Win32/Src/ffs.c
new file mode 100644 (file)
index 0000000..099ff8e
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ffs.c      8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+/*
+ * ffs -- vax ffs instruction
+ */
+int
+ffs(mask)
+       register int mask;
+{
+       register int bit;
+
+       if (mask == 0)
+               return(0);
+       for (bit = 1; !(mask & 1); bit++)
+               mask >>= 1;
+       return(bit);
+}
diff --git a/Win32/Src/gai_strerror.c b/Win32/Src/gai_strerror.c
new file mode 100644 (file)
index 0000000..edd970b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+#include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/net/gai_strerror.c,v 1.1 2005/04/06 12:45:51 ume Exp $");
+
+*/
+
+#ifdef WIN32
+
+#include <ws2tcpip.h>
+
+#else
+
+#include <netdb.h>
+
+#endif
+
+/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
+/* for backward compatibility with userland code prior to 2553bis-02 */
+static char *ai_errlist[] = {
+       "Success",                                      /* 0 */
+       "Address family for hostname not supported",    /* 1 */
+       "Temporary failure in name resolution",         /* EAI_AGAIN */
+       "Invalid value for ai_flags",                   /* EAI_BADFLAGS */
+       "Non-recoverable failure in name resolution",   /* EAI_FAIL */
+       "ai_family not supported",                      /* EAI_FAMILY */
+       "Memory allocation failure",                    /* EAI_MEMORY */
+       "No address associated with hostname",          /* 7 */
+       "hostname nor servname provided, or not known", /* EAI_NONAME */
+       "servname not supported for ai_socktype",       /* EAI_SERVICE */
+       "ai_socktype not supported",                    /* EAI_SOCKTYPE */
+       "System error returned in errno",               /* EAI_SYSTEM */
+       "Invalid value for hints",                      /* EAI_BADHINTS */
+       "Resolved protocol is unknown"                  /* EAI_PROTOCOL */
+};
+
+#ifndef EAI_MAX
+#define EAI_MAX (sizeof(ai_errlist)/sizeof(ai_errlist[0]))
+#endif
+
+/* on MingW, gai_strerror is available. 
+   We need to compile gai_strerrorA only for Cygwin
+ */
+#ifndef gai_strerror
+
+char *
+WSAAPI gai_strerrorA(int ecode)
+{
+       if (ecode >= 0 && ecode < EAI_MAX)
+               return ai_errlist[ecode];
+       return "Unknown error";
+}
+
+#endif /* gai_strerror */
\ No newline at end of file
diff --git a/Win32/Src/getaddrinfo.c b/Win32/Src/getaddrinfo.c
new file mode 100644 (file)
index 0000000..ebfe8c2
--- /dev/null
@@ -0,0 +1,1129 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked.
+ * - Return values.  There are nonstandard return values defined and used
+ *   in the source code.  This is because RFC2553 is silent about which error
+ *   code must be returned for which situation.
+ * Note:
+ * - We use getipnodebyname() just for thread-safeness.  There's no intent
+ *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
+ *   getipnodebyname().
+ * - The code filters out AFs that are not supported by the kernel,
+ *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
+ *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
+ *   in ai_flags?
+ */
+
+/*
+ * Mingw64 has its own implementation of getaddrinfo, mingw32 no
+ */
+#ifndef __MINGW64__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif 
+
+#ifndef lint
+static const char rcsid[] _U_ =
+     "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/getaddrinfo.c,v 1.3 2008-09-15 23:37:51 guy Exp $";
+#endif
+
+#include <pcap-stdinc.h>
+#if 0
+#include <sys/sysctl.h>
+#endif
+#ifndef __MINGW32__
+#include <arpa/nameser.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef HAVE_PORTABLE_PROTOTYPE
+#include "cdecl_ext.h"
+#endif 
+
+#ifndef HAVE_U_INT32_T
+#include "bittypes.h"
+#endif 
+
+#ifndef HAVE_SOCKADDR_STORAGE
+#ifndef __MINGW32__
+#include "sockstorage.h"
+#endif
+#endif 
+
+#ifdef NEED_ADDRINFO_H
+#include "addrinfo.h"
+#ifdef WIN32
+#include "ip6_misc.h"
+#endif
+#endif
+
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO  0
+
+#ifdef FAITH
+static int translate = NO;
+static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
+#endif
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 }; 
+static const char in6_loopback[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+struct sockinet {
+       u_char  si_len;
+       u_char  si_family;
+       u_short si_port;
+       u_int32_t si_scope_id;
+};
+
+static const struct afd {
+       int a_af;
+       int a_addrlen;
+       int a_socklen;
+       int a_off;
+       const char *a_addrany;
+       const char *a_loopback; 
+       int a_scoped;
+} afdl [] = {
+#ifdef INET6
+       {PF_INET6, sizeof(struct in6_addr),
+        sizeof(struct sockaddr_in6),
+        offsetof(struct sockaddr_in6, sin6_addr),
+        in6_addrany, in6_loopback, 1},
+#endif
+       {PF_INET, sizeof(struct in_addr),
+        sizeof(struct sockaddr_in),
+        offsetof(struct sockaddr_in, sin_addr),
+        in_addrany, in_loopback, 0},
+       {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+       int e_af;
+       int e_socktype;
+       int e_protocol;
+       const char *e_protostr;
+       int e_wild;
+#define WILD_AF(ex)            ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex)      ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex)      ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#if 0
+       { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+#endif
+#ifdef INET6
+       { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+       { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+       { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+#endif
+       { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+       { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+       { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+       { -1, 0, 0, NULL, 0 },
+};
+
+#ifdef INET6
+#define PTON_MAX       16
+#else
+#define PTON_MAX       4
+#endif
+
+
+static int str_isnumber __P((const char *));
+static int explore_fqdn __P((const struct addrinfo *, const char *,
+       const char *, struct addrinfo **));
+static int explore_null __P((const struct addrinfo *, const char *,
+       const char *, struct addrinfo **));
+static int explore_numeric __P((const struct addrinfo *, const char *,
+       const char *, struct addrinfo **));
+static int explore_numeric_scope __P((const struct addrinfo *, const char *,
+       const char *, struct addrinfo **));
+static int get_name __P((const char *, const struct afd *, struct addrinfo **,
+       char *, const struct addrinfo *, const char *));
+static int get_canonname __P((const struct addrinfo *,
+       struct addrinfo *, const char *));
+static struct addrinfo *get_ai __P((const struct addrinfo *,
+       const struct afd *, const char *));
+static int get_portmatch __P((const struct addrinfo *, const char *));
+static int get_port __P((struct addrinfo *, const char *, int));
+static const struct afd *find_afd __P((int));
+
+static char *ai_errlist[] = {
+       "Success",
+       "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
+       "Temporary failure in name resolution",         /* EAI_AGAIN      */
+       "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
+       "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
+       "ai_family not supported",                      /* EAI_FAMILY     */
+       "Memory allocation failure",                    /* EAI_MEMORY     */
+       "No address associated with hostname",          /* EAI_NODATA     */
+       "hostname nor servname provided, or not known", /* EAI_NONAME     */
+       "servname not supported for ai_socktype",       /* EAI_SERVICE    */
+       "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
+       "System error returned in errno",               /* EAI_SYSTEM     */
+       "Invalid value for hints",                      /* EAI_BADHINTS   */
+       "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
+       "Unknown error",                                /* EAI_MAX        */
+};
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+       /* external reference: pai, error, and label free */ \
+       (ai) = get_ai(pai, (afd), (addr)); \
+       if ((ai) == NULL) { \
+               error = EAI_MEMORY; \
+               goto free; \
+       } \
+} while (0)
+
+#define GET_PORT(ai, serv) \
+do { \
+       /* external reference: error and label free */ \
+       error = get_port((ai), (serv), 0); \
+       if (error != 0) \
+               goto free; \
+} while (0)
+
+#define GET_CANONNAME(ai, str) \
+do { \
+       /* external reference: pai, error and label free */ \
+       error = get_canonname(pai, (ai), (str)); \
+       if (error != 0) \
+               goto free; \
+} while (0)
+
+#define ERR(err) \
+do { \
+       /* external reference: error, and label bad */ \
+       error = (err); \
+       goto bad; \
+} while (0)
+
+#define MATCH_FAMILY(x, y, w) \
+       ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) \
+       ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
+
+#if  defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+char *
+gai_strerror(ecode)
+       int ecode;
+{
+       if (ecode < 0 || ecode > EAI_MAX)
+               ecode = EAI_MAX;
+       return ai_errlist[ecode];
+}
+#endif
+
+void
+freeaddrinfo(ai)
+       struct addrinfo *ai;
+{
+       struct addrinfo *next;
+
+       do {
+               next = ai->ai_next;
+               if (ai->ai_canonname)
+                       free(ai->ai_canonname);
+               /* no need to free(ai->ai_addr) */
+               free(ai);
+       } while ((ai = next) != NULL);
+}
+
+static int
+str_isnumber(p)
+       const char *p;
+{
+       char *q = (char *)p;
+       while (*q) {
+               if (! isdigit(*q))
+                       return NO;
+               q++;
+       }
+       return YES;
+}
+
+int
+getaddrinfo(hostname, servname, hints, res)
+       const char *hostname, *servname;
+       const struct addrinfo *hints;
+       struct addrinfo **res;
+{
+       struct addrinfo sentinel;
+       struct addrinfo *cur;
+       int error = 0;
+       struct addrinfo ai;
+       struct addrinfo ai0;
+       struct addrinfo *pai;
+       const struct afd *afd;
+       const struct explore *ex;
+
+#ifdef FAITH
+       static int firsttime = 1;
+
+       if (firsttime) {
+               /* translator hack */
+               char *q = getenv("GAI");
+               if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
+                       translate = YES;
+               firsttime = 0;
+       }
+#endif
+
+       sentinel.ai_next = NULL;
+       cur = &sentinel;
+       pai = &ai;
+       pai->ai_flags = 0;
+       pai->ai_family = PF_UNSPEC;
+       pai->ai_socktype = ANY;
+       pai->ai_protocol = ANY;
+       pai->ai_addrlen = 0;
+       pai->ai_canonname = NULL;
+       pai->ai_addr = NULL;
+       pai->ai_next = NULL;
+       
+       if (hostname == NULL && servname == NULL)
+               return EAI_NONAME;
+       if (hints) {
+               /* error check for hints */
+               if (hints->ai_addrlen || hints->ai_canonname ||
+                   hints->ai_addr || hints->ai_next)
+                       ERR(EAI_BADHINTS); /* xxx */
+               if (hints->ai_flags & ~AI_MASK)
+                       ERR(EAI_BADFLAGS);
+               switch (hints->ai_family) {
+               case PF_UNSPEC:
+               case PF_INET:
+#ifdef INET6
+               case PF_INET6:
+#endif
+                       break;
+               default:
+                       ERR(EAI_FAMILY);
+               }
+               memcpy(pai, hints, sizeof(*pai));
+
+               /*
+                * if both socktype/protocol are specified, check if they
+                * are meaningful combination.
+                */
+               if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+                       for (ex = explore; ex->e_af >= 0; ex++) {
+                               if (pai->ai_family != ex->e_af)
+                                       continue;
+                               if (ex->e_socktype == ANY)
+                                       continue;
+                               if (ex->e_protocol == ANY)
+                                       continue;
+                               if (pai->ai_socktype == ex->e_socktype
+                                && pai->ai_protocol != ex->e_protocol) {
+                                       ERR(EAI_BADHINTS);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * check for special cases.  (1) numeric servname is disallowed if
+        * socktype/protocol are left unspecified. (2) servname is disallowed
+        * for raw and other inet{,6} sockets.
+        */
+       if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef PF_INET6
+        || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+           ) {
+               ai0 = *pai;
+
+               if (pai->ai_family == PF_UNSPEC) {
+#ifdef PF_INET6
+                       pai->ai_family = PF_INET6;
+#else
+                       pai->ai_family = PF_INET;
+#endif
+               }
+               error = get_portmatch(pai, servname);
+               if (error)
+                       ERR(error);
+
+               *pai = ai0;
+       }
+
+       ai0 = *pai;
+
+       /* NULL hostname, or numeric hostname */
+       for (ex = explore; ex->e_af >= 0; ex++) {
+               *pai = ai0;
+
+               if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+                       continue;
+               if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+                       continue;
+               if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+                       continue;
+
+               if (pai->ai_family == PF_UNSPEC)
+                       pai->ai_family = ex->e_af;
+               if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+                       pai->ai_socktype = ex->e_socktype;
+               if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+                       pai->ai_protocol = ex->e_protocol;
+
+               if (hostname == NULL)
+                       error = explore_null(pai, hostname, servname, &cur->ai_next);
+               else
+                       error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
+
+               if (error)
+                       goto free;
+
+               while (cur && cur->ai_next)
+                       cur = cur->ai_next;
+       }
+
+       /*
+        * XXX
+        * If numreic representation of AF1 can be interpreted as FQDN
+        * representation of AF2, we need to think again about the code below.
+        */
+       if (sentinel.ai_next)
+               goto good;
+
+       if (pai->ai_flags & AI_NUMERICHOST)
+               ERR(EAI_NONAME);
+       if (hostname == NULL)
+               ERR(EAI_NONAME);
+
+       /*
+        * hostname as alphabetical name.
+        * we would like to prefer AF_INET6 than AF_INET, so we'll make a
+        * outer loop by AFs.
+        */
+       for (afd = afdl; afd->a_af; afd++) {
+               *pai = ai0;
+
+               if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
+                       continue;
+
+               for (ex = explore; ex->e_af >= 0; ex++) {
+                       *pai = ai0;
+
+                       if (pai->ai_family == PF_UNSPEC)
+                               pai->ai_family = afd->a_af;
+
+                       if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+                               continue;
+                       if (!MATCH(pai->ai_socktype, ex->e_socktype,
+                                       WILD_SOCKTYPE(ex))) {
+                               continue;
+                       }
+                       if (!MATCH(pai->ai_protocol, ex->e_protocol,
+                                       WILD_PROTOCOL(ex))) {
+                               continue;
+                       }
+
+                       if (pai->ai_family == PF_UNSPEC)
+                               pai->ai_family = ex->e_af;
+                       if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+                               pai->ai_socktype = ex->e_socktype;
+                       if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+                               pai->ai_protocol = ex->e_protocol;
+
+                       error = explore_fqdn(pai, hostname, servname,
+                               &cur->ai_next);
+
+                       while (cur && cur->ai_next)
+                               cur = cur->ai_next;
+               }
+       }
+
+       /* XXX */
+       if (sentinel.ai_next)
+               error = 0;
+
+       if (error)
+               goto free;
+       if (error == 0) {
+               if (sentinel.ai_next) {
+ good:
+                       *res = sentinel.ai_next;
+                       return SUCCESS;
+               } else
+                       error = EAI_FAIL;
+       }
+ free:
+ bad:
+       if (sentinel.ai_next)
+               freeaddrinfo(sentinel.ai_next);
+       *res = NULL;
+       return error;
+}
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(pai, hostname, servname, res)
+       const struct addrinfo *pai;
+       const char *hostname;
+       const char *servname;
+       struct addrinfo **res;
+{
+       struct hostent *hp;
+       int h_error;
+       int af;
+       char **aplist = NULL, *apbuf = NULL;
+       char *ap;
+       struct addrinfo sentinel, *cur;
+       int i;
+#ifndef USE_GETIPNODEBY
+       int naddrs;
+#endif
+       const struct afd *afd;
+       int error;
+
+       *res = NULL;
+       sentinel.ai_next = NULL;
+       cur = &sentinel;
+
+       /*
+        * Do not filter unsupported AFs here.  We need to honor content of
+        * databases (/etc/hosts, DNS and others).  Otherwise we cannot
+        * replace gethostbyname() by getaddrinfo().
+        */
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+
+       /*
+        * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
+        * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
+        * handling code by ourselves in case we don't have getipnodebyname().
+        */
+#ifdef USE_GETIPNODEBY
+       hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
+#else
+#ifdef HAVE_GETHOSTBYNAME2
+       hp = gethostbyname2(hostname, pai->ai_family);
+#else
+       if (pai->ai_family != AF_INET)
+               return 0;
+       hp = gethostbyname(hostname);
+#ifdef HAVE_H_ERRNO
+       h_error = h_errno;
+#else
+       h_error = EINVAL;
+#endif
+#endif /*HAVE_GETHOSTBYNAME2*/
+#endif /*USE_GETIPNODEBY*/
+
+       if (hp == NULL) {
+               switch (h_error) {
+               case HOST_NOT_FOUND:
+               case NO_DATA:
+                       error = EAI_NODATA;
+                       break;
+               case TRY_AGAIN:
+                       error = EAI_AGAIN;
+                       break;
+               case NO_RECOVERY:
+               case NETDB_INTERNAL:
+               default:
+                       error = EAI_FAIL;
+                       break;
+               }
+       } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
+                       || (hp->h_addr_list[0] == NULL)) {
+#ifdef USE_GETIPNODEBY
+               freehostent(hp);
+#endif
+               hp = NULL;
+               error = EAI_FAIL;
+       }
+
+       if (hp == NULL)
+               goto free;
+
+#ifdef USE_GETIPNODEBY
+       aplist = hp->h_addr_list;
+#else
+       /*
+        * hp will be overwritten if we use gethostbyname2().
+        * always deep copy for simplification.
+        */
+       for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
+               ;
+       naddrs++;
+       aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
+       apbuf = (char *)malloc(hp->h_length * naddrs);
+       if (aplist == NULL || apbuf == NULL) {
+               error = EAI_MEMORY;
+               goto free;
+       }
+       memset(aplist, 0, sizeof(aplist[0]) * naddrs);
+       for (i = 0; i < naddrs; i++) {
+               if (hp->h_addr_list[i] == NULL) {
+                       aplist[i] = NULL;
+                       continue;
+               }
+               memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
+                       hp->h_length);
+               aplist[i] = &apbuf[i * hp->h_length];
+       }
+#endif
+
+       for (i = 0; aplist[i] != NULL; i++) {
+               af = hp->h_addrtype;
+               ap = aplist[i];
+#ifdef AF_INET6
+               if (af == AF_INET6
+                && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+                       af = AF_INET;
+                       ap = ap + sizeof(struct in6_addr)
+                               - sizeof(struct in_addr);
+               }
+#endif
+
+               if (af != pai->ai_family)
+                       continue;
+
+               if ((pai->ai_flags & AI_CANONNAME) == 0) {
+                       GET_AI(cur->ai_next, afd, ap);
+                       GET_PORT(cur->ai_next, servname);
+               } else {
+                       /*
+                        * if AI_CANONNAME and if reverse lookup
+                        * fail, return ai anyway to pacify
+                        * calling application.
+                        *
+                        * XXX getaddrinfo() is a name->address
+                        * translation function, and it looks
+                        * strange that we do addr->name
+                        * translation here.
+                        */
+                       get_name(ap, afd, &cur->ai_next,
+                               ap, pai, servname);
+               }
+
+               while (cur && cur->ai_next)
+                       cur = cur->ai_next;
+       }
+
+       *res = sentinel.ai_next;
+       return 0;
+
+free:
+#ifdef USE_GETIPNODEBY
+       if (hp)
+               freehostent(hp);
+#endif
+       if (aplist)
+               free(aplist);
+       if (apbuf)
+               free(apbuf);
+       if (sentinel.ai_next)
+               freeaddrinfo(sentinel.ai_next);
+       return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(pai, hostname, servname, res)
+       const struct addrinfo *pai;
+       const char *hostname;
+       const char *servname;
+       struct addrinfo **res;
+{
+       int s;
+       const struct afd *afd;
+       struct addrinfo *cur;
+       struct addrinfo sentinel;
+       int error;
+
+       *res = NULL;
+       sentinel.ai_next = NULL;
+       cur = &sentinel;
+
+       /*
+        * filter out AFs that are not supported by the kernel
+        * XXX errno?
+        */
+       s = socket(pai->ai_family, SOCK_DGRAM, 0);
+       if (s < 0) {
+               if (errno != EMFILE)
+                       return 0;
+       } else
+               close(s);
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+
+       if (pai->ai_flags & AI_PASSIVE) {
+               GET_AI(cur->ai_next, afd, afd->a_addrany);
+               /* xxx meaningless?
+                * GET_CANONNAME(cur->ai_next, "anyaddr");
+                */
+               GET_PORT(cur->ai_next, servname);
+       } else {
+               GET_AI(cur->ai_next, afd, afd->a_loopback);
+               /* xxx meaningless?
+                * GET_CANONNAME(cur->ai_next, "localhost");
+                */
+               GET_PORT(cur->ai_next, servname);
+       }
+       cur = cur->ai_next;
+
+       *res = sentinel.ai_next;
+       return 0;
+
+free:
+       if (sentinel.ai_next)
+               freeaddrinfo(sentinel.ai_next);
+       return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(pai, hostname, servname, res)
+       const struct addrinfo *pai;
+       const char *hostname;
+       const char *servname;
+       struct addrinfo **res;
+{
+       const struct afd *afd;
+       struct addrinfo *cur;
+       struct addrinfo sentinel;
+       int error;
+       char pton[PTON_MAX];
+       int flags;
+
+       *res = NULL;
+       sentinel.ai_next = NULL;
+       cur = &sentinel;
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+       flags = pai->ai_flags;
+
+       if (inet_pton(afd->a_af, hostname, pton) == 1) {
+               u_int32_t v4a;
+#ifdef INET6
+               u_char pfx;
+#endif
+
+               switch (afd->a_af) {
+               case AF_INET:
+                       v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
+                       if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+                               flags &= ~AI_CANONNAME;
+                       v4a >>= IN_CLASSA_NSHIFT;
+                       if (v4a == 0 || v4a == IN_LOOPBACKNET)
+                               flags &= ~AI_CANONNAME;
+                       break;
+#ifdef INET6
+               case AF_INET6:
+                       pfx = ((struct in6_addr *)pton)->s6_addr[0];
+                       if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+                               flags &= ~AI_CANONNAME;
+                       break;
+#endif
+               }
+
+               if (pai->ai_family == afd->a_af ||
+                   pai->ai_family == PF_UNSPEC /*?*/) {
+                       if ((flags & AI_CANONNAME) == 0) {
+                               GET_AI(cur->ai_next, afd, pton);
+                               GET_PORT(cur->ai_next, servname);
+                       } else {
+                               /*
+                                * if AI_CANONNAME and if reverse lookup
+                                * fail, return ai anyway to pacify
+                                * calling application.
+                                *
+                                * XXX getaddrinfo() is a name->address
+                                * translation function, and it looks
+                                * strange that we do addr->name
+                                * translation here.
+                                */
+                               get_name(pton, afd, &cur->ai_next,
+                                       pton, pai, servname);
+                       }
+                       while (cur && cur->ai_next)
+                               cur = cur->ai_next;
+               } else 
+                       ERR(EAI_FAMILY);        /*xxx*/
+       }
+
+       *res = sentinel.ai_next;
+       return 0;
+
+free:
+bad:
+       if (sentinel.ai_next)
+               freeaddrinfo(sentinel.ai_next);
+       return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(pai, hostname, servname, res)
+       const struct addrinfo *pai;
+       const char *hostname;
+       const char *servname;
+       struct addrinfo **res;
+{
+#ifndef SCOPE_DELIMITER
+       return explore_numeric(pai, hostname, servname, res);
+#else
+       const struct afd *afd;
+       struct addrinfo *cur;
+       int error;
+       char *cp, *hostname2 = NULL;
+       int scope;
+       struct sockaddr_in6 *sin6;
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+       if (!afd->a_scoped)
+               return explore_numeric(pai, hostname, servname, res);
+
+       cp = strchr(hostname, SCOPE_DELIMITER);
+       if (cp == NULL)
+               return explore_numeric(pai, hostname, servname, res);
+
+       /*
+        * Handle special case of <scoped_address><delimiter><scope id>
+        */
+       hostname2 = strdup(hostname);
+       if (hostname2 == NULL)
+               return EAI_MEMORY;
+       /* terminate at the delimiter */
+       hostname2[cp - hostname] = '\0';
+
+       cp++;
+       switch (pai->ai_family) {
+#ifdef INET6
+       case AF_INET6:
+               scope = if_nametoindex(cp);
+               if (scope == 0) {
+                       free(hostname2);
+                       return (EAI_NONAME);
+               }
+               break;
+#endif
+       }
+
+       error = explore_numeric(pai, hostname2, servname, res);
+       if (error == 0) {
+               for (cur = *res; cur; cur = cur->ai_next) {
+                       if (cur->ai_family != AF_INET6)
+                               continue;
+                       sin6 = (struct sockaddr_in6 *)cur->ai_addr;
+                       if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+                           IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
+                               sin6->sin6_scope_id = scope;
+               }
+       }
+
+       free(hostname2);
+
+       return error;
+#endif
+}
+
+static int
+get_name(addr, afd, res, numaddr, pai, servname)
+       const char *addr;
+       const struct afd *afd;
+       struct addrinfo **res;
+       char *numaddr;
+       const struct addrinfo *pai;
+       const char *servname;
+{
+       struct hostent *hp = NULL;
+       struct addrinfo *cur = NULL;
+       int error = 0;
+       char *ap = NULL, *cn = NULL;
+#ifdef USE_GETIPNODEBY
+       int h_error;
+
+       hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+       hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#endif
+       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+#ifdef USE_GETIPNODEBY
+               GET_AI(cur, afd, hp->h_addr_list[0]);
+               GET_PORT(cur, servname);
+               GET_CANONNAME(cur, hp->h_name);
+#else
+               /* hp will be damaged if we use gethostbyaddr() */
+               if ((ap = (char *)malloc(hp->h_length)) == NULL) {
+                       error = EAI_MEMORY;
+                       goto free;
+               }
+               memcpy(ap, hp->h_addr_list[0], hp->h_length);
+               if ((cn = strdup(hp->h_name)) == NULL) {
+                       error = EAI_MEMORY;
+                       goto free;
+               }
+
+               GET_AI(cur, afd, ap);
+               GET_PORT(cur, servname);
+               GET_CANONNAME(cur, cn);
+               free(ap); ap = NULL;
+               free(cn); cn = NULL;
+#endif
+       } else {
+               GET_AI(cur, afd, numaddr);
+               GET_PORT(cur, servname);
+       }
+       
+#ifdef USE_GETIPNODEBY
+       if (hp)
+               freehostent(hp);
+#endif
+       *res = cur;
+       return SUCCESS;
+ free:
+       if (cur)
+               freeaddrinfo(cur);
+       if (ap)
+               free(ap);
+       if (cn)
+               free(cn);
+#ifdef USE_GETIPNODEBY
+       if (hp)
+               freehostent(hp);
+#endif
+       *res = NULL;
+       return error;
+}
+
+static int
+get_canonname(pai, ai, str)
+       const struct addrinfo *pai;
+       struct addrinfo *ai;
+       const char *str;
+{
+       if ((pai->ai_flags & AI_CANONNAME) != 0) {
+               ai->ai_canonname = strdup(str);
+               if (ai->ai_canonname == NULL)
+                       return EAI_MEMORY;
+       }
+       return 0;
+}
+
+static struct addrinfo *
+get_ai(pai, afd, addr)
+       const struct addrinfo *pai;
+       const struct afd *afd;
+       const char *addr;
+{
+       char *p;
+       struct addrinfo *ai;
+
+       ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+               + (afd->a_socklen));
+       if (ai == NULL)
+               return NULL;
+
+       memcpy(ai, pai, sizeof(struct addrinfo));
+       ai->ai_addr = (struct sockaddr *)(ai + 1);
+       memset(ai->ai_addr, 0, afd->a_socklen);
+#ifdef HAVE_SOCKADDR_SA_LEN
+       ai->ai_addr->sa_len = afd->a_socklen;
+#endif
+       ai->ai_addrlen = afd->a_socklen;
+       ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+       p = (char *)(ai->ai_addr);
+       memcpy(p + afd->a_off, addr, afd->a_addrlen);
+       return ai;
+}
+
+static int
+get_portmatch(ai, servname)
+       const struct addrinfo *ai;
+       const char *servname;
+{
+
+       /* get_port does not touch first argument. when matchonly == 1. */
+       return get_port((struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(ai, servname, matchonly)
+       struct addrinfo *ai;
+       const char *servname;
+       int matchonly;
+{
+       const char *proto;
+       struct servent *sp;
+       int port;
+       int allownumeric;
+
+       if (servname == NULL)
+               return 0;
+       switch (ai->ai_family) {
+       case AF_INET:
+#ifdef AF_INET6
+       case AF_INET6:
+#endif
+               break;
+       default:
+               return 0;
+       }
+
+       switch (ai->ai_socktype) {
+       case SOCK_RAW:
+               return EAI_SERVICE;
+       case SOCK_DGRAM:
+       case SOCK_STREAM:
+               allownumeric = 1;
+               break;
+       case ANY:
+               allownumeric = 0;
+               break;
+       default:
+               return EAI_SOCKTYPE;
+       }
+
+       if (str_isnumber(servname)) {
+               if (!allownumeric)
+                       return EAI_SERVICE;
+               port = htons(atoi(servname));
+               if (port < 0 || port > 65535)
+                       return EAI_SERVICE;
+       } else {
+               switch (ai->ai_socktype) {
+               case SOCK_DGRAM:
+                       proto = "udp";
+                       break;
+               case SOCK_STREAM:
+                       proto = "tcp";
+                       break;
+               default:
+                       proto = NULL;
+                       break;
+               }
+
+               if ((sp = getservbyname(servname, proto)) == NULL)
+                       return EAI_SERVICE;
+               port = sp->s_port;
+       }
+
+       if (!matchonly) {
+               switch (ai->ai_family) {
+               case AF_INET:
+                       ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
+                       break;
+#ifdef INET6
+               case AF_INET6:
+                       ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
+                       break;
+#endif
+               }
+       }
+
+       return 0;
+}
+
+static const struct afd *
+find_afd(af)
+       int af;
+{
+       const struct afd *afd;
+
+       if (af == PF_UNSPEC)
+               return NULL;
+       for (afd = afdl; afd->a_af; afd++) {
+               if (afd->a_af == af)
+                       return afd;
+       }
+       return NULL;
+}
+
+
+#endif /*__MING64__*/
diff --git a/Win32/Src/getnetbynm.c b/Win32/Src/getnetbynm.c
new file mode 100644 (file)
index 0000000..fa4d398
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetbyname.c     5.5 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include "inetprivate.h"
+
+extern int _net_stayopen;
+
+struct netent *
+getnetbyname(const char *name)
+{
+       register struct netent *p;
+       register char **cp;
+
+       setnetent(_net_stayopen);
+       while (p = getnetent()) {
+               if (strcmp(p->n_name, name) == 0)
+                       break;
+               for (cp = p->n_aliases; *cp != 0; cp++)
+                       if (strcmp(*cp, name) == 0)
+                               goto found;
+       }
+found:
+       if (!_net_stayopen)
+               endnetent();
+       return (p);
+}
diff --git a/Win32/Src/getnetent.c b/Win32/Src/getnetent.c
new file mode 100644 (file)
index 0000000..d4cceb3
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c        5.5 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include "inetprivate.h"
+
+#define        MAXALIASES      35
+
+static char NETDB[] = _PATH_NETWORKS;
+static FILE *netf = NULL;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+static char *any(char *, char *);
+
+int _net_stayopen;
+extern u_int32_t inet_network(const char *cp);
+
+void
+setnetent(f)
+       int f;
+{
+       if (netf == NULL)
+               netf = fopen(NETDB, "r" );
+       else
+               rewind(netf);
+       _net_stayopen |= f;
+}
+
+void
+endnetent()
+{
+       if (netf) {
+               fclose(netf);
+               netf = NULL;
+       }
+       _net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+       char *p;
+       register char *cp, **q;
+
+       if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL)
+               return (NULL);
+again:
+       p = fgets(line, BUFSIZ, netf);
+       if (p == NULL)
+               return (NULL);
+       if (*p == '#')
+               goto again;
+       cp = any(p, "#\n");
+       if (cp == NULL)
+               goto again;
+       *cp = '\0';
+       net.n_name = p;
+       cp = any(p, " \t");
+       if (cp == NULL)
+               goto again;
+       *cp++ = '\0';
+       while (*cp == ' ' || *cp == '\t')
+               cp++;
+       p = any(cp, " \t");
+       if (p != NULL)
+               *p++ = '\0';
+       net.n_net = inet_network(cp);
+       net.n_addrtype = AF_INET;
+       q = net.n_aliases = net_aliases;
+       if (p != NULL) 
+               cp = p;
+       while (cp && *cp) {
+               if (*cp == ' ' || *cp == '\t') {
+                       cp++;
+                       continue;
+               }
+               if (q < &net_aliases[MAXALIASES - 1])
+                       *q++ = cp;
+               cp = any(cp, " \t");
+               if (cp != NULL)
+                       *cp++ = '\0';
+       }
+       *q = NULL;
+       return (&net);
+}
+
+static char *
+any(cp, match)
+       register char *cp;
+       char *match;
+{
+       register char *mp, c;
+
+       while (c = *cp) {
+               for (mp = match; *mp; mp++)
+                       if (*mp == c)
+                               return (cp);
+               cp++;
+       }
+       return ((char *)0);
+}
diff --git a/Win32/Src/getopt.c b/Win32/Src/getopt.c
new file mode 100644 (file)
index 0000000..03c2086
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c   8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int    opterr = 1,             /* if error message should be printed */
+       optind = 1,             /* index into parent argv vector */
+       optopt,                 /* character checked for validity */
+       optreset;               /* reset getopt */
+char   *optarg;                /* argument associated with option */
+
+#define        BADCH   (int)'?'
+#define        BADARG  (int)':'
+#define        EMSG    ""
+
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+       int nargc;
+       char * const *nargv;
+       const char *ostr;
+{
+#ifdef WIN32
+       char *__progname="windump";
+#else
+       extern char *__progname;
+#endif
+       static char *place = EMSG;              /* option letter processing */
+       char *oli;                              /* option letter list index */
+
+       if (optreset || !*place) {              /* update scanning pointer */
+               optreset = 0;
+               if (optind >= nargc || *(place = nargv[optind]) != '-') {
+                       place = EMSG;
+                       return (-1);
+               }
+               if (place[1] && *++place == '-') {      /* found "--" */
+                       ++optind;
+                       place = EMSG;
+                       return (-1);
+               }
+       }                                       /* option letter okay? */
+       if ((optopt = (int)*place++) == (int)':' ||
+           !(oli = strchr(ostr, optopt))) {
+               /*
+                * if the user didn't specify '-' as an option,
+                * assume it means -1.
+                */
+               if (optopt == (int)'-')
+                       return (-1);
+               if (!*place)
+                       ++optind;
+               if (opterr && *ostr != ':')
+                       (void)fprintf(stderr,
+                           "%s: illegal option -- %c\n", __progname, optopt);
+               return (BADCH);
+       }
+       if (*++oli != ':') {                    /* don't need argument */
+               optarg = NULL;
+               if (!*place)
+                       ++optind;
+       }
+       else {                                  /* need an argument */
+               if (*place)                     /* no white space */
+                       optarg = place;
+               else if (nargc <= ++optind) {   /* no arg */
+                       place = EMSG;
+                       if (*ostr == ':')
+                               return (BADARG);
+                       if (opterr)
+                               (void)fprintf(stderr,
+                                   "%s: option requires an argument -- %c\n",
+                                   __progname, optopt);
+                       return (BADCH);
+               }
+               else                            /* white space */
+                       optarg = nargv[optind];
+               place = EMSG;
+               ++optind;
+       }
+       return (optopt);                        /* dump back option letter */
+}
diff --git a/Win32/Src/getservent.c b/Win32/Src/getservent.c
new file mode 100644 (file)
index 0000000..61b8cb0
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c       8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <net/netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <arpa/nameser.h>
+
+#define        MAXALIASES      35
+
+static char SERVDB[] = _PATH_SERVICES;
+static FILE *servf = NULL;
+static char line[BUFSIZ+1];
+static struct servent serv;
+static char *serv_aliases[MAXALIASES];
+int _serv_stayopen;
+
+void
+setservent(f)
+       int f;
+{
+       if (servf == NULL)
+               servf = fopen(SERVDB, "r" );
+       else
+               rewind(servf);
+       _serv_stayopen |= f;
+}
+
+void
+endservent()
+{
+       if (servf) {
+               fclose(servf);
+               servf = NULL;
+       }
+       _serv_stayopen = 0;
+}
+
+struct servent *
+getservent()
+{
+       char *p;
+       register char *cp, **q;
+
+       if (servf == NULL && (servf = fopen(SERVDB, "r" )) == NULL)
+               return (NULL);
+again:
+       if ((p = fgets(line, BUFSIZ, servf)) == NULL)
+               return (NULL);
+       if (*p == '#')
+               goto again;
+       cp = strpbrk(p, "#\n");
+       if (cp == NULL)
+               goto again;
+       *cp = '\0';
+       serv.s_name = p;
+       p = strpbrk(p, " \t");
+       if (p == NULL)
+               goto again;
+       *p++ = '\0';
+       while (*p == ' ' || *p == '\t')
+               p++;
+       cp = strpbrk(p, ",/");
+       if (cp == NULL)
+               goto again;
+       *cp++ = '\0';
+       serv.s_port = htons((u_short)atoi(p));
+       serv.s_proto = cp;
+       q = serv.s_aliases = serv_aliases;
+       cp = strpbrk(cp, " \t");
+       if (cp != NULL)
+               *cp++ = '\0';
+       while (cp && *cp) {
+               if (*cp == ' ' || *cp == '\t') {
+                       cp++;
+                       continue;
+               }
+               if (q < &serv_aliases[MAXALIASES - 1])
+                       *q++ = cp;
+               cp = strpbrk(cp, " \t");
+               if (cp != NULL)
+                       *cp++ = '\0';
+       }
+       *q = NULL;
+       return (&serv);
+}
diff --git a/Win32/Src/inet_aton.c b/Win32/Src/inet_aton.c
new file mode 100644 (file)
index 0000000..3da6667
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the Kungliga Tekniska
+ *      Högskolan and its contributors.
+ * 
+ * 4. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: inet_aton.c,v 1.2 2003-11-15 23:24:06 guy Exp $ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+     "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/inet_aton.c,v 1.2 2003-11-15 23:24:06 guy Exp $";
+#endif
+
+#include <sys/types.h>
+#include <pcap-stdinc.h>
+
+/* Minimal implementation of inet_aton.
+ * Cannot distinguish between failure and a local broadcast address. */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+  addr->s_addr = inet_addr(cp);
+  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
diff --git a/Win32/Src/inet_net.c b/Win32/Src/inet_net.c
new file mode 100644 (file)
index 0000000..5bbe391
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_network.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include "inetprivate.h"
+
+/*
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+u_int32_t
+inet_network(const char *cp)
+{
+       register u_long val, base, n;
+       register char c;
+       u_long parts[4], *pp = parts;
+       register int i;
+
+again:
+       /*
+        * Collect number up to ``.''.
+        * Values are specified as for C:
+        * 0x=hex, 0=octal, other=decimal.
+        */
+       val = 0; base = 10;
+       /*
+        * The 4.4BSD version of this file also accepts 'x__' as a hexa
+        * number.  I don't think this is correct.  -- Uli
+        */
+       if (*cp == '0') {
+               if (*++cp == 'x' || *cp == 'X')
+                       base = 16, cp++;
+               else
+                       base = 8;
+       }
+       while ((c = *cp)) {
+               if (isdigit(c)) {
+                       val = (val * base) + (c - '0');
+                       cp++;
+                       continue;
+               }
+               if (base == 16 && isxdigit(c)) {
+                       val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+                       cp++;
+                       continue;
+               }
+               break;
+       }
+       if (*cp == '.') {
+               if (pp >= parts + 4)
+                       return (INADDR_NONE);
+               *pp++ = val, cp++;
+               goto again;
+       }
+       if (*cp && !isspace(*cp))
+               return (INADDR_NONE);
+       *pp++ = val;
+       n = pp - parts;
+       if (n > 4)
+               return (INADDR_NONE);
+       for (val = 0, i = 0; i < (int)n; i++) {
+               val <<= 8;
+               val |= parts[i] & 0xff;
+       }
+       return (val);
+}
diff --git a/Win32/Src/inet_pton.c b/Win32/Src/inet_pton.c
new file mode 100644 (file)
index 0000000..7933a4e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the Kungliga Tekniska
+ *      Högskolan and its contributors.
+ * 
+ * 4. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: inet_pton.c,v 1.3 2007-09-27 18:02:20 gianluca Exp $ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+     "@(#) $Header: /tcpdump/master/libpcap/Win32/Src/inet_pton.c,v 1.3 2007-09-27 18:02:20 gianluca Exp $";
+#endif
+
+#include <errno.h>
+
+#ifdef WIN32
+#ifndef EAFNOSUPPORT
+#define        EAFNOSUPPORT    97      /* not present in errno.h provided with VC */
+#endif
+#endif
+
+#ifdef __MINGW32__
+int* _errno();
+#define errno (*_errno())
+#endif /* __MINGW32__ */
+
+#include <pcap-stdinc.h>
+
+int inet_aton(const char *cp, struct in_addr *addr);
+
+int
+inet_pton(int af, const char *src, void *dst)
+{
+    if (af != AF_INET) {
+       errno = EAFNOSUPPORT;
+       return -1;
+    }
+    return inet_aton (src, dst);
+}
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..20db44f
--- /dev/null
@@ -0,0 +1,1037 @@
+dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.93 2008-11-18 07:29:48 guy Exp $ (LBL)
+dnl
+dnl Copyright (c) 1995, 1996, 1997, 1998
+dnl    The Regents of the University of California.  All rights reserved.
+dnl
+dnl Redistribution and use in source and binary forms, with or without
+dnl modification, are permitted provided that: (1) source code distributions
+dnl retain the above copyright notice and this paragraph in its entirety, (2)
+dnl distributions including binary code include the above copyright notice and
+dnl this paragraph in its entirety in the documentation or other materials
+dnl provided with the distribution, and (3) all advertising materials mentioning
+dnl features or use of this software display the following acknowledgement:
+dnl ``This product includes software developed by the University of California,
+dnl Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+dnl the University nor the names of its contributors may be used to endorse
+dnl or promote products derived from this software without specific prior
+dnl written permission.
+dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+dnl WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+dnl MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+dnl
+dnl LBL autoconf macros
+dnl
+
+dnl
+dnl Do whatever AC_LBL_C_INIT work is necessary before using AC_PROG_CC.
+dnl
+dnl It appears that newer versions of autoconf (2.64 and later) will,
+dnl if you use AC_TRY_COMPILE in a macro, stick AC_PROG_CC at the
+dnl beginning of the macro, even if the macro itself calls AC_PROG_CC.
+dnl See the "Prerequisite Macros" and "Expanded Before Required" sections
+dnl in the Autoconf documentation.
+dnl
+dnl This causes a steaming heap of fail in our case, as we were, in
+dnl AC_LBL_C_INIT, doing the tests we now do in AC_LBL_C_INIT_BEFORE_CC,
+dnl calling AC_PROG_CC, and then doing the tests we now do in
+dnl AC_LBL_C_INIT.  Now, we run AC_LBL_C_INIT_BEFORE_CC, AC_PROG_CC,
+dnl and AC_LBL_C_INIT at the top level.
+dnl
+AC_DEFUN(AC_LBL_C_INIT_BEFORE_CC,
+    [AC_PREREQ(2.50)
+    AC_BEFORE([$0], [AC_LBL_C_INIT])
+    AC_BEFORE([$0], [AC_PROG_CC])
+    AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+    AC_BEFORE([$0], [AC_LBL_DEVEL])
+    AC_ARG_WITH(gcc, [  --without-gcc           don't use gcc])
+    $1="-O"
+    $2=""
+    if test "${srcdir}" != "." ; then
+           $2="-I\$(srcdir)"
+    fi
+    if test "${CFLAGS+set}" = set; then
+           LBL_CFLAGS="$CFLAGS"
+    fi
+    if test -z "$CC" ; then
+           case "$host_os" in
+
+           bsdi*)
+                   AC_CHECK_PROG(SHLICC2, shlicc2, yes, no)
+                   if test $SHLICC2 = yes ; then
+                           CC=shlicc2
+                           export CC
+                   fi
+                   ;;
+           esac
+    fi
+    if test -z "$CC" -a "$with_gcc" = no ; then
+           CC=cc
+           export CC
+    fi
+])
+
+dnl
+dnl Determine which compiler we're using (cc or gcc)
+dnl If using gcc, determine the version number
+dnl If using cc, require that it support ansi prototypes
+dnl If using gcc, use -O2 (otherwise use -O)
+dnl If using cc, explicitly specify /usr/local/include
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_C_INIT(copt, incls)
+dnl
+dnl results:
+dnl
+dnl    $1 (copt set)
+dnl    $2 (incls set)
+dnl    CC
+dnl    LDFLAGS
+dnl    ac_cv_lbl_gcc_vers
+dnl    LBL_CFLAGS
+dnl
+AC_DEFUN(AC_LBL_C_INIT,
+    [AC_PREREQ(2.50)
+    AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+    AC_BEFORE([$0], [AC_LBL_DEVEL])
+    AC_BEFORE([$0], [AC_LBL_SHLIBS_INIT])
+    if test "$GCC" = yes ; then
+           if test "$SHLICC2" = yes ; then
+                   ac_cv_lbl_gcc_vers=2
+                   $1="-O2"
+           else
+                   AC_MSG_CHECKING(gcc version)
+                   AC_CACHE_VAL(ac_cv_lbl_gcc_vers,
+                       ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \
+                           sed -e '/^gcc version /!d' \
+                               -e 's/^gcc version //' \
+                               -e 's/ .*//' -e 's/^[[[^0-9]]]*//' \
+                               -e 's/\..*//'`)
+                   AC_MSG_RESULT($ac_cv_lbl_gcc_vers)
+                   if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+                           $1="-O2"
+                   fi
+           fi
+    else
+           AC_MSG_CHECKING(that $CC handles ansi prototypes)
+           AC_CACHE_VAL(ac_cv_lbl_cc_ansi_prototypes,
+               AC_TRY_COMPILE(
+                   [#include <sys/types.h>],
+                   [int frob(int, char *)],
+                   ac_cv_lbl_cc_ansi_prototypes=yes,
+                   ac_cv_lbl_cc_ansi_prototypes=no))
+           AC_MSG_RESULT($ac_cv_lbl_cc_ansi_prototypes)
+           if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
+                   case "$host_os" in
+
+                   hpux*)
+                           AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE))
+                           savedcflags="$CFLAGS"
+                           CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
+                           AC_CACHE_VAL(ac_cv_lbl_cc_hpux_cc_aa,
+                               AC_TRY_COMPILE(
+                                   [#include <sys/types.h>],
+                                   [int frob(int, char *)],
+                                   ac_cv_lbl_cc_hpux_cc_aa=yes,
+                                   ac_cv_lbl_cc_hpux_cc_aa=no))
+                           AC_MSG_RESULT($ac_cv_lbl_cc_hpux_cc_aa)
+                           if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
+                                   AC_MSG_ERROR(see the INSTALL doc for more info)
+                           fi
+                           CFLAGS="$savedcflags"
+                           $1="-Aa $$1"
+                           AC_DEFINE(_HPUX_SOURCE,1,[needed on HP-UX])
+                           ;;
+
+                   osf*)
+                           AC_MSG_CHECKING(for ansi mode in DEC compiler ($CC -std1))
+                           savedcflags="$CFLAGS"
+                           CFLAGS="-std1"
+                           AC_CACHE_VAL(ac_cv_lbl_cc_osf1_cc_std1,
+                               AC_TRY_COMPILE(
+                                   [#include <sys/types.h>],
+                                   [int frob(int, char *)],
+                                   ac_cv_lbl_cc_osf1_cc_std1=yes,
+                                   ac_cv_lbl_cc_osf1_cc_std1=no))
+                           AC_MSG_RESULT($ac_cv_lbl_cc_osf1_cc_std1)
+                           if test $ac_cv_lbl_cc_osf1_cc_std1 = no ; then
+                                   AC_MSG_ERROR(see the INSTALL doc for more info)
+                           fi
+                           CFLAGS="$savedcflags"
+                           $1="-std1 $$1"
+                           ;;
+
+                   *)
+                           AC_MSG_ERROR(see the INSTALL doc for more info)
+                           ;;
+                   esac
+           fi
+           $2="$$2 -I/usr/local/include"
+           LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+           case "$host_os" in
+
+           irix*)
+                   $1="$$1 -xansi -signed -g3"
+                   ;;
+
+           osf*)
+                   #
+                   # Presumed to be DEC OSF/1, Digital UNIX, or
+                   # Tru64 UNIX.
+                   #
+                   $1="$$1 -g3"
+                   ;;
+
+           ultrix*)
+                   AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
+                   AC_CACHE_VAL(ac_cv_lbl_cc_const_proto,
+                       AC_TRY_COMPILE(
+                           [#include <sys/types.h>],
+                           [struct a { int b; };
+                           void c(const struct a *)],
+                           ac_cv_lbl_cc_const_proto=yes,
+                           ac_cv_lbl_cc_const_proto=no))
+                   AC_MSG_RESULT($ac_cv_lbl_cc_const_proto)
+                   if test $ac_cv_lbl_cc_const_proto = no ; then
+                           AC_DEFINE(const,[],
+                               [to handle Ultrix compilers that don't support const in prototypes])
+                   fi
+                   ;;
+           esac
+    fi
+])
+
+dnl
+dnl Determine what options are needed to build a shared library
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_SHLIBS_INIT
+dnl
+dnl results:
+dnl
+dnl    V_CCOPT (modified to build position-independent code)
+dnl    V_SHLIB_CMD
+dnl    V_SHLIB_OPT
+dnl    V_SONAME_OPT
+dnl    V_RPATH_OPT
+dnl
+AC_DEFUN(AC_LBL_SHLIBS_INIT,
+    [AC_PREREQ(2.50)
+    if test "$GCC" = yes ; then
+           #
+           # On platforms where we build a shared library:
+           #
+           #   add options to generate position-independent code,
+           #   if necessary (it's the default in AIX and Darwin/OS X);
+           #
+           #   define option to set the soname of the shared library,
+           #   if the OS supports that;
+           #
+           #   add options to specify, at link time, a directory to
+           #   add to the run-time search path, if that's necessary.
+           #
+           V_SHLIB_CMD="\$(CC)"
+           V_SHLIB_OPT="-shared"
+           case "$host_os" in
+
+           aix*)
+                   ;;
+
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
+                   #
+                   # Platforms where the linker is the GNU linker
+                   # or accepts command-line arguments like
+                   # those the GNU linker accepts.
+                   #
+                   # Some instruction sets require -fPIC on some
+                   # operating systems.  Check for them.  If you
+                   # have a combination that requires it, add it
+                   # here.
+                   #
+                   PIC_OPT=-fpic
+                   case "$host_cpu" in
+
+                   sparc64*)
+                       case "$host_os" in
+
+                       freebsd*)
+                           PIC_OPT=-fPIC
+                           ;;
+                       esac
+                       ;;
+                   esac
+                   V_CCOPT="$V_CCOPT $PIC_OPT"
+                   V_SONAME_OPT="-Wl,-soname,"
+                   V_RPATH_OPT="-Wl,-rpath,"
+                   ;;
+
+           hpux*)
+                   V_CCOPT="$V_CCOPT -fpic"
+                   #
+                   # XXX - this assumes GCC is using the HP linker,
+                   # rather than the GNU linker, and that the "+h"
+                   # option is used on all HP-UX platforms, both .sl
+                   # and .so.
+                   #
+                   V_SONAME_OPT="-Wl,+h,"
+                   #
+                   # By default, directories specifed with -L
+                   # are added to the run-time search path, so
+                   # we don't add them in pcap-config.
+                   #
+                   ;;
+
+           solaris*)
+                   V_CCOPT="$V_CCOPT -fpic"
+                   #
+                   # XXX - this assumes GCC is using the Sun linker,
+                   # rather than the GNU linker.
+                   #
+                   V_SONAME_OPT="-Wl,-h,"
+                   V_RPATH_OPT="-Wl,-R,"
+                   ;;
+           esac
+    else
+           #
+           # Set the appropriate compiler flags and, on platforms
+           # where we build a shared library:
+           #
+           #   add options to generate position-independent code,
+           #   if necessary (it's the default in Darwin/OS X);
+           #
+           #   if we generate ".so" shared libraries, define the
+           #   appropriate options for building the shared library;
+           #
+           #   add options to specify, at link time, a directory to
+           #   add to the run-time search path, if that's necessary.
+           #
+           # Note: spaces after V_SONAME_OPT are significant; on
+           # some platforms the soname is passed with a GCC-like
+           # "-Wl,-soname,{soname}" option, with the soname part
+           # of the option, while on other platforms the C compiler
+           # driver takes it as a regular option with the soname
+           # following the option.  The same applies to V_RPATH_OPT.
+           #
+           case "$host_os" in
+
+           aix*)
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-G -bnoentry -bexpall"
+                   ;;
+
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*)
+                   #
+                   # "cc" is GCC.
+                   #
+                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-shared"
+                   V_SONAME_OPT="-Wl,-soname,"
+                   V_RPATH_OPT="-Wl,-rpath,"
+                   ;;
+
+           hpux*)
+                   V_CCOPT="$V_CCOPT +z"
+                   V_SHLIB_CMD="\$(LD)"
+                   V_SHLIB_OPT="-b"
+                   V_SONAME_OPT="+h "
+                   #
+                   # By default, directories specifed with -L
+                   # are added to the run-time search path, so
+                   # we don't add them in pcap-config.
+                   #
+                   ;;
+
+           osf*)
+                   #
+                   # Presumed to be DEC OSF/1, Digital UNIX, or
+                   # Tru64 UNIX.
+                   #
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-shared"
+                   V_SONAME_OPT="-soname "
+                   V_RPATH_OPT="-rpath "
+                   ;;
+
+           solaris*)
+                   V_CCOPT="$V_CCOPT -Kpic"
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-G"
+                   V_SONAME_OPT="-h "
+                   V_RPATH_OPT="-R"
+                   ;;
+           esac
+    fi
+])
+
+#
+# Try compiling a sample of the type of code that appears in
+# gencode.c with "inline", "__inline__", and "__inline".
+#
+# Autoconf's AC_C_INLINE, at least in autoconf 2.13, isn't good enough,
+# as it just tests whether a function returning "int" can be inlined;
+# at least some versions of HP's C compiler can inline that, but can't
+# inline a function that returns a struct pointer.
+#
+# Make sure we use the V_CCOPT flags, because some of those might
+# disable inlining.
+#
+AC_DEFUN(AC_LBL_C_INLINE,
+    [AC_MSG_CHECKING(for inline)
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$V_CCOPT"
+    AC_CACHE_VAL(ac_cv_lbl_inline, [
+       ac_cv_lbl_inline=""
+       ac_lbl_cc_inline=no
+       for ac_lbl_inline in inline __inline__ __inline
+       do
+           AC_TRY_COMPILE(
+               [#define inline $ac_lbl_inline
+               static inline struct iltest *foo(void);
+               struct iltest {
+                   int iltest1;
+                   int iltest2;
+               };
+
+               static inline struct iltest *
+               foo()
+               {
+                   static struct iltest xxx;
+
+                   return &xxx;
+               }],,ac_lbl_cc_inline=yes,)
+           if test "$ac_lbl_cc_inline" = yes ; then
+               break;
+           fi
+       done
+       if test "$ac_lbl_cc_inline" = yes ; then
+           ac_cv_lbl_inline=$ac_lbl_inline
+       fi])
+    CFLAGS="$save_CFLAGS"
+    if test ! -z "$ac_cv_lbl_inline" ; then
+       AC_MSG_RESULT($ac_cv_lbl_inline)
+    else
+       AC_MSG_RESULT(no)
+    fi
+    AC_DEFINE_UNQUOTED(inline, $ac_cv_lbl_inline, [Define as token for inline if inlining supported])])
+
+dnl
+dnl If using gcc, make sure we have ANSI ioctl definitions
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_FIXINCLUDES
+dnl
+AC_DEFUN(AC_LBL_FIXINCLUDES,
+    [if test "$GCC" = yes ; then
+           AC_MSG_CHECKING(for ANSI ioctl definitions)
+           AC_CACHE_VAL(ac_cv_lbl_gcc_fixincludes,
+               AC_TRY_COMPILE(
+                   [/*
+                    * This generates a "duplicate case value" when fixincludes
+                    * has not be run.
+                    */
+#              include <sys/types.h>
+#              include <sys/time.h>
+#              include <sys/ioctl.h>
+#              ifdef HAVE_SYS_IOCCOM_H
+#              include <sys/ioccom.h>
+#              endif],
+                   [switch (0) {
+                   case _IO('A', 1):;
+                   case _IO('B', 1):;
+                   }],
+                   ac_cv_lbl_gcc_fixincludes=yes,
+                   ac_cv_lbl_gcc_fixincludes=no))
+           AC_MSG_RESULT($ac_cv_lbl_gcc_fixincludes)
+           if test $ac_cv_lbl_gcc_fixincludes = no ; then
+                   # Don't cache failure
+                   unset ac_cv_lbl_gcc_fixincludes
+                   AC_MSG_ERROR(see the INSTALL for more info)
+           fi
+    fi])
+
+dnl
+dnl Check for flex, default to lex
+dnl Require flex 2.4 or higher
+dnl Check for bison, default to yacc
+dnl Default to lex/yacc if both flex and bison are not available
+dnl Define the yy prefix string if using flex and bison
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
+dnl
+dnl results:
+dnl
+dnl    $1 (lex set)
+dnl    $2 (yacc appended)
+dnl    $3 (optional flex and bison -P prefix)
+dnl
+AC_DEFUN(AC_LBL_LEX_AND_YACC,
+    [AC_ARG_WITH(flex, [  --without-flex          don't use flex])
+    AC_ARG_WITH(bison, [  --without-bison         don't use bison])
+    if test "$with_flex" = no ; then
+           $1=lex
+    else
+           AC_CHECK_PROGS($1, flex, lex)
+    fi
+    if test "$$1" = flex ; then
+           # The -V flag was added in 2.4
+           AC_MSG_CHECKING(for flex 2.4 or higher)
+           AC_CACHE_VAL(ac_cv_lbl_flex_v24,
+               if flex -V >/dev/null 2>&1; then
+                       ac_cv_lbl_flex_v24=yes
+               else
+                       ac_cv_lbl_flex_v24=no
+               fi)
+           AC_MSG_RESULT($ac_cv_lbl_flex_v24)
+           if test $ac_cv_lbl_flex_v24 = no ; then
+                   s="2.4 or higher required"
+                   AC_MSG_WARN(ignoring obsolete flex executable ($s))
+                   $1=lex
+           fi
+    fi
+    if test "$with_bison" = no ; then
+           $2=yacc
+    else
+           AC_CHECK_PROGS($2, bison, yacc)
+    fi
+    if test "$$2" = bison ; then
+           $2="$$2 -y"
+    fi
+    if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
+           AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
+           $1=lex
+           $2=yacc
+    fi
+    if test "$$1" = flex -a -n "$3" ; then
+           $1="$$1 -P$3"
+           $2="$$2 -p $3"
+    fi])
+
+dnl
+dnl Checks to see if union wait is used with WEXITSTATUS()
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_UNION_WAIT
+dnl
+dnl results:
+dnl
+dnl    DECLWAITSTATUS (defined)
+dnl
+AC_DEFUN(AC_LBL_UNION_WAIT,
+    [AC_MSG_CHECKING(if union wait is used)
+    AC_CACHE_VAL(ac_cv_lbl_union_wait,
+       AC_TRY_COMPILE([
+#      include <sys/types.h>
+#      include <sys/wait.h>],
+           [int status;
+           u_int i = WEXITSTATUS(status);
+           u_int j = waitpid(0, &status, 0);],
+           ac_cv_lbl_union_wait=no,
+           ac_cv_lbl_union_wait=yes))
+    AC_MSG_RESULT($ac_cv_lbl_union_wait)
+    if test $ac_cv_lbl_union_wait = yes ; then
+           AC_DEFINE(DECLWAITSTATUS,union wait,[type for wait])
+    else
+           AC_DEFINE(DECLWAITSTATUS,int,[type for wait])
+    fi])
+
+dnl
+dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_SOCKADDR_SA_LEN
+dnl
+dnl results:
+dnl
+dnl    HAVE_SOCKADDR_SA_LEN (defined)
+dnl
+AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN,
+    [AC_MSG_CHECKING(if sockaddr struct has the sa_len member)
+    AC_CACHE_VAL(ac_cv_lbl_sockaddr_has_sa_len,
+       AC_TRY_COMPILE([
+#      include <sys/types.h>
+#      include <sys/socket.h>],
+       [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
+       ac_cv_lbl_sockaddr_has_sa_len=yes,
+       ac_cv_lbl_sockaddr_has_sa_len=no))
+    AC_MSG_RESULT($ac_cv_lbl_sockaddr_has_sa_len)
+    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
+           AC_DEFINE(HAVE_SOCKADDR_SA_LEN,1,[if struct sockaddr has the sa_len member])
+    fi])
+
+dnl
+dnl Checks to see if there's a sockaddr_storage structure
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_SOCKADDR_STORAGE
+dnl
+dnl results:
+dnl
+dnl    HAVE_SOCKADDR_STORAGE (defined)
+dnl
+AC_DEFUN(AC_LBL_SOCKADDR_STORAGE,
+    [AC_MSG_CHECKING(if sockaddr_storage struct exists)
+    AC_CACHE_VAL(ac_cv_lbl_has_sockaddr_storage,
+       AC_TRY_COMPILE([
+#      include <sys/types.h>
+#      include <sys/socket.h>],
+       [u_int i = sizeof (struct sockaddr_storage)],
+       ac_cv_lbl_has_sockaddr_storage=yes,
+       ac_cv_lbl_has_sockaddr_storage=no))
+    AC_MSG_RESULT($ac_cv_lbl_has_sockaddr_storage)
+    if test $ac_cv_lbl_has_sockaddr_storage = yes ; then
+           AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[if struct sockaddr_storage exists])
+    fi])
+
+dnl
+dnl Checks to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
+dnl dl_module_id_1 member
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
+dnl
+dnl results:
+dnl
+dnl    HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 (defined)
+dnl
+dnl NOTE: any compile failure means we conclude that it doesn't have
+dnl that member, so if we don't have DLPI, don't have a <sys/dlpi_ext.h>
+dnl header, or have one that doesn't declare a dl_hp_ppa_info_t type,
+dnl we conclude it doesn't have that member (which is OK, as either we
+dnl won't be using code that would use that member, or we wouldn't
+dnl compile in any case).
+dnl
+AC_DEFUN(AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1,
+    [AC_MSG_CHECKING(if dl_hp_ppa_info_t struct has dl_module_id_1 member)
+    AC_CACHE_VAL(ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1,
+       AC_TRY_COMPILE([
+#      include <sys/types.h>
+#      include <sys/dlpi.h>
+#      include <sys/dlpi_ext.h>],
+       [u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)],
+       ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes,
+       ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no))
+    AC_MSG_RESULT($ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1)
+    if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then
+           AC_DEFINE(HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1,1,[if ppa_info_t_dl_module_id exists])
+    fi])
+
+dnl
+dnl Checks to see if -R is used
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_HAVE_RUN_PATH
+dnl
+dnl results:
+dnl
+dnl    ac_cv_lbl_have_run_path (yes or no)
+dnl
+AC_DEFUN(AC_LBL_HAVE_RUN_PATH,
+    [AC_MSG_CHECKING(for ${CC-cc} -R)
+    AC_CACHE_VAL(ac_cv_lbl_have_run_path,
+       [echo 'main(){}' > conftest.c
+       ${CC-cc} -o conftest conftest.c -R/a1/b2/c3 >conftest.out 2>&1
+       if test ! -s conftest.out ; then
+               ac_cv_lbl_have_run_path=yes
+       else
+               ac_cv_lbl_have_run_path=no
+       fi
+       rm -f -r conftest*])
+    AC_MSG_RESULT($ac_cv_lbl_have_run_path)
+    ])
+
+dnl
+dnl Checks to see if unaligned memory accesses fail
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_UNALIGNED_ACCESS
+dnl
+dnl results:
+dnl
+dnl    LBL_ALIGN (DEFINED)
+dnl
+AC_DEFUN(AC_LBL_UNALIGNED_ACCESS,
+    [AC_MSG_CHECKING(if unaligned accesses fail)
+    AC_CACHE_VAL(ac_cv_lbl_unaligned_fail,
+       [case "$host_cpu" in
+
+       #
+       # These are CPU types where:
+       #
+       #       the CPU faults on an unaligned access, but at least some
+       #       OSes that support that CPU catch the fault and simulate
+       #       the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
+       #       the simulation is slow, so we don't want to use it;
+       #
+       #       the CPU, I infer (from the old
+       #
+       # XXX: should also check that they don't do weird things (like on arm)
+       #
+       #       comment) doesn't fault on unaligned accesses, but doesn't
+       #       do a normal unaligned fetch, either (e.g., presumably, ARM);
+       #
+       #       for whatever reason, the test program doesn't work
+       #       (this has been claimed to be the case for several of those
+       #       CPUs - I don't know what the problem is; the problem
+       #       was reported as "the test program dumps core" for SuperH,
+       #       but that's what the test program is *supposed* to do -
+       #       it dumps core before it writes anything, so the test
+       #       for an empty output file should find an empty output
+       #       file and conclude that unaligned accesses don't work).
+       #
+       # This run-time test won't work if you're cross-compiling, so
+       # in order to support cross-compiling for a particular CPU,
+       # we have to wire in the list of CPU types anyway, as far as
+       # I know, so perhaps we should just have a set of CPUs on
+       # which we know it doesn't work, a set of CPUs on which we
+       # know it does work, and have the script just fail on other
+       # cpu types and update it when such a failure occurs.
+       #
+       alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
+               ac_cv_lbl_unaligned_fail=yes
+               ;;
+
+       *)
+               cat >conftest.c <<EOF
+#              include <sys/types.h>
+#              include <sys/wait.h>
+#              include <stdio.h>
+               unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
+               main() {
+               unsigned int i;
+               pid_t pid;
+               int status;
+               /* avoid "core dumped" message */
+               pid = fork();
+               if (pid <  0)
+                       exit(2);
+               if (pid > 0) {
+                       /* parent */
+                       pid = waitpid(pid, &status, 0);
+                       if (pid < 0)
+                               exit(3);
+                       exit(!WIFEXITED(status));
+               }
+               /* child */
+               i = *(unsigned int *)&a[[1]];
+               printf("%d\n", i);
+               exit(0);
+               }
+EOF
+               ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
+                   conftest.c $LIBS >/dev/null 2>&1
+               if test ! -x conftest ; then
+                       dnl failed to compile for some reason
+                       ac_cv_lbl_unaligned_fail=yes
+               else
+                       ./conftest >conftest.out
+                       if test ! -s conftest.out ; then
+                               ac_cv_lbl_unaligned_fail=yes
+                       else
+                               ac_cv_lbl_unaligned_fail=no
+                       fi
+               fi
+               rm -f -r conftest* core core.conftest
+               ;;
+       esac])
+    AC_MSG_RESULT($ac_cv_lbl_unaligned_fail)
+    if test $ac_cv_lbl_unaligned_fail = yes ; then
+           AC_DEFINE(LBL_ALIGN,1,[if unaligned access fails])
+    fi])
+
+dnl
+dnl If using gcc and the file .devel exists:
+dnl    Compile with -g (if supported) and -Wall
+dnl    If using gcc 2 or later, do extra prototype checking
+dnl    If an os prototype include exists, symlink os-proto.h to it
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_DEVEL(copt)
+dnl
+dnl results:
+dnl
+dnl    $1 (copt appended)
+dnl    HAVE_OS_PROTO_H (defined)
+dnl    os-proto.h (symlinked)
+dnl
+AC_DEFUN(AC_LBL_DEVEL,
+    [rm -f os-proto.h
+    if test "${LBL_CFLAGS+set}" = set; then
+           $1="$$1 ${LBL_CFLAGS}"
+    fi
+    if test -f .devel ; then
+           if test "$GCC" = yes ; then
+                   if test "${LBL_CFLAGS+set}" != set; then
+                           if test "$ac_cv_prog_cc_g" = yes ; then
+                                   $1="-g $$1"
+                           fi
+                           $1="$$1 -Wall"
+                           if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+                                   $1="$$1 -Wmissing-prototypes -Wstrict-prototypes"
+                           fi
+                   fi
+           else
+                   case "$host_os" in
+
+                   irix6*)
+                           V_CCOPT="$V_CCOPT -n32"
+                           ;;
+
+                   *)
+                           ;;
+                   esac
+           fi
+           os=`echo $host_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
+           name="lbl/os-$os.h"
+           if test -f $name ; then
+                   ln -s $name os-proto.h
+                   AC_DEFINE(HAVE_OS_PROTO_H, 1,
+                       [if there's an os_proto.h for this platform, to use additional prototypes])
+           else
+                   AC_MSG_WARN(can't find $name)
+           fi
+    fi])
+
+dnl
+dnl Improved version of AC_CHECK_LIB
+dnl
+dnl Thanks to John Hawkinson (jhawk@mit.edu)
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [,
+dnl        ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+dnl
+dnl results:
+dnl
+dnl    LIBS
+dnl
+dnl XXX - "AC_LBL_LIBRARY_NET" was redone to use "AC_SEARCH_LIBS"
+dnl rather than "AC_LBL_CHECK_LIB", so this isn't used any more.
+dnl We keep it around for reference purposes in case it's ever
+dnl useful in the future.
+dnl
+
+define(AC_LBL_CHECK_LIB,
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing the library, function
+dnl name, and extra libraries to link with, because the test really is
+dnl for library $1 defining function $2, when linked with potinal
+dnl library $5, not just for library $1.  Separate tests with the same
+dnl $1 and different $2's or $5's may have different results.
+ac_lib_var=`echo $1['_']$2['_']$5 | sed 'y%./+- %__p__%'`
+AC_CACHE_VAL(ac_cv_lbl_lib_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-l$1 $5 $LIBS"
+AC_TRY_LINK(dnl
+ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+[/* Override any gcc2 internal prototype to avoid an error.  */
+]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $2();
+]),
+           [$2()],
+           eval "ac_cv_lbl_lib_$ac_lib_var=yes",
+           eval "ac_cv_lbl_lib_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$3], ,
+[changequote(, )dnl
+  ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+changequote([, ])dnl
+  AC_DEFINE_UNQUOTED($ac_tr_lib)
+  LIBS="-l$1 $LIBS"
+], [$3])
+else
+  AC_MSG_RESULT(no)
+ifelse([$4], , , [$4
+])dnl
+fi
+])
+
+dnl
+dnl AC_LBL_LIBRARY_NET
+dnl
+dnl This test is for network applications that need socket() and
+dnl gethostbyname() -ish functions.  Under Solaris, those applications
+dnl need to link with "-lsocket -lnsl".  Under IRIX, they need to link
+dnl with "-lnsl" but should *not* link with "-lsocket" because
+dnl libsocket.a breaks a number of things (for instance:
+dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
+dnl versions of IRIX).
+dnl
+dnl Unfortunately, many application developers are not aware of this,
+dnl and mistakenly write tests that cause -lsocket to be used under
+dnl IRIX.  It is also easy to write tests that cause -lnsl to be used
+dnl under operating systems where neither are necessary (or useful),
+dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
+dnl
+dnl This test exists so that every application developer does not test
+dnl this in a different, and subtly broken fashion.
+
+dnl It has been argued that this test should be broken up into two
+dnl seperate tests, one for the resolver libraries, and one for the
+dnl libraries necessary for using Sockets API. Unfortunately, the two
+dnl are carefully intertwined and allowing the autoconf user to use
+dnl them independantly potentially results in unfortunate ordering
+dnl dependancies -- as such, such component macros would have to
+dnl carefully use indirection and be aware if the other components were
+dnl executed. Since other autoconf macros do not go to this trouble,
+dnl and almost no applications use sockets without the resolver, this
+dnl complexity has not been implemented.
+dnl
+dnl The check for libresolv is in case you are attempting to link
+dnl statically and happen to have a libresolv.a lying around (and no
+dnl libnsl.a).
+dnl
+AC_DEFUN(AC_LBL_LIBRARY_NET, [
+    # Most operating systems have gethostbyname() in the default searched
+    # libraries (i.e. libc):
+    # Some OSes (eg. Solaris) place it in libnsl
+    # Some strange OSes (SINIX) have it in libsocket:
+    AC_SEARCH_LIBS(gethostbyname, nsl socket resolv)
+    # Unfortunately libsocket sometimes depends on libnsl and
+    # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
+    if test "$ac_cv_search_gethostbyname" = "no"
+    then
+       AC_CHECK_LIB(socket, gethostbyname,
+                     LIBS="-lsocket -lnsl $LIBS", , -lnsl)
+    fi
+    AC_SEARCH_LIBS(socket, socket, ,
+       AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    AC_SEARCH_LIBS(putmsg, str)
+    ])
+
+dnl
+dnl Test for __attribute__
+dnl
+
+AC_DEFUN(AC_C___ATTRIBUTE__, [
+AC_MSG_CHECKING(for __attribute__)
+AC_CACHE_VAL(ac_cv___attribute__, [
+AC_COMPILE_IFELSE(
+  AC_LANG_SOURCE([[
+#include <stdlib.h>
+
+static void foo(void) __attribute__ ((noreturn));
+
+static void
+foo(void)
+{
+  exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+  foo();
+}
+  ]]),
+ac_cv___attribute__=yes,
+ac_cv___attribute__=no)])
+if test "$ac_cv___attribute__" = "yes"; then
+  AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__])
+  V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\""
+else
+  V_DEFS="$V_DEFS -D_U_=\"\""
+fi
+AC_MSG_RESULT($ac_cv___attribute__)
+])
+
+dnl
+dnl Checks to see if tpacket_stats is defined in linux/if_packet.h
+dnl If so then pcap-linux.c can use this to report proper statistics.
+dnl
+dnl -Scott Barron
+dnl
+AC_DEFUN(AC_LBL_TPACKET_STATS,
+   [AC_MSG_CHECKING(if if_packet.h has tpacket_stats defined)
+   AC_CACHE_VAL(ac_cv_lbl_tpacket_stats,
+   AC_TRY_COMPILE([
+#  include <linux/if_packet.h>],
+   [struct tpacket_stats stats],
+   ac_cv_lbl_tpacket_stats=yes,
+   ac_cv_lbl_tpacket_stats=no))
+   AC_MSG_RESULT($ac_cv_lbl_tpacket_stats)
+   if test $ac_cv_lbl_tpacket_stats = yes; then
+       AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined])
+   fi])
+
+dnl
+dnl Checks to see if the tpacket_auxdata struct has a tp_vlan_tci member.
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+dnl
+dnl results:
+dnl
+dnl    HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI (defined)
+dnl
+dnl NOTE: any compile failure means we conclude that it doesn't have
+dnl that member, so if we don't have tpacket_auxdata, we conclude it
+dnl doesn't have that member (which is OK, as either we won't be using
+dnl code that would use that member, or we wouldn't compile in any case).
+dnl
+AC_DEFUN(AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI,
+    [AC_MSG_CHECKING(if tpacket_auxdata struct has tp_vlan_tci member)
+    AC_CACHE_VAL(ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci,
+       AC_TRY_COMPILE([
+#      include <sys/types.h>
+#      include <linux/if_packet.h>],
+       [u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)],
+       ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes,
+       ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no))
+    AC_MSG_RESULT($ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci)
+    if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then
+           HAVE_LINUX_TPACKET_AUXDATA=tp_vlan_tci
+           AC_SUBST(HAVE_LINUX_TPACKET_AUXDATA)
+           AC_DEFINE(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI,1,[if tp_vlan_tci exists])
+    fi])
+
+dnl
+dnl Checks to see if Solaris has the dl_passive_req_t struct defined
+dnl in <sys/dlpi.h>.
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_DL_PASSIVE_REQ_T
+dnl
+dnl results:
+dnl 
+dnl    HAVE_DLPI_PASSIVE (defined)
+dnl
+AC_DEFUN(AC_LBL_DL_PASSIVE_REQ_T,
+        [AC_MSG_CHECKING(if dl_passive_req_t struct exists)
+       AC_CACHE_VAL(ac_cv_lbl_has_dl_passive_req_t,
+                AC_TRY_COMPILE([
+#       include <sys/types.h>
+#       include <sys/dlpi.h>],
+        [u_int i = sizeof(dl_passive_req_t)],
+        ac_cv_lbl_has_dl_passive_req_t=yes,
+        ac_cv_lbl_has_dl_passive_req_t=no))
+    AC_MSG_RESULT($ac_cv_lbl_has_dl_passive_req_t)
+    if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
+            AC_DEFINE(HAVE_DLPI_PASSIVE,1,[if passive_req_t primitive
+               exists])
+    fi])
diff --git a/arcnet.h b/arcnet.h
new file mode 100644 (file)
index 0000000..4f86043
--- /dev/null
+++ b/arcnet.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $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
+ */
+
+/* RFC 1051 */
+#define        ARCTYPE_IP_OLD          240     /* IP protocol */
+#define        ARCTYPE_ARP_OLD         241     /* address resolution protocol */
+
+/* RFC 1201 */
+#define        ARCTYPE_IP              212     /* IP protocol */
+#define        ARCTYPE_ARP             213     /* address resolution protocol */
+#define        ARCTYPE_REVARP          214     /* reverse addr resolution protocol */
+
+#define        ARCTYPE_ATALK           221     /* Appletalk */
+#define        ARCTYPE_BANIAN          247     /* Banyan Vines */
+#define        ARCTYPE_IPX             250     /* Novell IPX */
+
+#define ARCTYPE_INET6          0xc4    /* IPng */
+#define ARCTYPE_DIAGNOSE       0x80    /* as per ANSI/ATA 878.1 */
diff --git a/atmuni31.h b/atmuni31.h
new file mode 100644 (file)
index 0000000..880cc1a
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Yen Yen Lim and
+        North Dakota State University
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#) $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 */
+
+/* ATM traffic types based on VPI=0 and (the following VCI */
+#define VCI_PPC                        0x05    /* Point-to-point signal msg */
+#define VCI_BCC                        0x02    /* Broadcast signal msg */
+#define VCI_OAMF4SC            0x03    /* Segment OAM F4 flow cell */
+#define VCI_OAMF4EC            0x04    /* End-to-end OAM F4 flow cell */
+#define VCI_METAC              0x01    /* Meta signal msg */
+#define VCI_ILMIC              0x10    /* ILMI msg */
+
+/* Q.2931 signalling messages */
+#define CALL_PROCEED           0x02    /* call proceeding */
+#define CONNECT                        0x07    /* connect */
+#define CONNECT_ACK            0x0f    /* connect_ack */
+#define SETUP                  0x05    /* setup */
+#define RELEASE                        0x4d    /* release */
+#define RELEASE_DONE           0x5a    /* release_done */
+#define RESTART                        0x46    /* restart */
+#define RESTART_ACK            0x4e    /* restart ack */
+#define STATUS                 0x7d    /* status */
+#define STATUS_ENQ             0x75    /* status ack */
+#define ADD_PARTY              0x80    /* add party */
+#define ADD_PARTY_ACK          0x81    /* add party ack */
+#define ADD_PARTY_REJ          0x82    /* add party rej */
+#define DROP_PARTY             0x83    /* drop party */
+#define DROP_PARTY_ACK         0x84    /* drop party ack */
+
+/* Information Element Parameters in the signalling messages */
+#define CAUSE                  0x08    /* cause */
+#define ENDPT_REF              0x54    /* endpoint reference */
+#define AAL_PARA               0x58    /* ATM adaptation layer parameters */
+#define TRAFF_DESCRIP          0x59    /* atm traffic descriptors */
+#define CONNECT_ID             0x5a    /* connection identifier */
+#define QOS_PARA               0x5c    /* quality of service parameters */
+#define B_HIGHER               0x5d    /* broadband higher layer information */
+#define B_BEARER               0x5e    /* broadband bearer capability */
+#define B_LOWER                        0x5f    /* broadband lower information */
+#define CALLING_PARTY          0x6c    /* calling party number */
+#define CALLED_PARTY           0x70    /* called party nmber */
+
+#define Q2931                  0x09
+
+/* Q.2931 signalling general messages format */
+#define PROTO_POS       0      /* offset of protocol discriminator */
+#define CALL_REF_POS    2      /* offset of call reference value */
+#define MSG_TYPE_POS    5      /* offset of message type */
+#define MSG_LEN_POS     7      /* offset of mesage length */
+#define IE_BEGIN_POS    9      /* offset of first information element */
+
+/* format of signalling messages */
+#define TYPE_POS       0
+#define LEN_POS                2
+#define FIELD_BEGIN_POS 4
diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c
new file mode 100644 (file)
index 0000000..0c4fb00
--- /dev/null
@@ -0,0 +1,686 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)bpf.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
+
+#include <pcap-stdinc.h>
+
+#else /* WIN32 */
+
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#define        SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
+#if defined(__hpux) || SOLARIS
+# include <sys/sysmacros.h>
+# include <sys/stream.h>
+# define       mbuf    msgb
+# define       m_next  b_cont
+# define       MLEN(m) ((m)->b_wptr - (m)->b_rptr)
+# define       mtod(m,t)       ((t)(m)->b_rptr)
+#else /* defined(__hpux) || SOLARIS */
+# define       MLEN(m) ((m)->m_len)
+#endif /* defined(__hpux) || SOLARIS */
+
+#endif /* WIN32 */
+
+#include <pcap/bpf.h>
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+#include <stdlib.h>
+#endif
+
+#define int32 bpf_int32
+#define u_int32 bpf_u_int32
+
+#ifndef LBL_ALIGN
+/*
+ * XXX - IA-64?  If not, this probably won't work on Win64 IA-64
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ * XXX - SuperH?  If not, this probably won't work on WinCE SuperH
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ */
+#if defined(sparc) || defined(__sparc__) || defined(mips) || \
+    defined(ibm032) || defined(__alpha) || defined(__hpux) || \
+    defined(__arm__)
+#define LBL_ALIGN
+#endif
+#endif
+
+#ifndef LBL_ALIGN
+#ifndef WIN32
+#include <netinet/in.h>
+#endif
+
+#define EXTRACT_SHORT(p)       ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p)                (ntohl(*(u_int32 *)p))
+#else
+#define EXTRACT_SHORT(p)\
+       ((u_short)\
+               ((u_short)*((u_char *)p+0)<<8|\
+                (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+               ((u_int32)*((u_char *)p+0)<<24|\
+                (u_int32)*((u_char *)p+1)<<16|\
+                (u_int32)*((u_char *)p+2)<<8|\
+                (u_int32)*((u_char *)p+3)<<0)
+#endif
+
+#if defined(KERNEL) || defined(_KERNEL)
+# if !defined(__hpux) && !SOLARIS
+#include <sys/mbuf.h>
+# endif
+#define MINDEX(len, _m, _k) \
+{ \
+       len = MLEN(m); \
+       while ((_k) >= len) { \
+               (_k) -= len; \
+               (_m) = (_m)->m_next; \
+               if ((_m) == 0) \
+                       return 0; \
+               len = MLEN(m); \
+       } \
+}
+
+static int
+m_xword(m, k, err)
+       register struct mbuf *m;
+       register int k, *err;
+{
+       register int len;
+       register u_char *cp, *np;
+       register struct mbuf *m0;
+
+       MINDEX(len, m, k);
+       cp = mtod(m, u_char *) + k;
+       if (len - k >= 4) {
+               *err = 0;
+               return EXTRACT_LONG(cp);
+       }
+       m0 = m->m_next;
+       if (m0 == 0 || MLEN(m0) + len - k < 4)
+               goto bad;
+       *err = 0;
+       np = mtod(m0, u_char *);
+       switch (len - k) {
+
+       case 1:
+               return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
+
+       case 2:
+               return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
+
+       default:
+               return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
+       }
+    bad:
+       *err = 1;
+       return 0;
+}
+
+static int
+m_xhalf(m, k, err)
+       register struct mbuf *m;
+       register int k, *err;
+{
+       register int len;
+       register u_char *cp;
+       register struct mbuf *m0;
+
+       MINDEX(len, m, k);
+       cp = mtod(m, u_char *) + k;
+       if (len - k >= 2) {
+               *err = 0;
+               return EXTRACT_SHORT(cp);
+       }
+       m0 = m->m_next;
+       if (m0 == 0)
+               goto bad;
+       *err = 0;
+       return (cp[0] << 8) | mtod(m0, u_char *)[0];
+ bad:
+       *err = 1;
+       return 0;
+}
+#endif
+
+/*
+ * 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
+ * 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.
+ */
+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;
+{
+       register u_int32 A, X;
+       register int k;
+       int32 mem[BPF_MEMWORDS];
+#if defined(KERNEL) || defined(_KERNEL)
+       struct mbuf *m, *n;
+       int merr, len;
+
+       if (buflen == 0) {
+               m = (struct mbuf *)p;
+               p = mtod(m, u_char *);
+               buflen = MLEN(m);
+       } else
+               m = NULL;
+#endif
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (u_int)-1;
+       A = 0;
+       X = 0;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+#if defined(KERNEL) || defined(_KERNEL)
+                       return 0;
+#else
+                       abort();
+#endif
+               case BPF_RET|BPF_K:
+                       return (u_int)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (u_int)A;
+
+               case BPF_LD|BPF_W|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(int32) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               A = m_xword(m, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(short) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               A = m_xhalf(m, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               n = m;
+                               MINDEX(len, n, k);
+                               A = mtod(n, u_char *)[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_LEN:
+                       A = wirelen;
+                       continue;
+
+               case BPF_LDX|BPF_W|BPF_LEN:
+                       X = wirelen;
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(int32) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               A = m_xword(m, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(short) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               A = m_xhalf(m, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_IND:
+                       k = X + pc->k;
+                       if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               n = m;
+                               MINDEX(len, n, k);
+                               A = mtod(n, u_char *)[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LDX|BPF_MSH|BPF_B:
+                       k = pc->k;
+                       if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (m == NULL)
+                                       return 0;
+                               n = m;
+                               MINDEX(len, n, k);
+                               X = (mtod(n, char *)[k] & 0xf) << 2;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       X = (p[pc->k] & 0xf) << 2;
+                       continue;
+
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+               case BPF_JMP|BPF_JA:
+#if defined(KERNEL) || defined(_KERNEL)
+                       /*
+                        * No backward jumps allowed.
+                        */
+                       pc += pc->k;
+#else
+                       /*
+                        * XXX - we currently implement "ip6 protochain"
+                        * with backward jumps, so sign-extend pc->k.
+                        */
+                       pc += (bpf_int32)pc->k;
+#endif
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += (A > pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += (A >= pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += (A == pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       A = -A;
+                       continue;
+
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+               }
+       }
+}
+
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code, that memory accesses are within valid ranges (to the
+ * extent that this can be checked statically; loads of packet
+ * data have to be, and are, also checked at run time), and that
+ * the code terminates with either an accept or reject.
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(f, len)
+       const struct bpf_insn *f;
+       int len;
+{
+       u_int i, from;
+       const struct bpf_insn *p;
+
+       if (len < 1)
+               return 0;
+       /*
+        * There's no maximum program length in userland.
+        */
+#if defined(KERNEL) || defined(_KERNEL)
+       if (len > BPF_MAXINSNS)
+               return 0;
+#endif
+
+       for (i = 0; i < len; ++i) {
+               p = &f[i];
+               switch (BPF_CLASS(p->code)) {
+               /*
+                * Check that memory operations use valid addresses.
+                */
+               case BPF_LD:
+               case BPF_LDX:
+                       switch (BPF_MODE(p->code)) {
+                       case BPF_IMM:
+                               break;
+                       case BPF_ABS:
+                       case BPF_IND:
+                       case BPF_MSH:
+                               /*
+                                * There's no maximum packet data size
+                                * in userland.  The runtime packet length
+                                * check suffices.
+                                */
+#if defined(KERNEL) || defined(_KERNEL)
+                               /*
+                                * More strict check with actual packet length
+                                * is done runtime.
+                                */
+                               if (p->k >= bpf_maxbufsize)
+                                       return 0;
+#endif
+                               break;
+                       case BPF_MEM:
+                               if (p->k >= BPF_MEMWORDS)
+                                       return 0;
+                               break;
+                       case BPF_LEN:
+                               break;
+                       default:
+                               return 0;
+                       }
+                       break;
+               case BPF_ST:
+               case BPF_STX:
+                       if (p->k >= BPF_MEMWORDS)
+                               return 0;
+                       break;
+               case BPF_ALU:
+                       switch (BPF_OP(p->code)) {
+                       case BPF_ADD:
+                       case BPF_SUB:
+                       case BPF_MUL:
+                       case BPF_OR:
+                       case BPF_AND:
+                       case BPF_LSH:
+                       case BPF_RSH:
+                       case BPF_NEG:
+                               break;
+                       case BPF_DIV:
+                               /*
+                                * Check for constant division by 0.
+                                */
+                               if (BPF_SRC(p->code) == BPF_K && p->k == 0)
+                                       return 0;
+                               break;
+                       default:
+                               return 0;
+                       }
+                       break;
+               case BPF_JMP:
+                       /*
+                        * Check that jumps are within the code block,
+                        * and that unconditional branches don't go
+                        * backwards as a result of an overflow.
+                        * Unconditional branches have a 32-bit offset,
+                        * so they could overflow; we check to make
+                        * sure they don't.  Conditional branches have
+                        * an 8-bit offset, and the from address is <=
+                        * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+                        * is sufficiently small that adding 255 to it
+                        * won't overflow.
+                        *
+                        * We know that len is <= BPF_MAXINSNS, and we
+                        * assume that BPF_MAXINSNS is < the maximum size
+                        * of a u_int, so that i + 1 doesn't overflow.
+                        *
+                        * For userland, we don't know that the from
+                        * or len are <= BPF_MAXINSNS, but we know that
+                        * from <= len, and, except on a 64-bit system,
+                        * it's unlikely that len, if it truly reflects
+                        * the size of the program we've been handed,
+                        * will be anywhere near the maximum size of
+                        * a u_int.  We also don't check for backward
+                        * branches, as we currently support them in
+                        * userland for the protochain operation.
+                        */
+                       from = i + 1;
+                       switch (BPF_OP(p->code)) {
+                       case BPF_JA:
+#if defined(KERNEL) || defined(_KERNEL)
+                               if (from + p->k < from || from + p->k >= len)
+#else
+                               if (from + p->k >= len)
+#endif
+                                       return 0;
+                               break;
+                       case BPF_JEQ:
+                       case BPF_JGT:
+                       case BPF_JGE:
+                       case BPF_JSET:
+                               if (from + p->jt >= len || from + p->jf >= len)
+                                       return 0;
+                               break;
+                       default:
+                               return 0;
+                       }
+                       break;
+               case BPF_RET:
+                       break;
+               case BPF_MISC:
+                       break;
+               default:
+                       return 0;
+               }
+       }
+       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/bpf_dump.c b/bpf_dump.c
new file mode 100644 (file)
index 0000000..e4ff4a2
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 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"
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+
+void
+bpf_dump(const struct bpf_program *p, int option)
+{
+       const struct bpf_insn *insn;
+       int i;
+       int n = p->bf_len;
+
+       insn = p->bf_insns;
+       if (option > 2) {
+               printf("%d\n", n);
+               for (i = 0; i < n; ++insn, ++i) {
+                       printf("%u %u %u %u\n", insn->code,
+                              insn->jt, insn->jf, insn->k);
+               }
+               return ;
+       }
+       if (option > 1) {
+               for (i = 0; i < n; ++insn, ++i)
+                       printf("{ 0x%x, %d, %d, 0x%08x },\n",
+                              insn->code, insn->jt, insn->jf, insn->k);
+               return;
+       }
+       for (i = 0; i < n; ++insn, ++i) {
+#ifdef BDEBUG
+               extern int bids[];
+               printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+#endif
+               puts(bpf_image(insn, i));
+       }
+}
diff --git a/bpf_image.c b/bpf_image.c
new file mode 100644 (file)
index 0000000..e2f1a77
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 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 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
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+char *
+bpf_image(p, n)
+       const struct bpf_insn *p;
+       int n;
+{
+       int v;
+       const char *fmt, *op;
+       static char image[256];
+       char operand[64];
+
+       v = p->k;
+       switch (p->code) {
+
+       default:
+               op = "unimp";
+               fmt = "0x%x";
+               v = p->code;
+               break;
+
+       case BPF_RET|BPF_K:
+               op = "ret";
+               fmt = "#%d";
+               break;
+
+       case BPF_RET|BPF_A:
+               op = "ret";
+               fmt = "";
+               break;
+
+       case BPF_LD|BPF_W|BPF_ABS:
+               op = "ld";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_H|BPF_ABS:
+               op = "ldh";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_B|BPF_ABS:
+               op = "ldb";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_W|BPF_LEN:
+               op = "ld";
+               fmt = "#pktlen";
+               break;
+
+       case BPF_LD|BPF_W|BPF_IND:
+               op = "ld";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_H|BPF_IND:
+               op = "ldh";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_B|BPF_IND:
+               op = "ldb";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_IMM:
+               op = "ld";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_LDX|BPF_IMM:
+               op = "ldx";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_LDX|BPF_MSH|BPF_B:
+               op = "ldxb";
+               fmt = "4*([%d]&0xf)";
+               break;
+
+       case BPF_LD|BPF_MEM:
+               op = "ld";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_LDX|BPF_MEM:
+               op = "ldx";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_ST:
+               op = "st";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_STX:
+               op = "stx";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_JMP|BPF_JA:
+               op = "ja";
+               fmt = "%d";
+               v = n + 1 + p->k;
+               break;
+
+       case BPF_JMP|BPF_JGT|BPF_K:
+               op = "jgt";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JGE|BPF_K:
+               op = "jge";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JEQ|BPF_K:
+               op = "jeq";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JSET|BPF_K:
+               op = "jset";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JGT|BPF_X:
+               op = "jgt";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JGE|BPF_X:
+               op = "jge";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JEQ|BPF_X:
+               op = "jeq";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JSET|BPF_X:
+               op = "jset";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_X:
+               op = "add";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_SUB|BPF_X:
+               op = "sub";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_MUL|BPF_X:
+               op = "mul";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_DIV|BPF_X:
+               op = "div";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_AND|BPF_X:
+               op = "and";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_OR|BPF_X:
+               op = "or";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_LSH|BPF_X:
+               op = "lsh";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_RSH|BPF_X:
+               op = "rsh";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_K:
+               op = "add";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_SUB|BPF_K:
+               op = "sub";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_MUL|BPF_K:
+               op = "mul";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_DIV|BPF_K:
+               op = "div";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_AND|BPF_K:
+               op = "and";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_ALU|BPF_OR|BPF_K:
+               op = "or";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_ALU|BPF_LSH|BPF_K:
+               op = "lsh";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_RSH|BPF_K:
+               op = "rsh";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_NEG:
+               op = "neg";
+               fmt = "";
+               break;
+
+       case BPF_MISC|BPF_TAX:
+               op = "tax";
+               fmt = "";
+               break;
+
+       case BPF_MISC|BPF_TXA:
+               op = "txa";
+               fmt = "";
+               break;
+       }
+       (void)snprintf(operand, sizeof operand, fmt, v);
+       (void)snprintf(image, sizeof image,
+                     (BPF_CLASS(p->code) == BPF_JMP &&
+                      BPF_OP(p->code) != BPF_JA) ?
+                     "(%03d) %-8s %-16s jt %d\tjf %d"
+                     : "(%03d) %-8s %s",
+                     n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+       return image;
+}
diff --git a/chmod_bpf b/chmod_bpf
new file mode 100755 (executable)
index 0000000..0a30d99
--- /dev/null
+++ b/chmod_bpf
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+#
+# Unfortunately, Mac OS X's devfs is based on the old FreeBSD
+# one, not the current one, so there's no way to configure it
+# to create BPF devices with particular owners or groups.
+# This startup item will make it owned by the admin group,
+# with permissions rw-rw----, so that anybody in the admin
+# group can use programs that capture or send raw packets.
+#
+# Change this as appropriate for your site, e.g. to make
+# it owned by a particular user without changing the permissions,
+# so only that user and the super-user can capture or send raw
+# packets, or give it the permissions rw-r-----, so that
+# only the super-user can send raw packets but anybody in the
+# admin group can capture packets.
+#
+chgrp admin /dev/bpf*
+chmod g+rw /dev/bpf*
diff --git a/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..c2246a4
--- /dev/null
@@ -0,0 +1,1502 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+#   Free Software Foundation, Inc.
+
+timestamp='2009-12-30'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep -q __ELF__
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    s390x:SunOS:*:*)
+       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+       echo i386-pc-auroraux${UNAME_RELEASE}
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[456])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep -q __LP64__
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           authenticamd | genuineintel | EM64T)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    8664:Windows_NT:*)
+       echo x86_64-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep -q ld.so.1
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-gnu
+       else
+           echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       LIBC=gnu
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+       echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef ${UNAME_MACHINE}
+       #undef ${UNAME_MACHINE}el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=${UNAME_MACHINE}el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=${UNAME_MACHINE}
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-gnu
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i586.
+       # Note: whatever this is, it MUST be the same as what config.sub
+       # prints for the "djgpp" host, or else GDB configury will decide that
+       # this is a cross-build.
+       echo i586-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           i386)
+               eval $set_cc_for_build
+               if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+                 if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+                     (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+                     grep IS_64BIT_ARCH >/dev/null
+                 then
+                     UNAME_PROCESSOR="x86_64"
+                 fi
+               fi ;;
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+    i*86:AROS:*:*)
+       echo ${UNAME_MACHINE}-pc-aros
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..bd5177c
--- /dev/null
@@ -0,0 +1,314 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Enable optimizer debugging */
+#undef BDEBUG
+
+/* define if you have a cloning BPF device */
+#undef HAVE_CLONING_BPF
+
+/* define if you have the DAG API */
+#undef HAVE_DAG_API
+
+/* define if you have dag_get_erf_types() */
+#undef HAVE_DAG_GET_ERF_TYPES
+
+/* define if you have dag_get_stream_erf_types() */
+#undef HAVE_DAG_GET_STREAM_ERF_TYPES
+
+/* define if you have streams capable DAG API */
+#undef HAVE_DAG_STREAMS_API
+
+/* define if you have vdag_set_device_info() */
+#undef HAVE_DAG_VDAG
+
+/* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
+   don't. */
+#undef HAVE_DECL_ETHER_HOSTTON
+
+/* define if you have a /dev/dlpi */
+#undef HAVE_DEV_DLPI
+
+/* if passive_req_t primitive exists */
+#undef HAVE_DLPI_PASSIVE
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#undef HAVE_ETHER_HOSTTON
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* on HP-UX 10.20 or later */
+#undef HAVE_HPUX10_20_OR_LATER
+
+/* on HP-UX 9.x */
+#undef HAVE_HPUX9
+
+/* if ppa_info_t_dl_module_id exists */
+#undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* if libdlpi exists */
+#undef HAVE_LIBDLPI
+
+/* if libnl exists */
+#undef HAVE_LIBNL
+
+/* if libnl exists and is version 2.x */
+#undef HAVE_LIBNL_2_x
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+#undef HAVE_LINUX_COMPILER_H
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#undef HAVE_LINUX_ETHTOOL_H
+
+/* Define to 1 if you have the <linux/if_packet.h> header file. */
+#undef HAVE_LINUX_IF_PACKET_H
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+#undef HAVE_LINUX_NET_TSTAMP_H
+
+/* if tp_vlan_tci exists */
+#undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+#undef HAVE_LINUX_TYPES_H
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+#undef HAVE_LINUX_USBDEVICE_FS_H
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#undef HAVE_LINUX_WIRELESS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netinet/ether.h> header file. */
+#undef HAVE_NETINET_ETHER_H
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define to 1 if you have the <netpacket/if_packet.h> header file. */
+#undef HAVE_NETPACKET_IF_PACKET_H
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+#undef HAVE_NETPACKET_PACKET_H
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#undef HAVE_NET_IF_MEDIA_H
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#undef HAVE_NET_PFVAR_H
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+#undef HAVE_OS_PROTO_H
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#undef HAVE_PF_NAT_THROUGH_PF_NORDR
+
+/* define if you have a Septel API */
+#undef HAVE_SEPTEL_API
+
+/* define if you have Myricom SNF API */
+#undef HAVE_SNF_API
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* if struct sockaddr has the sa_len member */
+#undef HAVE_SOCKADDR_SA_LEN
+
+/* if struct sockaddr_storage exists */
+#undef HAVE_SOCKADDR_STORAGE
+
+/* define if socklen_t is defined */
+#undef HAVE_SOCKLEN_T
+
+/* On solaris */
+#undef HAVE_SOLARIS
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+#undef HAVE_STRUCT_BPF_TIMEVAL
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+#undef HAVE_STRUCT_ETHER_ADDR
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+#undef HAVE_SYS_BITYPES_H
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+#undef HAVE_SYS_BUFMOD_H
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+#undef HAVE_SYS_DLPI_EXT_H
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#undef HAVE_SYS_IOCCOM_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* if if_packet.h has tpacket_stats defined */
+#undef HAVE_TPACKET_STATS
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* if struct usbdevfs_ctrltransfer has bRequestType */
+#undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+
+/* define if version.h is generated in the build procedure */
+#undef HAVE_VERSION_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* define if the system supports zerocopy BPF */
+#undef HAVE_ZEROCOPY_BPF
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* IPv6 */
+#undef INET6
+
+/* if unaligned access fails */
+#undef LBL_ALIGN
+
+/* path for device for USB sniffing */
+#undef LINUX_USB_MON_DEV
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
+
+/* do not use protochain */
+#undef NO_PROTOCHAIN
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* /dev/dlpi directory */
+#undef PCAP_DEV_PREFIX
+
+/* target host supports Bluetooth sniffing */
+#undef PCAP_SUPPORT_BT
+
+/* target host supports CAN sniffing */
+#undef PCAP_SUPPORT_CAN
+
+/* target host supports canusb */
+#undef PCAP_SUPPORT_CANUSB
+
+/* target host supports netfilter sniffing */
+#undef PCAP_SUPPORT_NETFILTER
+
+/* target host supports USB sniffing */
+#undef PCAP_SUPPORT_USB
+
+/* include ACN support */
+#undef SITA
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable parser debugging */
+#undef YYDEBUG
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* needed on HP-UX */
+#undef _HPUX_SOURCE
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* define on AIX to get certain functions */
+#undef _SUN
+
+/* to handle Ultrix compilers that don't support const in prototypes */
+#undef const
+
+/* Define as token for inline if inlining supported */
+#undef inline
+
+/* Define to `short' if int16_t not defined. */
+#undef int16_t
+
+/* Define to `int' if int32_t not defined. */
+#undef int32_t
+
+/* Define to `long long' if int64_t not defined. */
+#undef int64_t
+
+/* Define to `signed char' if int8_t not defined. */
+#undef int8_t
+
+/* on sinix */
+#undef sinix
+
+/* Define to `unsigned short' if u_int16_t not defined. */
+#undef u_int16_t
+
+/* Define to `unsigned int' if u_int32_t not defined. */
+#undef u_int32_t
+
+/* Define to `unsigned long long' if u_int64_t not defined. */
+#undef u_int64_t
+
+/* Define to `unsigned char' if u_int8_t not defined. */
+#undef u_int8_t
diff --git a/config.sub b/config.sub
new file mode 100755 (executable)
index 0000000..8518609
--- /dev/null
@@ -0,0 +1,1708 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+#   Free Software Foundation, Inc.
+
+timestamp='2009-12-31'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray | -microblaze)
+               os=
+               basic_machine=$1
+               ;;
+        -bluegene*)
+               os=-cnk
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | moxie \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | rx \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | ubicom32 \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* | rx-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+       | tron-* \
+       | ubicom32-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aros)
+               basic_machine=i386-pc
+               os=-aros
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       bluegene*)
+               basic_machine=powerpc-ibm
+               os=-cnk
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+        cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+        microblaze)
+               basic_machine=microblaze-xilinx
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tile*)
+               basic_machine=tile-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+        -auroraux)
+               os=-auroraux
+               ;;
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+             | -sym* | -kopensolaris* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* | -aros* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+        -nacl*)
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -cnk*|-aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..29e0f35
--- /dev/null
+++ b/configure
@@ -0,0 +1,9080 @@
+#! /bin/sh
+# From configure.in Revision: 1.168 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.67.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+        /*)
+          for as_base in sh bash ksh sh5; do
+            # Try only shells that exist, to save several forks.
+            as_shell=$as_dir/$as_base
+            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+          done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+       # neutralization value for shells without unset; and this also
+       # works around shells that cannot unset nonexistent variables.
+       BASH_ENV=/dev/null
+       ENV=/dev/null
+       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+       export CONFIG_SHELL
+       exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="pcap.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+CAN_SRC
+PCAP_SUPPORT_CAN
+CANUSB_SRC
+PCAP_SUPPORT_CANUSB
+BT_SRC
+PCAP_SUPPORT_BT
+NETFILTER_SRC
+PCAP_SUPPORT_NETFILTER
+USB_SRC
+PCAP_SUPPORT_USB
+MAN_MISC_INFO
+MAN_FILE_FORMATS
+DYEXT
+SSRC
+ADDLARCHIVEOBJS
+ADDLOBJS
+V_RPATH_OPT
+V_SONAME_OPT
+V_SHLIB_OPT
+V_SHLIB_CMD
+V_PCAP
+V_INCLS
+V_FINDALLDEVS
+V_DEFS
+V_CCOPT
+AR
+RANLIB
+V_YACC
+V_LEX
+HAVE_LINUX_TPACKET_AUXDATA
+LIBOBJS
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+SHLICC2
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_gcc
+enable_largefile
+enable_protochain
+with_sita
+with_pcap
+with_libnl
+enable_ipv6
+enable_optimizer_dbg
+enable_yydebug
+with_dag
+with_dag_includes
+with_dag_libraries
+with_septel
+with_snf
+with_snf_includes
+with_snf_libraries
+with_flex
+with_bison
+enable_universal
+enable_bluetooth
+enable_canusb
+enable_can
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used" >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-largefile     omit support for large files
+  --disable-protochain    disable \"protochain\" insn
+  --enable-ipv6           build IPv6-capable version [default=yes, if
+                          getaddrinfo available]
+  --enable-optimizer-dbg  build optimizer debugging code
+  --enable-yydebug        build parser debugging code
+  --disable-universal     don't build universal on OS X
+  --enable-bluetooth      enable Bluetooth support [default=yes, if support
+                          available]
+  --enable-canusb         enable canusb support [default=yes, if support
+                          available]
+
+  --enable-can            enable CAN support [default=yes, if support
+                          available]
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-gcc           don't use gcc
+  --with-sita             include SITA support
+  --with-pcap=TYPE        use packet capture TYPE
+  --without-libnl         disable libnl support [default=yes, on Linux, if
+                          present]
+  --with-dag[=DIR]        include Endace DAG support ["yes", "no" or DIR;
+                          default="yes" on BSD and Linux if present]
+  --with-dag-includes=DIR Endace DAG include directory
+  --with-dag-libraries=DIR
+                          Endace DAG library directory
+  --with-septel[=DIR]     include Septel support (located in directory DIR, if
+                          supplied). [default=yes, on Linux, if present]
+  --with-snf[=DIR]        include Myricom SNF support ["yes", "no" or DIR;
+                          default="yes" on BSD and Linux if present]
+  --with-snf-includes=DIR Myricom SNF include directory
+  --with-snf-libraries=DIR
+                          Myricom SNF library directory
+  --without-flex          don't use flex
+  --without-bison         don't use bison
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.67
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval "test \"\${$3+set}\"" = set; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.67.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5 ; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5 ;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+
+
+
+
+
+
+# Check whether --with-gcc was given.
+if test "${with_gcc+set}" = set; then :
+  withval=$with_gcc;
+fi
+
+    V_CCOPT="-O"
+    V_INCLS=""
+    if test "${srcdir}" != "." ; then
+           V_INCLS="-I\$(srcdir)"
+    fi
+    if test "${CFLAGS+set}" = set; then
+           LBL_CFLAGS="$CFLAGS"
+    fi
+    if test -z "$CC" ; then
+           case "$host_os" in
+
+           bsdi*)
+                   # Extract the first word of "shlicc2", so it can be a program name with args.
+set dummy shlicc2; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_SHLICC2+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$SHLICC2"; then
+  ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_SHLICC2="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no"
+fi
+fi
+SHLICC2=$ac_cv_prog_SHLICC2
+if test -n "$SHLICC2"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHLICC2" >&5
+$as_echo "$SHLICC2" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+                   if test $SHLICC2 = yes ; then
+                           CC=shlicc2
+                           export CC
+                   fi
+                   ;;
+           esac
+    fi
+    if test -z "$CC" -a "$with_gcc" = no ; then
+           CC=cc
+           export CC
+    fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5 ; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5 ; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5 ; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+    if test "$GCC" = yes ; then
+           if test "$SHLICC2" = yes ; then
+                   ac_cv_lbl_gcc_vers=2
+                   V_CCOPT="-O2"
+           else
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5
+$as_echo_n "checking gcc version... " >&6; }
+                   if test "${ac_cv_lbl_gcc_vers+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_lbl_gcc_vers=`$CC -v 2>&1 | \
+                           sed -e '/^gcc version /!d' \
+                               -e 's/^gcc version //' \
+                               -e 's/ .*//' -e 's/^[^0-9]*//' \
+                               -e 's/\..*//'`
+fi
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_vers" >&5
+$as_echo "$ac_cv_lbl_gcc_vers" >&6; }
+                   if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+                           V_CCOPT="-O2"
+                   fi
+           fi
+    else
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking that $CC handles ansi prototypes" >&5
+$as_echo_n "checking that $CC handles ansi prototypes... " >&6; }
+           if test "${ac_cv_lbl_cc_ansi_prototypes+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+int frob(int, char *)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_cc_ansi_prototypes=yes
+else
+  ac_cv_lbl_cc_ansi_prototypes=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_ansi_prototypes" >&5
+$as_echo "$ac_cv_lbl_cc_ansi_prototypes" >&6; }
+           if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
+                   case "$host_os" in
+
+                   hpux*)
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
+$as_echo_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)... " >&6; }
+                           savedcflags="$CFLAGS"
+                           CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
+                           if test "${ac_cv_lbl_cc_hpux_cc_aa+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+int frob(int, char *)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_cc_hpux_cc_aa=yes
+else
+  ac_cv_lbl_cc_hpux_cc_aa=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_hpux_cc_aa" >&5
+$as_echo "$ac_cv_lbl_cc_hpux_cc_aa" >&6; }
+                           if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
+                                   as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5
+                           fi
+                           CFLAGS="$savedcflags"
+                           V_CCOPT="-Aa $V_CCOPT"
+
+$as_echo "#define _HPUX_SOURCE 1" >>confdefs.h
+
+                           ;;
+
+                   osf*)
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ansi mode in DEC compiler ($CC -std1)" >&5
+$as_echo_n "checking for ansi mode in DEC compiler ($CC -std1)... " >&6; }
+                           savedcflags="$CFLAGS"
+                           CFLAGS="-std1"
+                           if test "${ac_cv_lbl_cc_osf1_cc_std1+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+int frob(int, char *)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_cc_osf1_cc_std1=yes
+else
+  ac_cv_lbl_cc_osf1_cc_std1=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_osf1_cc_std1" >&5
+$as_echo "$ac_cv_lbl_cc_osf1_cc_std1" >&6; }
+                           if test $ac_cv_lbl_cc_osf1_cc_std1 = no ; then
+                                   as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5
+                           fi
+                           CFLAGS="$savedcflags"
+                           V_CCOPT="-std1 $V_CCOPT"
+                           ;;
+
+                   *)
+                           as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5
+                           ;;
+                   esac
+           fi
+           V_INCLS="$V_INCLS -I/usr/local/include"
+           LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+           case "$host_os" in
+
+           irix*)
+                   V_CCOPT="$V_CCOPT -xansi -signed -g3"
+                   ;;
+
+           osf*)
+                   #
+                   # Presumed to be DEC OSF/1, Digital UNIX, or
+                   # Tru64 UNIX.
+                   #
+                   V_CCOPT="$V_CCOPT -g3"
+                   ;;
+
+           ultrix*)
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking that Ultrix $CC hacks const in prototypes" >&5
+$as_echo_n "checking that Ultrix $CC hacks const in prototypes... " >&6; }
+                   if test "${ac_cv_lbl_cc_const_proto+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+struct a { int b; };
+                           void c(const struct a *)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_cc_const_proto=yes
+else
+  ac_cv_lbl_cc_const_proto=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_const_proto" >&5
+$as_echo "$ac_cv_lbl_cc_const_proto" >&6; }
+                   if test $ac_cv_lbl_cc_const_proto = no ; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+                   fi
+                   ;;
+           esac
+    fi
+
+
+    if test "$GCC" = yes ; then
+           #
+           # On platforms where we build a shared library:
+           #
+           #   add options to generate position-independent code,
+           #   if necessary (it's the default in AIX and Darwin/OS X);
+           #
+           #   define option to set the soname of the shared library,
+           #   if the OS supports that;
+           #
+           #   add options to specify, at link time, a directory to
+           #   add to the run-time search path, if that's necessary.
+           #
+           V_SHLIB_CMD="\$(CC)"
+           V_SHLIB_OPT="-shared"
+           case "$host_os" in
+
+           aix*)
+                   ;;
+
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
+                   #
+                   # Platforms where the linker is the GNU linker
+                   # or accepts command-line arguments like
+                   # those the GNU linker accepts.
+                   #
+                   # Some instruction sets require -fPIC on some
+                   # operating systems.  Check for them.  If you
+                   # have a combination that requires it, add it
+                   # here.
+                   #
+                   PIC_OPT=-fpic
+                   case "$host_cpu" in
+
+                   sparc64*)
+                       case "$host_os" in
+
+                       freebsd*)
+                           PIC_OPT=-fPIC
+                           ;;
+                       esac
+                       ;;
+                   esac
+                   V_CCOPT="$V_CCOPT $PIC_OPT"
+                   V_SONAME_OPT="-Wl,-soname,"
+                   V_RPATH_OPT="-Wl,-rpath,"
+                   ;;
+
+           hpux*)
+                   V_CCOPT="$V_CCOPT -fpic"
+                   #
+                   # XXX - this assumes GCC is using the HP linker,
+                   # rather than the GNU linker, and that the "+h"
+                   # option is used on all HP-UX platforms, both .sl
+                   # and .so.
+                   #
+                   V_SONAME_OPT="-Wl,+h,"
+                   #
+                   # By default, directories specifed with -L
+                   # are added to the run-time search path, so
+                   # we don't add them in pcap-config.
+                   #
+                   ;;
+
+           solaris*)
+                   V_CCOPT="$V_CCOPT -fpic"
+                   #
+                   # XXX - this assumes GCC is using the Sun linker,
+                   # rather than the GNU linker.
+                   #
+                   V_SONAME_OPT="-Wl,-h,"
+                   V_RPATH_OPT="-Wl,-R,"
+                   ;;
+           esac
+    else
+           #
+           # Set the appropriate compiler flags and, on platforms
+           # where we build a shared library:
+           #
+           #   add options to generate position-independent code,
+           #   if necessary (it's the default in Darwin/OS X);
+           #
+           #   if we generate ".so" shared libraries, define the
+           #   appropriate options for building the shared library;
+           #
+           #   add options to specify, at link time, a directory to
+           #   add to the run-time search path, if that's necessary.
+           #
+           # Note: spaces after V_SONAME_OPT are significant; on
+           # some platforms the soname is passed with a GCC-like
+           # "-Wl,-soname,{soname}" option, with the soname part
+           # of the option, while on other platforms the C compiler
+           # driver takes it as a regular option with the soname
+           # following the option.  The same applies to V_RPATH_OPT.
+           #
+           case "$host_os" in
+
+           aix*)
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-G -bnoentry -bexpall"
+                   ;;
+
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*)
+                   #
+                   # "cc" is GCC.
+                   #
+                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-shared"
+                   V_SONAME_OPT="-Wl,-soname,"
+                   V_RPATH_OPT="-Wl,-rpath,"
+                   ;;
+
+           hpux*)
+                   V_CCOPT="$V_CCOPT +z"
+                   V_SHLIB_CMD="\$(LD)"
+                   V_SHLIB_OPT="-b"
+                   V_SONAME_OPT="+h "
+                   #
+                   # By default, directories specifed with -L
+                   # are added to the run-time search path, so
+                   # we don't add them in pcap-config.
+                   #
+                   ;;
+
+           osf*)
+                   #
+                   # Presumed to be DEC OSF/1, Digital UNIX, or
+                   # Tru64 UNIX.
+                   #
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-shared"
+                   V_SONAME_OPT="-soname "
+                   V_RPATH_OPT="-rpath "
+                   ;;
+
+           solaris*)
+                   V_CCOPT="$V_CCOPT -Kpic"
+                   V_SHLIB_CMD="\$(CC)"
+                   V_SHLIB_OPT="-G"
+                   V_SONAME_OPT="-h "
+                   V_RPATH_OPT="-R"
+                   ;;
+           esac
+    fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$V_CCOPT"
+    if test "${ac_cv_lbl_inline+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       ac_cv_lbl_inline=""
+       ac_lbl_cc_inline=no
+       for ac_lbl_inline in inline __inline__ __inline
+       do
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define inline $ac_lbl_inline
+               static inline struct iltest *foo(void);
+               struct iltest {
+                   int iltest1;
+                   int iltest2;
+               };
+
+               static inline struct iltest *
+               foo()
+               {
+                   static struct iltest xxx;
+
+                   return &xxx;
+               }
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lbl_cc_inline=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+           if test "$ac_lbl_cc_inline" = yes ; then
+               break;
+           fi
+       done
+       if test "$ac_lbl_cc_inline" = yes ; then
+           ac_cv_lbl_inline=$ac_lbl_inline
+       fi
+fi
+
+    CFLAGS="$save_CFLAGS"
+    if test ! -z "$ac_cv_lbl_inline" ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_inline" >&5
+$as_echo "$ac_cv_lbl_inline" >&6; }
+    else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+
+cat >>confdefs.h <<_ACEOF
+#define inline $ac_cv_lbl_inline
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5
+$as_echo_n "checking for __attribute__... " >&6; }
+if test "${ac_cv___attribute__+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+
+static void foo(void) __attribute__ ((noreturn));
+
+static void
+foo(void)
+{
+  exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+  foo();
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv___attribute__=yes
+else
+  ac_cv___attribute__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "$ac_cv___attribute__" = "yes"; then
+
+$as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h
+
+  V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\""
+else
+  V_DEFS="$V_DEFS -D_U_=\"\""
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__" >&5
+$as_echo "$ac_cv___attribute__" >&6; }
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in sys/bitypes.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/bitypes.h" "ac_cv_header_sys_bitypes_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_bitypes_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_BITYPES_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_int8_t" = x""yes; then :
+
+else
+
+$as_echo "#define int8_t signed char" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_u_int8_t" = x""yes; then :
+
+else
+
+$as_echo "#define u_int8_t unsigned char" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default"
+if test "x$ac_cv_type_int16_t" = x""yes; then :
+
+else
+
+$as_echo "#define int16_t short" >>confdefs.h
+
+       $ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+fi
+
+ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_u_int16_t" = x""yes; then :
+
+else
+
+$as_echo "#define u_int16_t unsigned short" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_int32_t" = x""yes; then :
+
+else
+
+$as_echo "#define int32_t int" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_u_int32_t" = x""yes; then :
+
+else
+
+$as_echo "#define u_int32_t unsigned int" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_int64_t" = x""yes; then :
+
+else
+
+$as_echo "#define int64_t long long" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+"
+if test "x$ac_cv_type_u_int64_t" = x""yes; then :
+
+else
+
+$as_echo "#define u_int64_t unsigned long long" >>confdefs.h
+
+fi
+
+
+#
+# Try to arrange for large file support.
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h> /* for off_t */
+     #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_sys_largefile_source=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGEFILE_SOURCE 1
+#include <sys/types.h> /* for off_t */
+     #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_sys_largefile_source=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  ac_cv_sys_largefile_source=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
+$as_echo "$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -rf conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
+
+fi
+
+
+for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/types.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_types_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_TYPES_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/if_packet.h netpacket/packet.h netpacket/if_packet.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in net/pfvar.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+"
+if test "x$ac_cv_header_net_pfvar_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PFVAR_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+       #
+       # Check for various PF actions.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
+$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+           #include <sys/socket.h>
+           #include <net/if.h>
+           #include <net/pfvar.h>
+int
+main ()
+{
+return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+for ac_header in netinet/if_ether.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_header_netinet_if_ether_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IF_ETHER_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_netinet_if_ether_h" != yes; then
+       #
+       # The simple test didn't work.
+       # Do we need to include <net/if.h> first?
+       # Unset ac_cv_header_netinet_if_ether_h so we don't
+       # treat the previous failure as a cached value and
+       # suppress the next test.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Rechecking with some additional includes" >&5
+$as_echo "$as_me: Rechecking with some additional includes" >&6;}
+       unset ac_cv_header_netinet_if_ether_h
+       for ac_header in netinet/if_ether.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+"
+if test "x$ac_cv_header_netinet_if_ether_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IF_ETHER_H 1
+_ACEOF
+
+fi
+
+done
+
+fi
+
+if test "$GCC" = yes ; then
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI ioctl definitions" >&5
+$as_echo_n "checking for ANSI ioctl definitions... " >&6; }
+           if test "${ac_cv_lbl_gcc_fixincludes+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/*
+                    * This generates a "duplicate case value" when fixincludes
+                    * has not be run.
+                    */
+#              include <sys/types.h>
+#              include <sys/time.h>
+#              include <sys/ioctl.h>
+#              ifdef HAVE_SYS_IOCCOM_H
+#              include <sys/ioccom.h>
+#              endif
+int
+main ()
+{
+switch (0) {
+                   case _IO('A', 1):;
+                   case _IO('B', 1):;
+                   }
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_gcc_fixincludes=yes
+else
+  ac_cv_lbl_gcc_fixincludes=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_fixincludes" >&5
+$as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; }
+           if test $ac_cv_lbl_gcc_fixincludes = no ; then
+                   # Don't cache failure
+                   unset ac_cv_lbl_gcc_fixincludes
+                   as_fn_error $? "see the INSTALL for more info" "$LINENO" 5
+           fi
+    fi
+
+for ac_func in strerror strlcpy
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+needsnprintf=no
+for ac_func in vsnprintf snprintf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  needsnprintf=yes
+fi
+done
+
+if test $needsnprintf = yes; then
+       case " $LIBOBJS " in
+  *" snprintf.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "gethostbyname() -ish function".
+#
+
+    # Most operating systems have gethostbyname() in the default searched
+    # libraries (i.e. libc):
+    # Some OSes (eg. Solaris) place it in libnsl
+    # Some strange OSes (SINIX) have it in libsocket:
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if test "${ac_cv_search_gethostbyname+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' nsl socket resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_gethostbyname+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_gethostbyname+set}" = set; then :
+
+else
+  ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+    # Unfortunately libsocket sometimes depends on libnsl and
+    # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
+    if test "$ac_cv_search_gethostbyname" = "no"
+    then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5
+$as_echo_n "checking for gethostbyname in -lsocket... " >&6; }
+if test "${ac_cv_lib_socket_gethostbyname+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_gethostbyname=yes
+else
+  ac_cv_lib_socket_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5
+$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; }
+if test "x$ac_cv_lib_socket_gethostbyname" = x""yes; then :
+  LIBS="-lsocket -lnsl $LIBS"
+fi
+
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if test "${ac_cv_search_socket+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_socket+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_socket+set}" = set; then :
+
+else
+  ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+$as_echo_n "checking for socket in -lsocket... " >&6; }
+if test "${ac_cv_lib_socket_socket+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_socket=yes
+else
+  ac_cv_lib_socket_socket=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+$as_echo "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = x""yes; then :
+  LIBS="-lsocket -lnsl $LIBS"
+fi
+
+fi
+
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
+$as_echo_n "checking for library containing putmsg... " >&6; }
+if test "${ac_cv_search_putmsg+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char putmsg ();
+int
+main ()
+{
+return putmsg ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' str; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_putmsg=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_putmsg+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_putmsg+set}" = set; then :
+
+else
+  ac_cv_search_putmsg=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
+$as_echo "$ac_cv_search_putmsg" >&6; }
+ac_res=$ac_cv_search_putmsg
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it, but not declare it in any header file.
+# Some might have it, but declare it in <netinet/if_ether.h>.
+# Some might have it, but declare it in <netinet/ether.h>
+# (And some might have it but document it as something declared in
+# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
+#
+# Before you is a C compiler.
+#
+for ac_func in ether_hostton
+do :
+  ac_fn_c_check_func "$LINENO" "ether_hostton" "ac_cv_func_ether_hostton"
+if test "x$ac_cv_func_ether_hostton" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ETHER_HOSTTON 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ether_hostton" = yes; then
+       #
+       # OK, we have ether_hostton().  Do we have <netinet/if_ether.h>?
+       #
+       if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+               #
+               # Yes.  Does it declare ether_hostton()?
+               #
+               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = x""yes; then :
+
+
+$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/ether.h>, as on Linux?
+               #
+               for ac_header in netinet/ether.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "netinet/ether.h" "ac_cv_header_netinet_ether_h" "$ac_includes_default"
+if test "x$ac_cv_header_netinet_ether_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_ETHER_H 1
+_ACEOF
+
+fi
+
+done
+
+               if test "$ac_cv_header_netinet_ether_h" = yes; then
+                       #
+                       # We have it - does it declare ether_hostton()?
+                       # Unset ac_cv_have_decl_ether_hostton so we don't
+                       # treat the previous failure as a cached value and
+                       # suppress the next test.
+                       #
+                       unset ac_cv_have_decl_ether_hostton
+                       ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <netinet/ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = x""yes; then :
+
+
+$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+               fi
+       fi
+       #
+       # Is ether_hostton() declared?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, we'll have to declare it ourselves.
+               # Do we have "struct ether_addr"?
+               #
+               ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_type_struct_ether_addr" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_ETHER_ADDR 1
+_ACEOF
+
+
+fi
+
+
+$as_echo "#define HAVE_DECL_ETHER_HOSTTON 0" >>confdefs.h
+
+       else
+
+$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
+
+       fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-protochain option is specified" >&5
+$as_echo_n "checking if --disable-protochain option is specified... " >&6; }
+# Check whether --enable-protochain was given.
+if test "${enable_protochain+set}" = set; then :
+  enableval=$enable_protochain;
+fi
+
+case "x$enable_protochain" in
+xyes)  enable_protochain=enabled       ;;
+xno)   enable_protochain=disabled      ;;
+x)     enable_protochain=enabled       ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+
+$as_echo "#define NO_PROTOCHAIN 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_protochain}" >&5
+$as_echo "${enable_protochain}" >&6; }
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+
+# Check whether --with-sita was given.
+if test "${with_sita+set}" = set; then :
+  withval=$with_sita;
+       if test ! "x$withval" = "xno" ; then
+
+$as_echo "#define SITA 1" >>confdefs.h
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5
+$as_echo "$as_me: Enabling SITA ACN support" >&6;}
+               V_PCAP=sita
+               V_FINDALLDEVS=sita
+       fi
+
+else
+
+if test -z "$with_pcap" && test "$cross_compiling" = yes; then
+       as_fn_error $? "pcap type not determined when cross-compiling; use --with-pcap=..." "$LINENO" 5
+fi
+
+# Check whether --with-pcap was given.
+if test "${with_pcap+set}" = set; then :
+  withval=$with_pcap;
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
+$as_echo_n "checking packet capture type... " >&6; }
+if test ! -z "$with_pcap" ; then
+       V_PCAP="$withval"
+elif test -r /dev/bpf -o -h /dev/bpf ; then
+       #
+       # Cloning BPF device.
+       #
+       V_PCAP=bpf
+
+$as_echo "#define HAVE_CLONING_BPF 1" >>confdefs.h
+
+elif test -r /dev/bpf0 ; then
+       V_PCAP=bpf
+elif test -r /usr/include/net/pfilt.h ; then
+       V_PCAP=pf
+elif test -r /dev/enet ; then
+       V_PCAP=enet
+elif test -r /dev/nit ; then
+       V_PCAP=snit
+elif test -r /usr/include/sys/net/nit.h ; then
+       V_PCAP=nit
+elif test -r /usr/include/linux/socket.h ; then
+       V_PCAP=linux
+elif test -r /usr/include/net/raw.h ; then
+       V_PCAP=snoop
+elif test -r /usr/include/odmi.h ; then
+       #
+       # On AIX, the BPF devices might not yet be present - they're
+       # created the first time libpcap runs after booting.
+       # We check for odmi.h instead.
+       #
+       V_PCAP=bpf
+elif test -c /dev/bpf0 ; then          # check again in case not readable
+       V_PCAP=bpf
+elif test -r /usr/include/sys/dlpi.h ; then
+       V_PCAP=dlpi
+elif test -c /dev/enet ; then          # check again in case not readable
+       V_PCAP=enet
+elif test -c /dev/nit ; then           # check again in case not readable
+       V_PCAP=snit
+else
+       V_PCAP=null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
+$as_echo "$V_PCAP" >&6; }
+
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+       #
+       # Checks to see if Solaris has the public libdlpi(3LIB) library.
+       # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+       # public libdlpi(3LIB) version. Before libdlpi was made public, a
+       # private version also existed, which did not have the same APIs.
+       # Due to a gcc bug, the default search path for 32-bit libraries does
+       # not include /lib, we add it explicitly here.
+       # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+       # Also, due to the bug above applications that link to libpcap with
+       # libdlpi will have to add "-L/lib" option to "configure".
+       #
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="$LIBS -L/lib"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
+$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
+if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldlpi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlpi_walk ();
+int
+main ()
+{
+return dlpi_walk ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dlpi_dlpi_walk=yes
+else
+  ac_cv_lib_dlpi_dlpi_walk=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
+$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_walk" = x""yes; then :
+  LIBS="-ldlpi $LIBS"
+               V_PCAP=libdlpi
+
+$as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h
+
+else
+  V_PCAP=dlpi
+fi
+
+       LDFLAGS=$saved_ldflags
+
+       #
+       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+       # versions of DLPI.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <sys/dlpi.h> is usable" >&5
+$as_echo_n "checking whether <sys/dlpi.h> is usable... " >&6; }
+       if test "${ac_cv_sys_dlpi_usable+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+                       #include <sys/types.h>
+                       #include <sys/time.h>
+                       #include <sys/dlpi.h>
+
+int
+main ()
+{
+int i = DL_PROMISC_PHYS;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_dlpi_usable=yes
+else
+  ac_cv_sys_dlpi_usable=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_dlpi_usable" >&5
+$as_echo "$ac_cv_sys_dlpi_usable" >&6; }
+       if test $ac_cv_sys_dlpi_usable = no ; then
+               as_fn_error $? "<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" "$LINENO" 5
+       fi
+
+       #
+       # Check whether we have a /dev/dlpi device or have multiple devices.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/dlpi device" >&5
+$as_echo_n "checking for /dev/dlpi device... " >&6; }
+       if test -c /dev/dlpi ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_DEV_DLPI 1" >>confdefs.h
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               dir="/dev/dlpi"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir directory" >&5
+$as_echo_n "checking for $dir directory... " >&6; }
+               if test -d $dir ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define PCAP_DEV_PREFIX "$dir"
+_ACEOF
+
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               fi
+       fi
+
+       #
+       # This check is for Solaris with DLPI support for passive modes.
+       # See dlpi(7P) for more details.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_passive_req_t struct exists" >&5
+$as_echo_n "checking if dl_passive_req_t struct exists... " >&6; }
+       if test "${ac_cv_lbl_has_dl_passive_req_t+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#       include <sys/types.h>
+#       include <sys/dlpi.h>
+int
+main ()
+{
+u_int i = sizeof(dl_passive_req_t)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_has_dl_passive_req_t=yes
+else
+  ac_cv_lbl_has_dl_passive_req_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_dl_passive_req_t" >&5
+$as_echo "$ac_cv_lbl_has_dl_passive_req_t" >&6; }
+    if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
+
+$as_echo "#define HAVE_DLPI_PASSIVE 1" >>confdefs.h
+
+    fi
+       ;;
+
+linux)
+       #
+       # Do we have the wireless extensions?
+       #
+       for ac_header in linux/wireless.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_wireless_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_WIRELESS_H 1
+_ACEOF
+
+fi
+
+done
+
+
+       #
+       # Do we have libnl?
+       #
+
+# Check whether --with-libnl was given.
+if test "${with_libnl+set}" = set; then :
+  withval=$with_libnl; with_libnl=$withval
+fi
+
+
+       if test x$with_libnl != xno ; then
+               #
+               # Try libnl 2.x first.
+               #
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5
+$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; }
+if test "${ac_cv_lib_nl_nl_socket_alloc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_socket_alloc ();
+int
+main ()
+{
+return nl_socket_alloc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nl_nl_socket_alloc=yes
+else
+  ac_cv_lib_nl_nl_socket_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_socket_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_socket_alloc" = x""yes; then :
+
+                       #
+                       # Yes, we have libnl 2.x.
+                       #
+                       LIBS="-lnl-genl -lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h
+
+
+else
+
+                       #
+                       # No, we don't; do we have libnl 1.x?
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
+$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
+if test "${ac_cv_lib_nl_nl_handle_alloc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_handle_alloc ();
+int
+main ()
+{
+return nl_handle_alloc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nl_nl_handle_alloc=yes
+else
+  ac_cv_lib_nl_nl_handle_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_handle_alloc" = x""yes; then :
+
+                               #
+                               # Yes.
+                               #
+                               LIBS="-lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+
+else
+
+                               #
+                               # No, we don't have libnl at all.
+                               #
+                               if test x$with_libnl = xyes ; then
+                                       as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
+                               fi
+
+fi
+
+
+fi
+
+       fi
+
+       for ac_header in linux/ethtool.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
+$ac_includes_default
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_ethtool_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_ETHTOOL_H 1
+_ACEOF
+
+fi
+
+done
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if if_packet.h has tpacket_stats defined" >&5
+$as_echo_n "checking if if_packet.h has tpacket_stats defined... " >&6; }
+   if test "${ac_cv_lbl_tpacket_stats+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#  include <linux/if_packet.h>
+int
+main ()
+{
+struct tpacket_stats stats
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_tpacket_stats=yes
+else
+  ac_cv_lbl_tpacket_stats=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_tpacket_stats" >&5
+$as_echo "$ac_cv_lbl_tpacket_stats" >&6; }
+   if test $ac_cv_lbl_tpacket_stats = yes; then
+
+$as_echo "#define HAVE_TPACKET_STATS 1" >>confdefs.h
+
+   fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if tpacket_auxdata struct has tp_vlan_tci member" >&5
+$as_echo_n "checking if tpacket_auxdata struct has tp_vlan_tci member... " >&6; }
+    if test "${ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#      include <sys/types.h>
+#      include <linux/if_packet.h>
+int
+main ()
+{
+u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes
+else
+  ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&5
+$as_echo "$ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&6; }
+    if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then
+           HAVE_LINUX_TPACKET_AUXDATA=tp_vlan_tci
+
+
+$as_echo "#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1" >>confdefs.h
+
+    fi
+       ;;
+
+bpf)
+       #
+       # Check whether we have the *BSD-style ioctls.
+       #
+       for ac_header in net/if_media.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/if_media.h" "ac_cv_header_net_if_media_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_media_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_MEDIA_H 1
+_ACEOF
+
+fi
+
+done
+
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the system supports zerocopy BPF" >&5
+$as_echo_n "checking whether the system supports zerocopy BPF... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/socket.h>
+           #include <sys/ioctl.h>
+           #include <net/if.h>
+           #include <net/bpf.h>
+int
+main ()
+{
+return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_ZEROCOPY_BPF 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+           #
+           # Check whether we have struct BPF_TIMEVAL.
+           #
+           ac_fn_c_check_type "$LINENO" "struct BPF_TIMEVAL" "ac_cv_type_struct_BPF_TIMEVAL" "
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+
+"
+if test "x$ac_cv_type_struct_BPF_TIMEVAL" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_BPF_TIMEVAL 1
+_ACEOF
+
+
+fi
+
+       ;;
+
+dag)
+       V_DEFS="$V_DEFS -DDAG_ONLY"
+       ;;
+
+septel)
+       V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+       ;;
+
+snf)
+       V_DEFS="$V_DEFS -DSNF_ONLY"
+       ;;
+
+null)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine packet capture interface" >&5
+$as_echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: (see the INSTALL doc for more info)" >&5
+$as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
+       ;;
+esac
+
+if test "$V_PCAP" = null
+then
+       #
+       # We can't capture, so we can't open any capture
+       # devices, so we won't return any interfaces.
+       #
+       V_FINDALLDEVS=null
+else
+       ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = x""yes; then :
+
+               #
+               # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+               # as well, just in case some platform is really weird.
+               #
+               ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ifaddrs_h" = x""yes; then :
+
+                   #
+                   # We have the header, so we use "getifaddrs()" to
+                   # get the list of interfaces.
+                   #
+                   V_FINDALLDEVS=getad
+
+else
+
+                   #
+                   # We don't have the header - give up.
+                   # XXX - we could also fall back on some other
+                   # mechanism, but, for now, this'll catch this
+                   # problem so that we can at least try to figure
+                   # out something to do on systems with "getifaddrs()"
+                   # but without "ifaddrs.h", if there is something
+                   # we can do on those systems.
+                   #
+                   as_fn_error $? "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." "$LINENO" 5
+
+fi
+
+
+
+else
+
+               #
+               # Well, we don't have "getifaddrs()", so we have to use
+               # some other mechanism; determine what that mechanism is.
+               #
+               # The first thing we use is the type of capture mechanism,
+               # which is somewhat of a proxy for the OS we're using.
+               #
+               case "$V_PCAP" in
+
+               dlpi|libdlpi)
+                       for ac_header in sys/bufmod.h sys/dlpi_ext.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+                       #
+                       # This might be Solaris 8 or later, with
+                       # SIOCGLIFCONF, or it might be some other OS
+                       # or some older version of Solaris, with
+                       # just SIOCGIFCONF.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have SIOCGLIFCONF" >&5
+$as_echo_n "checking whether we have SIOCGLIFCONF... " >&6; }
+                       if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/param.h>
+                               #include <sys/file.h>
+                               #include <sys/ioctl.h>
+                               #include <sys/socket.h>
+                               #include <sys/sockio.h>
+int
+main ()
+{
+ioctl(0, SIOCGLIFCONF, (char *)0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_have_siocglifconf=yes
+else
+  ac_cv_lbl_have_siocglifconf=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
+$as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
+                       if test $ac_cv_lbl_have_siocglifconf = yes ; then
+                               V_FINDALLDEVS=glifc
+                       else
+                               V_FINDALLDEVS=gifc
+                       fi
+                       #
+                       # Needed for common functions used by pcap-[dlpi,libdlpi].c
+                       #
+                       SSRC="dlpisubs.c"
+                       ;;
+
+               *)
+                       #
+                       # Assume we just have SIOCGIFCONF.
+                       # (XXX - on at least later Linux kernels, there's
+                       # another mechanism, and we should be using that
+                       # instead.)
+                       #
+                       V_FINDALLDEVS=gifc
+                       ;;
+               esac
+fi
+
+fi
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
+$as_echo_n "checking for socklen_t... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+       #include <sys/types.h>
+       #include <sys/socket.h>
+
+int
+main ()
+{
+ socklen_t x;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_socklen_t=yes
+else
+  have_socklen_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x$have_socklen_t" = "xyes"; then
+
+$as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_socklen_t" >&5
+$as_echo "$have_socklen_t" >&6; }
+
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+  enableval=$enable_ipv6;
+else
+  enable_ipv6=ifavailable
+fi
+
+if test "$enable_ipv6" != "no"; then
+       ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
+if test "x$ac_cv_func_getaddrinfo" = x""yes; then :
+
+
+$as_echo "#define INET6 1" >>confdefs.h
+
+
+else
+
+               if test "$enable_ipv6" != "ifavailable"; then
+                       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--enable-ipv6 was given, but getaddrinfo isn't available
+See \`config.log' for more details" "$LINENO" 5 ; }
+               fi
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build optimizer debugging code" >&5
+$as_echo_n "checking whether to build optimizer debugging code... " >&6; }
+# Check whether --enable-optimizer-dbg was given.
+if test "${enable_optimizer_dbg+set}" = set; then :
+  enableval=$enable_optimizer_dbg;
+fi
+
+if test "$enable_optimizer_dbg" = "yes"; then
+
+$as_echo "#define BDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_optimizer_dbg-no}" >&5
+$as_echo "${enable_optimizer_dbg-no}" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build parser debugging code" >&5
+$as_echo_n "checking whether to build parser debugging code... " >&6; }
+# Check whether --enable-yydebug was given.
+if test "${enable_yydebug+set}" = set; then :
+  enableval=$enable_yydebug;
+fi
+
+if test "$enable_yydebug" = "yes"; then
+
+$as_echo "#define YYDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
+$as_echo "${enable_yydebug-no}" >&6; }
+
+# Check for Endace DAG card support.
+
+# Check whether --with-dag was given.
+if test "${with_dag+set}" = set; then :
+  withval=$with_dag;
+       if test "$withval" = no
+       then
+               # User doesn't want DAG support.
+               want_dag=no
+       elif test "$withval" = yes
+       then
+               # User wants DAG support but hasn't specified a directory.
+               want_dag=yes
+       else
+               # User wants DAG support and has specified a directory, so use the provided value.
+               want_dag=yes
+               dag_root=$withval
+       fi
+
+else
+
+       #
+       # Use DAG API if present, otherwise don't
+       #
+       want_dag=ifpresent
+
+fi
+
+
+
+# Check whether --with-dag-includes was given.
+if test "${with_dag_includes+set}" = set; then :
+  withval=$with_dag_includes;
+       # User wants DAG support and has specified a header directory, so use the provided value.
+       want_dag=yes
+       dag_include_dir=$withval
+
+fi
+
+
+
+# Check whether --with-dag-libraries was given.
+if test "${with_dag_libraries+set}" = set; then :
+  withval=$with_dag_libraries;
+       # User wants DAG support and has specified a library directory, so use the provided value.
+       want_dag=yes
+       dag_lib_dir=$withval
+
+fi
+
+
+case "$V_PCAP" in
+linux|bpf|dag)
+       #
+       # We support the DAG API if we're on Linux or BSD, or if we're
+       # building a DAG-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested DAG, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_dag = yes; then
+               as_fn_error $? "DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" "$LINENO" 5
+       elif test $want_dag = yes; then
+               want_dag=no
+       fi
+       ;;
+esac
+
+ac_cv_lbl_dag_api=no
+if test "$want_dag" != no; then
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have DAG API headers" >&5
+$as_echo_n "checking whether we have DAG API headers... " >&6; }
+
+       # If necessary, set default paths for DAG API headers and libraries.
+       if test -z "$dag_root"; then
+           dag_root=/usr/local
+       fi
+
+       if test -z "$dag_include_dir"; then
+               dag_include_dir="$dag_root/include"
+       fi
+
+       if test -z "$dag_lib_dir"; then
+           dag_lib_dir="$dag_root/lib"
+       fi
+
+       if test -z "$dag_tools_dir"; then
+           dag_tools_dir="$dag_root/tools"
+       fi
+
+       if test -r $dag_include_dir/dagapi.h; then
+               ac_cv_lbl_dag_api=yes
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5
+$as_echo "$ac_cv_lbl_dag_api ($dag_include_dir)" >&6; }
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+       V_INCLS="$V_INCLS -I$dag_include_dir"
+
+       if test $V_PCAP != dag ; then
+                SSRC="pcap-dag.c"
+       fi
+
+       # See if we can find a general version string.
+       # Don't need to save and restore LIBS to prevent -ldag being
+       # included if there's a found-action (arg 3).
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="-L$dag_lib_dir"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
+$as_echo_n "checking for dag_attach_stream in -ldag... " >&6; }
+if test "${ac_cv_lib_dag_dag_attach_stream+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_attach_stream ();
+int
+main ()
+{
+return dag_attach_stream ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_attach_stream=yes
+else
+  ac_cv_lib_dag_dag_attach_stream=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_attach_stream" >&5
+$as_echo "$ac_cv_lib_dag_dag_attach_stream" >&6; }
+if test "x$ac_cv_lib_dag_dag_attach_stream" = x""yes; then :
+  dag_streams="1"
+else
+  dag_streams="0"
+fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
+$as_echo_n "checking for dag_get_erf_types in -ldag... " >&6; }
+if test "${ac_cv_lib_dag_dag_get_erf_types+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_get_erf_types ();
+int
+main ()
+{
+return dag_get_erf_types ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_get_erf_types=yes
+else
+  ac_cv_lib_dag_dag_get_erf_types=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_erf_types" = x""yes; then :
+
+
+$as_echo "#define HAVE_DAG_GET_ERF_TYPES 1" >>confdefs.h
+
+fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
+$as_echo_n "checking for dag_get_stream_erf_types in -ldag... " >&6; }
+if test "${ac_cv_lib_dag_dag_get_stream_erf_types+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_get_stream_erf_types ();
+int
+main ()
+{
+return dag_get_stream_erf_types ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_get_stream_erf_types=yes
+else
+  ac_cv_lib_dag_dag_get_stream_erf_types=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_stream_erf_types" = x""yes; then :
+
+
+$as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h
+
+fi
+
+
+       LDFLAGS=$saved_ldflags
+
+       if test "$dag_streams" = 1; then
+
+$as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h
+
+               LIBS="$LIBS -ldag"
+               LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
+$as_echo_n "checking for vdag_set_device_info in -lvdag... " >&6; }
+if test "${ac_cv_lib_vdag_vdag_set_device_info+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lvdag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char vdag_set_device_info ();
+int
+main ()
+{
+return vdag_set_device_info ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_vdag_vdag_set_device_info=yes
+else
+  ac_cv_lib_vdag_vdag_set_device_info=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vdag_vdag_set_device_info" >&5
+$as_echo "$ac_cv_lib_vdag_vdag_set_device_info" >&6; }
+if test "x$ac_cv_lib_vdag_vdag_set_device_info" = x""yes; then :
+  ac_dag_have_vdag="1"
+else
+  ac_dag_have_vdag="0"
+fi
+
+               if test "$ac_dag_have_vdag" = 1; then
+
+$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
+
+                       LIBS="$LIBS -lpthread"
+               fi
+       fi
+
+
+$as_echo "#define HAVE_DAG_API 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have the DAG API" >&5
+$as_echo_n "checking whether we have the DAG API... " >&6; }
+
+if test $ac_cv_lbl_dag_api = no; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       if test "$want_dag" = yes; then
+               # User wanted DAG support but we couldn't find it.
+               as_fn_error $? "DAG API requested, but not found at $dag_root: use --without-dag" "$LINENO" 5
+       fi
+
+       if test "$V_PCAP" = dag; then
+               # User requested "dag" capture type but the DAG API wasn't
+               # found.
+               as_fn_error $? "Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" "$LINENO" 5
+       fi
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+
+
+# Check whether --with-septel was given.
+if test "${with_septel+set}" = set; then :
+  withval=$with_septel;
+       if test "$withval" = no
+       then
+               want_septel=no
+       elif test "$withval" = yes
+       then
+               want_septel=yes
+               septel_root=
+       else
+               want_septel=yes
+               septel_root=$withval
+       fi
+
+else
+
+       #
+       # Use Septel API if present, otherwise don't
+       #
+       want_septel=ifpresent
+       septel_root=./../septel
+
+fi
+
+ac_cv_lbl_septel_api=no
+case "$V_PCAP" in
+linux|septel)
+       #
+       # We support the Septel API if we're on Linux, or if we're building
+       # a Septel-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested Septel, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_septel = yes; then
+               as_fn_error $? "Septel support only available with 'linux' and 'septel' packet capture types" "$LINENO" 5
+       elif test $want_septel = yes; then
+               want_septel=no
+       fi
+       ;;
+esac
+
+if test "$with_septel" != no; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API" >&5
+$as_echo_n "checking whether we have Septel API... " >&6; }
+
+       if test -z "$septel_root"; then
+               septel_root=$srcdir/../septel
+       fi
+
+       septel_tools_dir="$septel_root"
+       septel_include_dir="$septel_root/INC"
+
+       ac_cv_lbl_septel_api=no
+       if test -r "$septel_include_dir/msg.h"; then
+               V_INCLS="$V_INCLS -I$septel_include_dir"
+               ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+               ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+
+               if test "$V_PCAP" != septel ; then
+                        SSRC="pcap-septel.c"
+               fi
+               ac_cv_lbl_septel_api=yes
+       fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_septel_api" >&5
+$as_echo "$ac_cv_lbl_septel_api" >&6; }
+       if test $ac_cv_lbl_septel_api = no; then
+               if test "$want_septel" = yes; then
+                       as_fn_error $? "Septel API not found under directory $septel_root; use --without-septel" "$LINENO" 5
+               fi
+       else
+
+$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
+
+       fi
+fi
+
+if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
+       as_fn_error $? "Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" "$LINENO" 5
+fi
+
+# Check for Myricom SNF support.
+
+# Check whether --with-snf was given.
+if test "${with_snf+set}" = set; then :
+  withval=$with_snf;
+       if test "$withval" = no
+       then
+               # User explicitly doesn't want SNF
+               want_snf=no
+       elif test "$withval" = yes
+       then
+               # User wants SNF support but hasn't specific a directory.
+               want_snf=yes
+       else
+               # User wants SNF support with a specified directory.
+               want_snf=yes
+               snf_root=$withval
+       fi
+
+else
+
+       #
+       # Use Sniffer API if present, otherwise don't
+       #
+       want_snf=ifpresent
+
+fi
+
+
+
+# Check whether --with-snf-includes was given.
+if test "${with_snf_includes+set}" = set; then :
+  withval=$with_snf_includes;
+       # User wants SNF with specific header directory
+       want_snf=yes
+       snf_include_dir=$withval
+
+fi
+
+
+
+# Check whether --with-snf-libraries was given.
+if test "${with_snf_libraries+set}" = set; then :
+  withval=$with_snf_libraries;
+       # User wants SNF with specific lib directory
+       want_snf=yes
+       snf_lib_dir=$withval
+
+fi
+
+
+case "$V_PCAP" in
+bpf|linux|snf)
+       #
+       # We support the Sniffer API if we're on BSD, Linux, or if we're
+       # building a Sniffer-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested Sniffer, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_snf = yes; then
+               as_fn_error $? "Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" "$LINENO" 5
+       elif test $want_snf = yes; then
+               want_snf=no
+       fi
+       ;;
+esac
+
+ac_cv_lbl_snf_api=no
+if test "$with_snf" != no; then
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Myricom Sniffer API" >&5
+$as_echo_n "checking whether we have Myricom Sniffer API... " >&6; }
+
+       if test -z "$snf_root"; then
+               snf_root=/opt/snf
+       fi
+
+       if test -z "$snf_include_dir"; then
+               snf_include_dir="$snf_root/include"
+       fi
+
+       if test -z "$snf_lib_dir"; then
+               snf_lib_dir="$snf_root/lib"
+       fi
+
+       if test -f "$snf_include_dir/snf.h"; then
+               ac_cv_lbl_snf_api=yes
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_snf_api ($snf_root)" >&5
+$as_echo "$ac_cv_lbl_snf_api ($snf_root)" >&6; }
+
+       if test $ac_cv_lbl_snf_api = no; then
+               if test "$want_snf" = yes; then
+                       as_fn_error $? "SNF API headers not found under $snf_include_dir; use --without-snf" "$LINENO" 5
+               fi
+       else
+               saved_ldflags=$LDFLAGS
+               LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
+$as_echo_n "checking for snf_init in -lsnf... " >&6; }
+if test "${ac_cv_lib_snf_snf_init+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnf  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char snf_init ();
+int
+main ()
+{
+return snf_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_snf_snf_init=yes
+else
+  ac_cv_lib_snf_snf_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_snf_snf_init" >&5
+$as_echo "$ac_cv_lib_snf_snf_init" >&6; }
+if test "x$ac_cv_lib_snf_snf_init" = x""yes; then :
+  ac_cv_lbl_snf_api="yes"
+else
+  ac_cv_lbl_snf_api="no"
+fi
+
+               LDFLAGS="$saved_ldflags"
+
+               if test $ac_cv_lbl_snf_api = no; then
+                       if test "$want_snf" = yes; then
+                               as_fn_error $? "SNF API cannot correctly be linked check config.log; use --without-snf" "$LINENO" 5
+                       fi
+               else
+                       V_INCLS="$V_INCLS -I$snf_include_dir"
+                       LIBS="$LIBS -lsnf"
+                       LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+                       if test "$V_PCAP" != snf ; then
+                               SSRC="pcap-snf.c"
+                       fi
+
+$as_echo "#define HAVE_SNF_API 1" >>confdefs.h
+
+               fi
+       fi
+fi
+
+if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
+       as_fn_error $? "Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" "$LINENO" 5
+fi
+
+
+# Check whether --with-flex was given.
+if test "${with_flex+set}" = set; then :
+  withval=$with_flex;
+fi
+
+
+# Check whether --with-bison was given.
+if test "${with_bison+set}" = set; then :
+  withval=$with_bison;
+fi
+
+    if test "$with_flex" = no ; then
+           V_LEX=lex
+    else
+           for ac_prog in flex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_V_LEX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$V_LEX"; then
+  ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_V_LEX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+V_LEX=$ac_cv_prog_V_LEX
+if test -n "$V_LEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_LEX" >&5
+$as_echo "$V_LEX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$V_LEX" && break
+done
+test -n "$V_LEX" || V_LEX="lex"
+
+    fi
+    if test "$V_LEX" = flex ; then
+           # The -V flag was added in 2.4
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flex 2.4 or higher" >&5
+$as_echo_n "checking for flex 2.4 or higher... " >&6; }
+           if test "${ac_cv_lbl_flex_v24+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if flex -V >/dev/null 2>&1; then
+                       ac_cv_lbl_flex_v24=yes
+               else
+                       ac_cv_lbl_flex_v24=no
+               fi
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_flex_v24" >&5
+$as_echo "$ac_cv_lbl_flex_v24" >&6; }
+           if test $ac_cv_lbl_flex_v24 = no ; then
+                   s="2.4 or higher required"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ignoring obsolete flex executable ($s)" >&5
+$as_echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;}
+                   V_LEX=lex
+           fi
+    fi
+    if test "$with_bison" = no ; then
+           V_YACC=yacc
+    else
+           for ac_prog in bison
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_V_YACC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$V_YACC"; then
+  ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_V_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+V_YACC=$ac_cv_prog_V_YACC
+if test -n "$V_YACC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_YACC" >&5
+$as_echo "$V_YACC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$V_YACC" && break
+done
+test -n "$V_YACC" || V_YACC="yacc"
+
+    fi
+    if test "$V_YACC" = bison ; then
+           V_YACC="$V_YACC -y"
+    fi
+    if test "$V_LEX" != lex -a "$V_YACC" = yacc -o "$V_LEX" = lex -a "$V_YACC" != yacc ; then
+           { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5
+$as_echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&2;}
+           V_LEX=lex
+           V_YACC=yacc
+    fi
+    if test "$V_LEX" = flex -a -n "pcap_" ; then
+           V_LEX="$V_LEX -Ppcap_"
+           V_YACC="$V_YACC -p pcap_"
+    fi
+if test "$V_LEX" = lex ; then
+# Some versions of lex can't handle the definitions section of scanner.l .
+# Try lexing it and complain if it can't deal.
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
+$as_echo_n "checking for capable lex... " >&6; }
+if test "${tcpdump_cv_capable_lex+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if lex -t scanner.l > /dev/null 2>&1; then
+                       tcpdump_cv_capable_lex=yes
+               else
+                       tcpdump_cv_capable_lex=insufficient
+               fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5
+$as_echo "$tcpdump_cv_capable_lex" >&6; }
+       if test $tcpdump_cv_capable_lex = insufficient ; then
+               as_fn_error $? "Your operating system's lex is insufficient to compile
+ libpcap.  flex is a lex replacement that has many advantages, including
+ being able to compile libpcap.  For more information, see
+ http://www.gnu.org/software/flex/flex.html ." "$LINENO" 5
+       fi
+fi
+
+#
+# Assume, by default, no support for shared libraries and V7/BSD convention
+# for man pages (file formats in section 5, miscellaneous info in section 7).
+# Individual cases can override this.
+#
+DYEXT="none"
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+case "$host_os" in
+
+aix*)
+
+$as_echo "#define _SUN 1" >>confdefs.h
+
+
+       #
+       # AIX makes it fun to build shared and static libraries,
+       # because they're *both* ".a" archive libraries.  We
+       # build the static library for the benefit of the traditional
+       # scheme of building libpcap and tcpdump in subdirectories of
+       # the same directory, with tcpdump statically linked with the
+       # libpcap in question, but we also build a shared library as
+       # "libpcap.shareda" and install *it*, rather than the static
+       # library, as "libpcap.a".
+       #
+       DYEXT="shareda"
+
+       case "$V_PCAP" in
+
+       dlpi)
+               #
+               # If we're using DLPI, applications will need to
+               # use /lib/pse.exp if present, as we use the
+               # STREAMS routines.
+               #
+               pseexe="/lib/pse.exp"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
+$as_echo_n "checking for $pseexe... " >&6; }
+               if test -f $pseexe ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       LIBS="-I:$pseexe"
+               fi
+               ;;
+
+       bpf)
+               #
+               # If we're using BPF, we need "-lodm" and "-lcfg", as
+               # we use them to load the BPF module.
+               #
+               LIBS="-lodm -lcfg"
+               ;;
+       esac
+       ;;
+
+darwin*)
+       DYEXT="dylib"
+       V_CCOPT="$V_CCOPT -fno-common"
+       # Check whether --enable-universal was given.
+if test "${enable_universal+set}" = set; then :
+  enableval=$enable_universal;
+fi
+
+       if test "$enable_universal" != "no"; then
+               case "$host_os" in
+
+               darwin9.*)
+                       #
+                       # Leopard.  Build for 32-bit PowerPC, 64-bit
+                       # PowerPC, x86, and x86-64, with 32-bit PowerPC
+                       # first.  (That's what Apple does.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       ;;
+
+               darwin10.*)
+                       #
+                       # Snow Leopard.  Build for x86-64, x86, and
+                       # 32-bit PowerPC, with x86-64 first.  (That's
+                       # what Apple does, even though Snow Leopard
+                       # doesn't run on PPC, so PPC libpcap runs under
+                       # Rosetta, and Rosetta doesn't support BPF
+                       # ioctls, so PPC programs can't do live
+                       # captures.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
+                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
+                       ;;
+
+               darwin11.*)
+                       #
+                       # Lion.  Build for x86-64 and x86, with x86-64
+                       # first.  (That's probably what Apple does,
+                       # given that Rosetta is gone.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
+                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
+                       ;;
+               esac
+       fi
+       ;;
+
+hpux9*)
+
+$as_echo "#define HAVE_HPUX9 1" >>confdefs.h
+
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.0*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.1*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux*)
+
+$as_echo "#define HAVE_HPUX10_20_OR_LATER 1" >>confdefs.h
+
+       if test "`uname -m`" = "ia64"; then
+               DYEXT="so"
+       else
+               DYEXT="sl"
+       fi
+
+       #
+       # "-b" builds a shared library; "+h" sets the soname.
+       #
+       SHLIB_OPT="-b"
+       SONAME_OPT="+h"
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+irix*)
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
+       DYEXT="so"
+
+       #
+       # Compiler assumed to be GCC; run-time linker may require a -R
+       # flag.
+       #
+       if test "$libdir" != "/usr/lib"; then
+               V_RFLAGS=-Wl,-R$libdir
+       fi
+       ;;
+
+osf*)
+       DYEXT="so"
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+sinix*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SINIX compiler defines sinix" >&5
+$as_echo_n "checking if SINIX compiler defines sinix... " >&6; }
+       if test "${ac_cv_cc_sinix_defined+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int i = sinix;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_cc_sinix_defined=yes
+else
+  ac_cv_cc_sinix_defined=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_sinix_defined" >&5
+$as_echo "$ac_cv_cc_sinix_defined" >&6; }
+           if test $ac_cv_cc_sinix_defined = no ; then
+
+$as_echo "#define sinix 1" >>confdefs.h
+
+           fi
+       ;;
+
+solaris*)
+
+$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h
+
+
+       DYEXT="so"
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+esac
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+
+rm -f os-proto.h
+    if test "${LBL_CFLAGS+set}" = set; then
+           V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
+    fi
+    if test -f .devel ; then
+           if test "$GCC" = yes ; then
+                   if test "${LBL_CFLAGS+set}" != set; then
+                           if test "$ac_cv_prog_cc_g" = yes ; then
+                                   V_CCOPT="-g $V_CCOPT"
+                           fi
+                           V_CCOPT="$V_CCOPT -Wall"
+                           if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+                                   V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+                           fi
+                   fi
+           else
+                   case "$host_os" in
+
+                   irix6*)
+                           V_CCOPT="$V_CCOPT -n32"
+                           ;;
+
+                   *)
+                           ;;
+                   esac
+           fi
+           os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
+           name="lbl/os-$os.h"
+           if test -f $name ; then
+                   ln -s $name os-proto.h
+
+$as_echo "#define HAVE_OS_PROTO_H 1" >>confdefs.h
+
+           else
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5
+$as_echo "$as_me: WARNING: can't find $name" >&2;}
+           fi
+    fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr struct has the sa_len member" >&5
+$as_echo_n "checking if sockaddr struct has the sa_len member... " >&6; }
+    if test "${ac_cv_lbl_sockaddr_has_sa_len+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#      include <sys/types.h>
+#      include <sys/socket.h>
+int
+main ()
+{
+u_int i = sizeof(((struct sockaddr *)0)->sa_len)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_sockaddr_has_sa_len=yes
+else
+  ac_cv_lbl_sockaddr_has_sa_len=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5
+$as_echo "$ac_cv_lbl_sockaddr_has_sa_len" >&6; }
+    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
+
+$as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h
+
+    fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_storage struct exists" >&5
+$as_echo_n "checking if sockaddr_storage struct exists... " >&6; }
+    if test "${ac_cv_lbl_has_sockaddr_storage+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#      include <sys/types.h>
+#      include <sys/socket.h>
+int
+main ()
+{
+u_int i = sizeof (struct sockaddr_storage)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_has_sockaddr_storage=yes
+else
+  ac_cv_lbl_has_sockaddr_storage=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_sockaddr_storage" >&5
+$as_echo "$ac_cv_lbl_has_sockaddr_storage" >&6; }
+    if test $ac_cv_lbl_has_sockaddr_storage = yes ; then
+
+$as_echo "#define HAVE_SOCKADDR_STORAGE 1" >>confdefs.h
+
+    fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5
+$as_echo_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member... " >&6; }
+    if test "${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#      include <sys/types.h>
+#      include <sys/dlpi.h>
+#      include <sys/dlpi_ext.h>
+int
+main ()
+{
+u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes
+else
+  ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&5
+$as_echo "$ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&6; }
+    if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then
+
+$as_echo "#define HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1" >>confdefs.h
+
+    fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5
+$as_echo_n "checking if unaligned accesses fail... " >&6; }
+    if test "${ac_cv_lbl_unaligned_fail+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case "$host_cpu" in
+
+       #
+       # These are CPU types where:
+       #
+       #       the CPU faults on an unaligned access, but at least some
+       #       OSes that support that CPU catch the fault and simulate
+       #       the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
+       #       the simulation is slow, so we don't want to use it;
+       #
+       #       the CPU, I infer (from the old
+       #
+       # XXX: should also check that they don't do weird things (like on arm)
+       #
+       #       comment) doesn't fault on unaligned accesses, but doesn't
+       #       do a normal unaligned fetch, either (e.g., presumably, ARM);
+       #
+       #       for whatever reason, the test program doesn't work
+       #       (this has been claimed to be the case for several of those
+       #       CPUs - I don't know what the problem is; the problem
+       #       was reported as "the test program dumps core" for SuperH,
+       #       but that's what the test program is *supposed* to do -
+       #       it dumps core before it writes anything, so the test
+       #       for an empty output file should find an empty output
+       #       file and conclude that unaligned accesses don't work).
+       #
+       # This run-time test won't work if you're cross-compiling, so
+       # in order to support cross-compiling for a particular CPU,
+       # we have to wire in the list of CPU types anyway, as far as
+       # I know, so perhaps we should just have a set of CPUs on
+       # which we know it doesn't work, a set of CPUs on which we
+       # know it does work, and have the script just fail on other
+       # cpu types and update it when such a failure occurs.
+       #
+       alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
+               ac_cv_lbl_unaligned_fail=yes
+               ;;
+
+       *)
+               cat >conftest.c <<EOF
+#              include <sys/types.h>
+#              include <sys/wait.h>
+#              include <stdio.h>
+               unsigned char a[5] = { 1, 2, 3, 4, 5 };
+               main() {
+               unsigned int i;
+               pid_t pid;
+               int status;
+               /* avoid "core dumped" message */
+               pid = fork();
+               if (pid <  0)
+                       exit(2);
+               if (pid > 0) {
+                       /* parent */
+                       pid = waitpid(pid, &status, 0);
+                       if (pid < 0)
+                               exit(3);
+                       exit(!WIFEXITED(status));
+               }
+               /* child */
+               i = *(unsigned int *)&a[1];
+               printf("%d\n", i);
+               exit(0);
+               }
+EOF
+               ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
+                   conftest.c $LIBS >/dev/null 2>&1
+               if test ! -x conftest ; then
+                                               ac_cv_lbl_unaligned_fail=yes
+               else
+                       ./conftest >conftest.out
+                       if test ! -s conftest.out ; then
+                               ac_cv_lbl_unaligned_fail=yes
+                       else
+                               ac_cv_lbl_unaligned_fail=no
+                       fi
+               fi
+               rm -f -r conftest* core core.conftest
+               ;;
+       esac
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5
+$as_echo "$ac_cv_lbl_unaligned_fail" >&6; }
+    if test $ac_cv_lbl_unaligned_fail = yes ; then
+
+$as_echo "#define LBL_ALIGN 1" >>confdefs.h
+
+    fi
+
+#
+# Makefile.in includes rules to generate version.h, so we assume
+# that it will be generated if autoconf is used.
+#
+
+$as_echo "#define HAVE_VERSION_H 1" >>confdefs.h
+
+
+rm -f net
+ln -s ${srcdir}/bpf/net net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
+$as_echo_n "checking for USB sniffing support... " >&6; }
+case "$host_os" in
+linux*)
+
+$as_echo "#define PCAP_SUPPORT_USB 1" >>confdefs.h
+
+       USB_SRC=pcap-usb-linux.c
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+       if test $? -ne 0 ; then
+         ac_usb_dev_name="usbmon"
+       fi
+
+cat >>confdefs.h <<_ACEOF
+#define LINUX_USB_MON_DEV "/dev/$ac_usb_dev_name"
+_ACEOF
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5
+$as_echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;}
+       #
+       # Do we have a version of <linux/compiler.h> available?
+       # If so, we might need it for <linux/usbdevice_fs.h>.
+       #
+       for ac_header in linux/compiler.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/compiler.h" "ac_cv_header_linux_compiler_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_compiler_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_COMPILER_H 1
+_ACEOF
+
+fi
+
+done
+
+       if test "$ac_cv_header_linux_compiler_h" = yes; then
+         #
+         # Yes - include it when testing for <linux/usbdevice_fs.h>.
+         #
+         for ac_header in linux/usbdevice_fs.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "#include <linux/compiler.h>
+"
+if test "x$ac_cv_header_linux_usbdevice_fs_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_USBDEVICE_FS_H 1
+_ACEOF
+
+fi
+
+done
+
+       else
+         for ac_header in linux/usbdevice_fs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_usbdevice_fs_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_USBDEVICE_FS_H 1
+_ACEOF
+
+fi
+
+done
+
+       fi
+       if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+         #
+         # OK, does it define bRequestType?  Older versions of the kernel
+         # define fields with names like "requesttype, "request", and
+         # "value", rather than "bRequestType", "bRequest", and
+         # "wValue".
+         #
+         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if usbdevfs_ctrltransfer struct has bRequestType member" >&5
+$as_echo_n "checking if usbdevfs_ctrltransfer struct has bRequestType member... " >&6; }
+         if test "${ac_cv_usbdevfs_ctrltransfer_has_bRequestType+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+$ac_includes_default
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/usbdevice_fs.h>
+int
+main ()
+{
+u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes
+else
+  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&5
+$as_echo "$ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&6; }
+           if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then
+
+$as_echo "#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1" >>confdefs.h
+
+           fi
+       fi
+       ;;
+*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       ;;
+esac
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
+$as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; }
+case "$host_os" in
+linux*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       #
+       # Life's too short to deal with trying to get this to compile
+       # if you don't get the right types defined with
+       # __KERNEL_STRICT_NAMES getting defined by some other include.
+       #
+       # Check whether the includes Just Work.  If not, don't turn on
+       # netfilter support.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
+$as_echo_n "checking whether we can compile the netfilter support... " >&6; }
+       if test "${ac_cv_netfilter_can_compile+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+$ac_includes_default
+#include <sys/socket.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_netfilter_can_compile=yes
+else
+  ac_cv_netfilter_can_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
+$as_echo "$ac_cv_netfilter_can_compile" >&6; }
+       if test $ac_cv_netfilter_can_compile = yes ; then
+
+$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
+
+         NETFILTER_SRC=pcap-netfilter-linux.c
+       fi
+       ;;
+*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       ;;
+esac
+
+
+
+# Check whether --enable-bluetooth was given.
+if test "${enable_bluetooth+set}" = set; then :
+  enableval=$enable_bluetooth;
+else
+  enable_bluetooth=yes
+fi
+
+
+if test "x$enable_bluetooth" != "xno" ; then
+               case "$host_os" in
+       linux*)
+               ac_fn_c_check_header_mongrel "$LINENO" "bluetooth/bluetooth.h" "ac_cv_header_bluetooth_bluetooth_h" "$ac_includes_default"
+if test "x$ac_cv_header_bluetooth_bluetooth_h" = x""yes; then :
+
+
+$as_echo "#define PCAP_SUPPORT_BT 1" >>confdefs.h
+
+                 BT_SRC=pcap-bt-linux.c
+                 { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5
+$as_echo "$as_me: Bluetooth sniffing is supported" >&6;}
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
+$as_echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
+
+fi
+
+
+               ;;
+       *)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: no Bluetooth sniffing support implemented for $host_os" >&5
+$as_echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;}
+               ;;
+       esac
+
+
+fi
+
+# Check whether --enable-canusb was given.
+if test "${enable_canusb+set}" = set; then :
+  enableval=$enable_canusb; enable_canusb=yes
+fi
+
+
+if test "x$enable_canusb" != "xno" ; then
+               case "$host_os" in
+       linux*)
+               ac_fn_c_check_header_mongrel "$LINENO" "libusb-1.0/libusb.h" "ac_cv_header_libusb_1_0_libusb_h" "$ac_includes_default"
+if test "x$ac_cv_header_libusb_1_0_libusb_h" = x""yes; then :
+
+
+$as_echo "#define PCAP_SUPPORT_CANUSB 1" >>confdefs.h
+
+                   CANUSB_SRC=pcap-canusb-linux.c
+                   LIBS="-lusb-1.0 $LIBS"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is supported" >&5
+$as_echo "$as_me: canusb sniffing is supported" >&6;}
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&5
+$as_echo "$as_me: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&6;}
+
+fi
+
+
+               ;;
+       *)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: no canusb support implemented for $host_os" >&5
+$as_echo "$as_me: no canusb support implemented for $host_os" >&6;}
+               ;;
+       esac
+
+
+fi
+
+# Check whether --enable-can was given.
+if test "${enable_can+set}" = set; then :
+  enableval=$enable_can;
+else
+  enable_can=yes
+fi
+
+
+if test "x$enable_can" != "xno" ; then
+               case "$host_os" in
+       linux*)
+               ac_fn_c_check_header_compile "$LINENO" "linux/can.h" "ac_cv_header_linux_can_h" "#include <sys/socket.h>
+
+"
+if test "x$ac_cv_header_linux_can_h" = x""yes; then :
+
+$as_echo "#define PCAP_SUPPORT_CAN 1" >>confdefs.h
+
+                       CAN_SRC=pcap-can-linux.c
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is supported" >&5
+$as_echo "$as_me: CAN sniffing is supported" >&6;}
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is not supported" >&5
+$as_echo "$as_me: CAN sniffing is not supported" >&6;}
+fi
+
+
+               ;;
+       *)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: no CAN sniffing support implemented for $host_os" >&5
+$as_echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;}
+               ;;
+       esac
+
+
+fi
+
+case "$host_os" in
+linux*)
+       for ac_header in linux/net_tstamp.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_net_tstamp_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_NET_TSTAMP_H 1
+_ACEOF
+
+fi
+
+done
+
+       ;;
+*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: no hardware timestamp support implemented for $host_os" >&5
+$as_echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;}
+       ;;
+esac
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_tstamp_type.3pcap"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.67.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.67,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;;
+    "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;;
+    "pcap-tstamp.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-tstamp.manmisc" ;;
+    "pcap-savefile.manfile") CONFIG_FILES="$CONFIG_FILES pcap-savefile.manfile" ;;
+    "pcap.3pcap") CONFIG_FILES="$CONFIG_FILES pcap.3pcap" ;;
+    "pcap_compile.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_compile.3pcap" ;;
+    "pcap_datalink.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_datalink.3pcap" ;;
+    "pcap_dump_open.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_dump_open.3pcap" ;;
+    "pcap_list_datalinks.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_datalinks.3pcap" ;;
+    "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;;
+    "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
+    "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
+    "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=[    ]*/{
+h
+s///
+s/^/:/
+s/[     ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[  ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5  ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+if test -f .devel ; then
+       make depend
+fi
+exit 0
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..8432d2a
--- /dev/null
@@ -0,0 +1,1471 @@
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.168 2008-12-23 20:49:26 guy Exp $ (LBL)
+dnl
+dnl Copyright (c) 1994, 1995, 1996, 1997
+dnl    The Regents of the University of California.  All rights reserved.
+dnl
+dnl Process this file with autoconf to produce a configure script.
+dnl
+
+#
+# See
+#
+#      http://ftp.gnu.org/gnu/config/README
+#
+# for the URLs to use to fetch new versions of config.guess and
+# config.sub.
+#
+
+AC_REVISION($Revision: 1.168 $)
+AC_PREREQ(2.50)
+AC_INIT(pcap.c)
+
+AC_CANONICAL_SYSTEM
+
+AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS)
+AC_PROG_CC
+AC_LBL_C_INIT(V_CCOPT, V_INCLS)
+AC_LBL_SHLIBS_INIT
+AC_LBL_C_INLINE
+AC_C___ATTRIBUTE__
+
+AC_CHECK_HEADERS(sys/bitypes.h)
+
+AC_CHECK_TYPE([int8_t], ,
+       [AC_DEFINE([int8_t], [signed char],
+       [Define to `signed char' if int8_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([u_int8_t], ,
+       [AC_DEFINE([u_int8_t], [unsigned char],
+       [Define to `unsigned char' if u_int8_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([int16_t], ,
+       [AC_DEFINE([int16_t], [short],
+       [Define to `short' if int16_t not defined.])]
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([u_int16_t], ,
+       [AC_DEFINE([u_int16_t], [unsigned short],
+       [Define to `unsigned short' if u_int16_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([int32_t], ,
+       [AC_DEFINE([int32_t], [int],
+       [Define to `int' if int32_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([u_int32_t], ,
+       [AC_DEFINE([u_int32_t], [unsigned int],
+       [Define to `unsigned int' if u_int32_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([int64_t], ,
+       [AC_DEFINE([int64_t], [long long],
+       [Define to `long long' if int64_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+AC_CHECK_TYPE([u_int64_t], ,
+       [AC_DEFINE([u_int64_t], [unsigned long long],
+       [Define to `unsigned long long' if u_int64_t not defined.])],
+       [AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif])
+
+#
+# Try to arrange for large file support.
+#
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+dnl
+dnl Even if <net/bpf.h> were, on all OSes that support BPF, fixed to
+dnl include <sys/ioccom.h>, and we were to drop support for older
+dnl releases without that fix, so that pcap-bpf.c doesn't need to
+dnl include <sys/ioccom.h>, the test program in "AC_LBL_FIXINCLUDES"
+dnl in "aclocal.m4" uses it, so we would still have to test for it
+dnl and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise
+dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris.
+dnl
+AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h)
+AC_CHECK_HEADERS(linux/types.h)
+AC_CHECK_HEADERS(linux/if_packet.h netpacket/packet.h netpacket/if_packet.h)
+AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>])
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+       #
+       # Check for various PF actions.
+       #
+       AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
+       AC_TRY_COMPILE(
+           [#include <sys/types.h>
+           #include <sys/socket.h>
+           #include <net/if.h>
+           #include <net/pfvar.h>],
+           [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
+           [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
+                   [define if net/pfvar.h defines PF_NAT through PF_NORDR])
+           ],
+           AC_MSG_RESULT(no))
+fi
+AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
+#include <sys/socket.h>])
+if test "$ac_cv_header_netinet_if_ether_h" != yes; then
+       #
+       # The simple test didn't work.
+       # Do we need to include <net/if.h> first?
+       # Unset ac_cv_header_netinet_if_ether_h so we don't
+       # treat the previous failure as a cached value and
+       # suppress the next test.
+       #
+       AC_MSG_NOTICE([Rechecking with some additional includes])
+       unset ac_cv_header_netinet_if_ether_h
+       AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>])
+fi
+
+AC_LBL_FIXINCLUDES
+
+AC_CHECK_FUNCS(strerror strlcpy)
+
+needsnprintf=no
+AC_CHECK_FUNCS(vsnprintf snprintf,,
+       [needsnprintf=yes])
+if test $needsnprintf = yes; then
+       AC_LIBOBJ([snprintf])
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "gethostbyname() -ish function".
+#
+AC_LBL_LIBRARY_NET
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it, but not declare it in any header file.
+# Some might have it, but declare it in <netinet/if_ether.h>.
+# Some might have it, but declare it in <netinet/ether.h>
+# (And some might have it but document it as something declared in
+# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
+#
+# Before you is a C compiler.
+#
+AC_CHECK_FUNCS(ether_hostton)
+if test "$ac_cv_func_ether_hostton" = yes; then
+       #
+       # OK, we have ether_hostton().  Do we have <netinet/if_ether.h>?
+       #
+       if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+               #
+               # Yes.  Does it declare ether_hostton()?
+               #
+               AC_CHECK_DECL(ether_hostton,
+                   [
+                       AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,,
+                           [Define to 1 if netinet/if_ether.h declares `ether_hostton'])
+                   ],,
+                   [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+                   ])
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/ether.h>, as on Linux?
+               #
+               AC_CHECK_HEADERS(netinet/ether.h)
+               if test "$ac_cv_header_netinet_ether_h" = yes; then
+                       #
+                       # We have it - does it declare ether_hostton()?
+                       # Unset ac_cv_have_decl_ether_hostton so we don't
+                       # treat the previous failure as a cached value and
+                       # suppress the next test.
+                       #
+                       unset ac_cv_have_decl_ether_hostton
+                       AC_CHECK_DECL(ether_hostton,
+                           [
+                               AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,,
+                                   [Define to 1 if netinet/ether.h declares `ether_hostton'])
+                           ],,
+                           [
+#include <netinet/ether.h>
+                           ])
+               fi
+       fi
+       #
+       # Is ether_hostton() declared?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, we'll have to declare it ourselves.
+               # Do we have "struct ether_addr"?
+               #
+               AC_CHECK_TYPES(struct ether_addr,,,
+                   [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+                   ])
+               AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 0,
+                   [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
+don't.])
+       else
+               AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1,
+                   [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
+don't.])
+       fi
+fi
+
+dnl to pacify those who hate protochain insn
+AC_MSG_CHECKING(if --disable-protochain option is specified)
+AC_ARG_ENABLE(protochain,
+AC_HELP_STRING([--disable-protochain],[disable \"protochain\" insn]))
+case "x$enable_protochain" in
+xyes)  enable_protochain=enabled       ;;
+xno)   enable_protochain=disabled      ;;
+x)     enable_protochain=enabled       ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+       AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain])
+fi
+AC_MSG_RESULT(${enable_protochain})
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+AC_ARG_WITH(sita,
+AC_HELP_STRING([--with-sita],[include SITA support]),
+[
+       if test ! "x$withval" = "xno" ; then
+               AC_DEFINE(SITA,1,[include ACN support])
+               AC_MSG_NOTICE(Enabling SITA ACN support)
+               V_PCAP=sita
+               V_FINDALLDEVS=sita
+       fi
+],
+[
+dnl
+dnl Not all versions of test support -c (character special) but it's a
+dnl better way of testing since the device might be protected. So we
+dnl check in our normal order using -r and then check the for the /dev
+dnl guys again using -c.
+dnl
+dnl XXX This could be done for cross-compiling, but for now it's not.
+dnl
+if test -z "$with_pcap" && test "$cross_compiling" = yes; then
+       AC_MSG_ERROR(pcap type not determined when cross-compiling; use --with-pcap=...)
+fi
+AC_ARG_WITH(pcap,
+AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
+AC_MSG_CHECKING(packet capture type)
+if test ! -z "$with_pcap" ; then
+       V_PCAP="$withval"
+elif test -r /dev/bpf -o -h /dev/bpf ; then
+       #
+       # Cloning BPF device.
+       #
+       V_PCAP=bpf
+       AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device])
+elif test -r /dev/bpf0 ; then
+       V_PCAP=bpf
+elif test -r /usr/include/net/pfilt.h ; then
+       V_PCAP=pf
+elif test -r /dev/enet ; then
+       V_PCAP=enet
+elif test -r /dev/nit ; then
+       V_PCAP=snit
+elif test -r /usr/include/sys/net/nit.h ; then
+       V_PCAP=nit
+elif test -r /usr/include/linux/socket.h ; then
+       V_PCAP=linux
+elif test -r /usr/include/net/raw.h ; then
+       V_PCAP=snoop
+elif test -r /usr/include/odmi.h ; then
+       #
+       # On AIX, the BPF devices might not yet be present - they're
+       # created the first time libpcap runs after booting.
+       # We check for odmi.h instead.
+       #
+       V_PCAP=bpf
+elif test -c /dev/bpf0 ; then          # check again in case not readable
+       V_PCAP=bpf
+elif test -r /usr/include/sys/dlpi.h ; then
+       V_PCAP=dlpi
+elif test -c /dev/enet ; then          # check again in case not readable
+       V_PCAP=enet
+elif test -c /dev/nit ; then           # check again in case not readable
+       V_PCAP=snit
+else
+       V_PCAP=null
+fi
+AC_MSG_RESULT($V_PCAP)
+
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+       #
+       # Checks to see if Solaris has the public libdlpi(3LIB) library.
+       # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+       # public libdlpi(3LIB) version. Before libdlpi was made public, a 
+       # private version also existed, which did not have the same APIs. 
+       # Due to a gcc bug, the default search path for 32-bit libraries does
+       # not include /lib, we add it explicitly here.
+       # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485]. 
+       # Also, due to the bug above applications that link to libpcap with
+       # libdlpi will have to add "-L/lib" option to "configure".
+       #
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="$LIBS -L/lib"
+       AC_CHECK_LIB(dlpi, dlpi_walk,
+               LIBS="-ldlpi $LIBS"
+               V_PCAP=libdlpi
+               AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists]),
+               V_PCAP=dlpi)
+       LDFLAGS=$saved_ldflags
+
+       #
+       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+       # versions of DLPI.
+       #
+       AC_MSG_CHECKING(whether <sys/dlpi.h> is usable)
+       AC_CACHE_VAL(ac_cv_sys_dlpi_usable,
+               AC_TRY_COMPILE(
+                   [
+                       #include <sys/types.h>
+                       #include <sys/time.h>
+                       #include <sys/dlpi.h>
+                   ],
+                   [int i = DL_PROMISC_PHYS;],
+                   ac_cv_sys_dlpi_usable=yes,
+                   ac_cv_sys_dlpi_usable=no))
+       AC_MSG_RESULT($ac_cv_sys_dlpi_usable)
+       if test $ac_cv_sys_dlpi_usable = no ; then
+               AC_MSG_ERROR(<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI)
+       fi
+
+       #
+       # Check whether we have a /dev/dlpi device or have multiple devices.
+       #
+       AC_MSG_CHECKING(for /dev/dlpi device)
+       if test -c /dev/dlpi ; then
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DEV_DLPI, 1, [define if you have a /dev/dlpi])
+       else
+               AC_MSG_RESULT(no)
+               dir="/dev/dlpi"
+               AC_MSG_CHECKING(for $dir directory)
+               if test -d $dir ; then
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir", [/dev/dlpi directory])
+               else
+                       AC_MSG_RESULT(no)
+               fi
+       fi
+
+       #
+       # This check is for Solaris with DLPI support for passive modes.
+       # See dlpi(7P) for more details.
+       #
+       AC_LBL_DL_PASSIVE_REQ_T
+       ;;
+
+linux)
+       #
+       # Do we have the wireless extensions?
+       #
+       AC_CHECK_HEADERS(linux/wireless.h, [], [],
+       [
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/types.h>
+       ])
+
+       #
+       # Do we have libnl?
+       #
+       AC_ARG_WITH(libnl,
+       AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
+               with_libnl=$withval,,)
+
+       if test x$with_libnl != xno ; then
+               #
+               # Try libnl 2.x first.
+               #
+               AC_CHECK_LIB(nl, nl_socket_alloc,
+               [
+                       #
+                       # Yes, we have libnl 2.x.
+                       #
+                       LIBS="-lnl-genl -lnl $LIBS"
+                       AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+                       AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
+               ],
+               [
+                       #
+                       # No, we don't; do we have libnl 1.x?
+                       #
+                       AC_CHECK_LIB(nl, nl_handle_alloc,
+                       [
+                               #
+                               # Yes.
+                               #
+                               LIBS="-lnl $LIBS"
+                               AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+                       ],
+                       [
+                               #
+                               # No, we don't have libnl at all.
+                               #
+                               if test x$with_libnl = xyes ; then
+                                       AC_MSG_ERROR([libnl support requested but libnl not found])
+                               fi
+                       ])
+               ])
+       fi
+
+       AC_CHECK_HEADERS(linux/ethtool.h,,,
+           [
+AC_INCLUDES_DEFAULT
+#include <linux/types.h>
+           ])
+       AC_LBL_TPACKET_STATS
+       AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+       ;;
+
+bpf)
+       #
+       # Check whether we have the *BSD-style ioctls.
+       #
+       AC_CHECK_HEADERS(net/if_media.h)
+
+       AC_MSG_CHECKING(whether the system supports zerocopy BPF)
+       AC_TRY_COMPILE(
+           [#include <sys/socket.h>
+           #include <sys/ioctl.h>
+           #include <net/if.h>
+           #include <net/bpf.h>],
+           [return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);],
+           [  
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_ZEROCOPY_BPF, 1,
+               [define if the system supports zerocopy BPF])
+           ],
+           AC_MSG_RESULT(no))
+
+           #
+           # Check whether we have struct BPF_TIMEVAL.
+           #
+           AC_CHECK_TYPES(struct BPF_TIMEVAL,,,
+               [
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+                   ])
+       ;;
+
+dag)
+       V_DEFS="$V_DEFS -DDAG_ONLY"
+       ;;
+
+septel)
+       V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+       ;;
+
+snf)
+       V_DEFS="$V_DEFS -DSNF_ONLY"
+       ;;
+
+null)
+       AC_MSG_WARN(cannot determine packet capture interface)
+       AC_MSG_WARN((see the INSTALL doc for more info))
+       ;;
+esac
+
+dnl
+dnl Now figure out how we get a list of interfaces and addresses,
+dnl if we support capturing.  Don't bother if we don't support
+dnl capturing.
+dnl
+if test "$V_PCAP" = null
+then
+       #
+       # We can't capture, so we can't open any capture
+       # devices, so we won't return any interfaces.
+       #
+       V_FINDALLDEVS=null
+else
+       AC_CHECK_FUNC(getifaddrs,[
+               #
+               # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+               # as well, just in case some platform is really weird.
+               #
+               AC_CHECK_HEADER(ifaddrs.h,[
+                   #
+                   # We have the header, so we use "getifaddrs()" to
+                   # get the list of interfaces.
+                   #
+                   V_FINDALLDEVS=getad
+               ],[
+                   #
+                   # We don't have the header - give up.
+                   # XXX - we could also fall back on some other
+                   # mechanism, but, for now, this'll catch this
+                   # problem so that we can at least try to figure
+                   # out something to do on systems with "getifaddrs()"
+                   # but without "ifaddrs.h", if there is something
+                   # we can do on those systems.
+                   #
+                   AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.])
+               ])
+       ],[
+               #
+               # Well, we don't have "getifaddrs()", so we have to use
+               # some other mechanism; determine what that mechanism is.
+               #
+               # The first thing we use is the type of capture mechanism,
+               # which is somewhat of a proxy for the OS we're using.
+               #
+               case "$V_PCAP" in
+
+               dlpi|libdlpi)
+                       AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
+                       #
+                       # This might be Solaris 8 or later, with
+                       # SIOCGLIFCONF, or it might be some other OS
+                       # or some older version of Solaris, with
+                       # just SIOCGIFCONF.
+                       #
+                       AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
+                       AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
+                           AC_TRY_COMPILE(
+                               [#include <sys/param.h>
+                               #include <sys/file.h>
+                               #include <sys/ioctl.h>
+                               #include <sys/socket.h>
+                               #include <sys/sockio.h>],
+                               [ioctl(0, SIOCGLIFCONF, (char *)0);],
+                               ac_cv_lbl_have_siocglifconf=yes,
+                               ac_cv_lbl_have_siocglifconf=no))
+                       AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
+                       if test $ac_cv_lbl_have_siocglifconf = yes ; then
+                               V_FINDALLDEVS=glifc
+                       else
+                               V_FINDALLDEVS=gifc
+                       fi
+                       #
+                       # Needed for common functions used by pcap-[dlpi,libdlpi].c
+                       #
+                       SSRC="dlpisubs.c"
+                       ;;
+
+               *)
+                       #
+                       # Assume we just have SIOCGIFCONF.
+                       # (XXX - on at least later Linux kernels, there's
+                       # another mechanism, and we should be using that
+                       # instead.)
+                       #
+                       V_FINDALLDEVS=gifc
+                       ;;
+               esac])
+fi
+])
+
+AC_MSG_CHECKING(for socklen_t)
+AC_TRY_COMPILE([
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       ],
+       [ socklen_t x; ],
+       have_socklen_t=yes,
+       have_socklen_t=no)
+if test "x$have_socklen_t" = "xyes"; then
+       AC_DEFINE(HAVE_SOCKLEN_T, 1, [define if socklen_t is defined])
+fi
+AC_MSG_RESULT($have_socklen_t)
+
+AC_ARG_ENABLE(ipv6,
+AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes, if getaddrinfo available@:>@]),
+    [],
+    [enable_ipv6=ifavailable])
+if test "$enable_ipv6" != "no"; then
+       AC_CHECK_FUNC(getaddrinfo,
+           [
+               AC_DEFINE(INET6,1,[IPv6])
+           ],
+           [
+               if test "$enable_ipv6" != "ifavailable"; then
+                       AC_MSG_FAILURE([--enable-ipv6 was given, but getaddrinfo isn't available])
+               fi
+           ])
+fi
+
+AC_MSG_CHECKING(whether to build optimizer debugging code)
+AC_ARG_ENABLE(optimizer-dbg,
+AC_HELP_STRING([--enable-optimizer-dbg],[build optimizer debugging code]))
+if test "$enable_optimizer_dbg" = "yes"; then
+       AC_DEFINE(BDEBUG,1,[Enable optimizer debugging])
+fi
+AC_MSG_RESULT(${enable_optimizer_dbg-no})
+
+AC_MSG_CHECKING(whether to build parser debugging code)
+AC_ARG_ENABLE(yydebug,
+AC_HELP_STRING([--enable-yydebug],[build parser debugging code]))
+if test "$enable_yydebug" = "yes"; then
+       AC_DEFINE(YYDEBUG,1,[Enable parser debugging])
+fi
+AC_MSG_RESULT(${enable_yydebug-no})
+
+# Check for Endace DAG card support.
+AC_ARG_WITH([dag],
+AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+[
+       if test "$withval" = no
+       then
+               # User doesn't want DAG support.
+               want_dag=no
+       elif test "$withval" = yes
+       then
+               # User wants DAG support but hasn't specified a directory.
+               want_dag=yes
+       else
+               # User wants DAG support and has specified a directory, so use the provided value.
+               want_dag=yes
+               dag_root=$withval
+       fi
+],[
+       #
+       # Use DAG API if present, otherwise don't
+       #
+       want_dag=ifpresent
+])
+
+AC_ARG_WITH([dag-includes],
+AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]),
+[
+       # User wants DAG support and has specified a header directory, so use the provided value.
+       want_dag=yes
+       dag_include_dir=$withval
+],[])
+
+AC_ARG_WITH([dag-libraries],
+AC_HELP_STRING([--with-dag-libraries=DIR],[Endace DAG library directory]),
+[
+       # User wants DAG support and has specified a library directory, so use the provided value.
+       want_dag=yes
+       dag_lib_dir=$withval
+],[])
+
+case "$V_PCAP" in
+linux|bpf|dag)
+       #
+       # We support the DAG API if we're on Linux or BSD, or if we're
+       # building a DAG-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested DAG, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_dag = yes; then
+               AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types])
+       elif test $want_dag = yes; then
+               want_dag=no
+       fi
+       ;;
+esac
+
+ac_cv_lbl_dag_api=no
+if test "$want_dag" != no; then
+
+       AC_MSG_CHECKING([whether we have DAG API headers])
+
+       # If necessary, set default paths for DAG API headers and libraries.
+       if test -z "$dag_root"; then
+           dag_root=/usr/local
+       fi
+
+       if test -z "$dag_include_dir"; then
+               dag_include_dir="$dag_root/include"
+       fi
+
+       if test -z "$dag_lib_dir"; then
+           dag_lib_dir="$dag_root/lib"
+       fi
+       
+       if test -z "$dag_tools_dir"; then
+           dag_tools_dir="$dag_root/tools"
+       fi
+
+       if test -r $dag_include_dir/dagapi.h; then
+               ac_cv_lbl_dag_api=yes
+       fi
+       AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)])
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+       V_INCLS="$V_INCLS -I$dag_include_dir"
+
+       if test $V_PCAP != dag ; then
+                SSRC="pcap-dag.c"
+       fi
+
+       # See if we can find a general version string.
+       # Don't need to save and restore LIBS to prevent -ldag being
+       # included if there's a found-action (arg 3).
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="-L$dag_lib_dir"
+       AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
+       AC_CHECK_LIB([dag],[dag_get_erf_types], [
+               AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
+       AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
+               AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
+
+       LDFLAGS=$saved_ldflags
+
+       if test "$dag_streams" = 1; then
+               AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
+               LIBS="$LIBS -ldag"
+               LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+               
+               AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"])
+               if test "$ac_dag_have_vdag" = 1; then
+                       AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()])
+                       LIBS="$LIBS -lpthread"
+               fi
+       fi
+
+       AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+fi
+
+AC_MSG_CHECKING(whether we have the DAG API)
+
+if test $ac_cv_lbl_dag_api = no; then
+       AC_MSG_RESULT(no)
+       if test "$want_dag" = yes; then
+               # User wanted DAG support but we couldn't find it.
+               AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag])
+       fi
+
+       if test "$V_PCAP" = dag; then
+               # User requested "dag" capture type but the DAG API wasn't
+               # found.
+               AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)])
+       fi
+else
+       AC_MSG_RESULT(yes)
+fi
+
+AC_ARG_WITH(septel,
+AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied).  @<:@default=yes, on Linux, if present@:>@]),
+[
+       if test "$withval" = no
+       then
+               want_septel=no
+       elif test "$withval" = yes
+       then
+               want_septel=yes
+               septel_root=
+       else
+               want_septel=yes
+               septel_root=$withval
+       fi
+],[
+       #
+       # Use Septel API if present, otherwise don't
+       #
+       want_septel=ifpresent
+       septel_root=./../septel
+])
+ac_cv_lbl_septel_api=no
+case "$V_PCAP" in
+linux|septel)
+       #
+       # We support the Septel API if we're on Linux, or if we're building
+       # a Septel-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested Septel, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_septel = yes; then
+               AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types)
+       elif test $want_septel = yes; then
+               want_septel=no
+       fi
+       ;;
+esac
+
+if test "$with_septel" != no; then
+       AC_MSG_CHECKING(whether we have Septel API)
+
+       if test -z "$septel_root"; then
+               septel_root=$srcdir/../septel
+       fi
+
+       septel_tools_dir="$septel_root"
+       septel_include_dir="$septel_root/INC"
+
+       ac_cv_lbl_septel_api=no
+       if test -r "$septel_include_dir/msg.h"; then
+               V_INCLS="$V_INCLS -I$septel_include_dir"
+               ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+               ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+
+               if test "$V_PCAP" != septel ; then
+                        SSRC="pcap-septel.c"
+               fi
+               ac_cv_lbl_septel_api=yes
+       fi
+
+       AC_MSG_RESULT($ac_cv_lbl_septel_api)
+       if test $ac_cv_lbl_septel_api = no; then
+               if test "$want_septel" = yes; then
+                       AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel)
+               fi
+       else
+               AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API])
+       fi
+fi
+
+if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
+       AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR)
+fi
+
+# Check for Myricom SNF support.
+AC_ARG_WITH([snf],
+AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+[
+       if test "$withval" = no
+       then
+               # User explicitly doesn't want SNF
+               want_snf=no
+       elif test "$withval" = yes
+       then
+               # User wants SNF support but hasn't specific a directory.
+               want_snf=yes
+       else
+               # User wants SNF support with a specified directory.
+               want_snf=yes
+               snf_root=$withval
+       fi
+],[
+       #
+       # Use Sniffer API if present, otherwise don't
+       #
+       want_snf=ifpresent
+])
+
+AC_ARG_WITH([snf-includes],
+AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]),
+[
+       # User wants SNF with specific header directory
+       want_snf=yes
+       snf_include_dir=$withval
+],[])
+
+AC_ARG_WITH([snf-libraries],
+AC_HELP_STRING([--with-snf-libraries=DIR],[Myricom SNF library directory]),
+[
+       # User wants SNF with specific lib directory
+       want_snf=yes
+       snf_lib_dir=$withval
+],[])
+
+case "$V_PCAP" in
+bpf|linux|snf)
+       #
+       # We support the Sniffer API if we're on BSD, Linux, or if we're
+       # building a Sniffer-only libpcap.
+       #
+       ;;
+*)
+       #
+       # If the user explicitly requested Sniffer, tell them it's not
+       # supported.
+       #
+       # If they expressed no preference, don't include it.
+       #
+       if test $want_snf = yes; then
+               AC_MSG_ERROR(Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types)
+       elif test $want_snf = yes; then
+               want_snf=no
+       fi
+       ;;
+esac
+
+ac_cv_lbl_snf_api=no
+if test "$with_snf" != no; then
+
+       AC_MSG_CHECKING(whether we have Myricom Sniffer API)
+
+       if test -z "$snf_root"; then
+               snf_root=/opt/snf
+       fi
+
+       if test -z "$snf_include_dir"; then
+               snf_include_dir="$snf_root/include"
+       fi
+
+       if test -z "$snf_lib_dir"; then
+               snf_lib_dir="$snf_root/lib"
+       fi
+
+       if test -f "$snf_include_dir/snf.h"; then
+               ac_cv_lbl_snf_api=yes
+       fi
+       AC_MSG_RESULT([$ac_cv_lbl_snf_api ($snf_root)])
+
+       if test $ac_cv_lbl_snf_api = no; then
+               if test "$want_snf" = yes; then
+                       AC_MSG_ERROR(SNF API headers not found under $snf_include_dir; use --without-snf)
+               fi
+       else
+               saved_ldflags=$LDFLAGS
+               LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+               AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"], [ac_cv_lbl_snf_api="no"])
+               LDFLAGS="$saved_ldflags"
+
+               if test $ac_cv_lbl_snf_api = no; then
+                       if test "$want_snf" = yes; then
+                               AC_MSG_ERROR(SNF API cannot correctly be linked check config.log; use --without-snf)
+                       fi
+               else
+                       V_INCLS="$V_INCLS -I$snf_include_dir"
+                       LIBS="$LIBS -lsnf"
+                       LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+                       if test "$V_PCAP" != snf ; then
+                               SSRC="pcap-snf.c"
+                       fi
+                       AC_DEFINE(HAVE_SNF_API, 1, [define if you have Myricom SNF API])
+               fi
+       fi
+fi
+
+if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
+       AC_MSG_ERROR(Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR)
+fi
+
+AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_)
+if test "$V_LEX" = lex ; then
+# Some versions of lex can't handle the definitions section of scanner.l .
+# Try lexing it and complain if it can't deal.
+       AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
+               if lex -t scanner.l > /dev/null 2>&1; then
+                       tcpdump_cv_capable_lex=yes
+               else
+                       tcpdump_cv_capable_lex=insufficient
+               fi)
+       if test $tcpdump_cv_capable_lex = insufficient ; then
+               AC_MSG_ERROR([Your operating system's lex is insufficient to compile
+ libpcap.  flex is a lex replacement that has many advantages, including
+ being able to compile libpcap.  For more information, see
+ http://www.gnu.org/software/flex/flex.html .])
+       fi
+fi
+
+#
+# Assume, by default, no support for shared libraries and V7/BSD convention
+# for man pages (file formats in section 5, miscellaneous info in section 7).
+# Individual cases can override this.
+#
+DYEXT="none"
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+case "$host_os" in
+
+aix*)
+       dnl Workaround to enable certain features
+       AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
+
+       #
+       # AIX makes it fun to build shared and static libraries,
+       # because they're *both* ".a" archive libraries.  We
+       # build the static library for the benefit of the traditional
+       # scheme of building libpcap and tcpdump in subdirectories of
+       # the same directory, with tcpdump statically linked with the
+       # libpcap in question, but we also build a shared library as
+       # "libpcap.shareda" and install *it*, rather than the static
+       # library, as "libpcap.a".
+       #
+       DYEXT="shareda"
+
+       case "$V_PCAP" in
+
+       dlpi)
+               #
+               # If we're using DLPI, applications will need to
+               # use /lib/pse.exp if present, as we use the
+               # STREAMS routines.
+               #
+               pseexe="/lib/pse.exp"
+               AC_MSG_CHECKING(for $pseexe)
+               if test -f $pseexe ; then
+                       AC_MSG_RESULT(yes)
+                       LIBS="-I:$pseexe"
+               fi
+               ;;
+
+       bpf)
+               #
+               # If we're using BPF, we need "-lodm" and "-lcfg", as
+               # we use them to load the BPF module.
+               #
+               LIBS="-lodm -lcfg"
+               ;;
+       esac
+       ;;
+
+darwin*)
+       DYEXT="dylib"
+       V_CCOPT="$V_CCOPT -fno-common"
+       AC_ARG_ENABLE(universal,
+       AC_HELP_STRING([--disable-universal],[don't build universal on OS X]))
+       if test "$enable_universal" != "no"; then
+               case "$host_os" in
+
+               darwin9.*)
+                       #
+                       # Leopard.  Build for 32-bit PowerPC, 64-bit
+                       # PowerPC, x86, and x86-64, with 32-bit PowerPC
+                       # first.  (That's what Apple does.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       ;;
+
+               darwin10.*)
+                       #
+                       # Snow Leopard.  Build for x86-64, x86, and
+                       # 32-bit PowerPC, with x86-64 first.  (That's
+                       # what Apple does, even though Snow Leopard
+                       # doesn't run on PPC, so PPC libpcap runs under
+                       # Rosetta, and Rosetta doesn't support BPF
+                       # ioctls, so PPC programs can't do live
+                       # captures.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
+                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
+                       ;;
+
+               darwin11.*)
+                       #
+                       # Lion.  Build for x86-64 and x86, with x86-64
+                       # first.  (That's probably what Apple does,
+                       # given that Rosetta is gone.)
+                       #
+                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
+                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
+                       ;;
+               esac
+       fi
+       ;;
+
+hpux9*)
+       AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x])
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.0*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.1*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux*)
+       dnl HPUX 10.20 and above is similar to HPUX 9, but
+       dnl not the same....
+       dnl
+       dnl XXX - DYEXT should be set to "sl" if this is building
+       dnl for 32-bit PA-RISC, but should be left as "so" for
+       dnl 64-bit PA-RISC or, I suspect, IA-64.
+       AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later])
+       if test "`uname -m`" = "ia64"; then
+               DYEXT="so"
+       else
+               DYEXT="sl"
+       fi
+
+       #
+       # "-b" builds a shared library; "+h" sets the soname.
+       #
+       SHLIB_OPT="-b"
+       SONAME_OPT="+h"
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+irix*)
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
+       DYEXT="so"
+
+       #
+       # Compiler assumed to be GCC; run-time linker may require a -R
+       # flag.
+       #
+       if test "$libdir" != "/usr/lib"; then
+               V_RFLAGS=-Wl,-R$libdir
+       fi
+       ;;
+
+osf*)
+       DYEXT="so"
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+sinix*)
+       AC_MSG_CHECKING(if SINIX compiler defines sinix)
+       AC_CACHE_VAL(ac_cv_cc_sinix_defined,
+               AC_TRY_COMPILE(
+                   [],
+                   [int i = sinix;],
+                   ac_cv_cc_sinix_defined=yes,
+                   ac_cv_cc_sinix_defined=no))
+           AC_MSG_RESULT($ac_cv_cc_sinix_defined)
+           if test $ac_cv_cc_sinix_defined = no ; then
+                   AC_DEFINE(sinix,1,[on sinix])
+           fi
+       ;;
+
+solaris*)
+       AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
+
+       DYEXT="so"
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+esac
+
+AC_ARG_ENABLE(shared,
+AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@]))
+test "x$enable_shared" = "xno" && DYEXT="none"
+
+AC_PROG_RANLIB
+AC_CHECK_TOOL([AR], [ar])
+
+AC_LBL_DEVEL(V_CCOPT)
+
+AC_LBL_SOCKADDR_SA_LEN
+
+AC_LBL_SOCKADDR_STORAGE
+
+AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
+
+AC_LBL_UNALIGNED_ACCESS
+
+#
+# Makefile.in includes rules to generate version.h, so we assume
+# that it will be generated if autoconf is used.
+#
+AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure])
+
+rm -f net
+ln -s ${srcdir}/bpf/net net
+
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_DEFS)
+AC_SUBST(V_FINDALLDEVS)
+AC_SUBST(V_INCLS)
+AC_SUBST(V_LEX)
+AC_SUBST(V_PCAP)
+AC_SUBST(V_SHLIB_CMD)
+AC_SUBST(V_SHLIB_OPT)
+AC_SUBST(V_SONAME_OPT)
+AC_SUBST(V_RPATH_OPT)
+AC_SUBST(V_YACC)
+AC_SUBST(ADDLOBJS)
+AC_SUBST(ADDLARCHIVEOBJS)
+AC_SUBST(SSRC)
+AC_SUBST(DYEXT)
+AC_SUBST(MAN_FILE_FORMATS)
+AC_SUBST(MAN_MISC_INFO)
+
+dnl check for USB sniffing support
+AC_MSG_CHECKING(for USB sniffing support)
+case "$host_os" in
+linux*)
+       AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
+       USB_SRC=pcap-usb-linux.c
+       AC_MSG_RESULT(yes)
+       ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+       if test $? -ne 0 ; then
+         ac_usb_dev_name="usbmon"
+       fi
+       AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
+       AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
+       #
+       # Do we have a version of <linux/compiler.h> available?
+       # If so, we might need it for <linux/usbdevice_fs.h>.
+       #
+       AC_CHECK_HEADERS(linux/compiler.h)
+       if test "$ac_cv_header_linux_compiler_h" = yes; then
+         #
+         # Yes - include it when testing for <linux/usbdevice_fs.h>.
+         #
+         AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
+       else
+         AC_CHECK_HEADERS(linux/usbdevice_fs.h)
+       fi
+       if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+         #
+         # OK, does it define bRequestType?  Older versions of the kernel
+         # define fields with names like "requesttype, "request", and
+         # "value", rather than "bRequestType", "bRequest", and
+         # "wValue".
+         #
+         AC_MSG_CHECKING(if usbdevfs_ctrltransfer struct has bRequestType member)
+         AC_CACHE_VAL(ac_cv_usbdevfs_ctrltransfer_has_bRequestType,
+           AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/usbdevice_fs.h>],
+             [u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)],
+             ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes,
+             ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no))
+           AC_MSG_RESULT($ac_cv_usbdevfs_ctrltransfer_has_bRequestType)
+           if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then
+             AC_DEFINE(HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE,1,
+               [if struct usbdevfs_ctrltransfer has bRequestType])
+           fi
+       fi
+       ;;
+*)
+       AC_MSG_RESULT(no)
+       ;;
+esac
+AC_SUBST(PCAP_SUPPORT_USB)
+AC_SUBST(USB_SRC)
+
+dnl check for netfilter sniffing support
+AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
+case "$host_os" in
+linux*)
+       AC_MSG_RESULT(yes)
+       #
+       # Life's too short to deal with trying to get this to compile
+       # if you don't get the right types defined with
+       # __KERNEL_STRICT_NAMES getting defined by some other include.
+       #
+       # Check whether the includes Just Work.  If not, don't turn on
+       # netfilter support.
+       #
+       AC_MSG_CHECKING(whether we can compile the netfilter support)
+       AC_CACHE_VAL(ac_cv_netfilter_can_compile,
+         AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>],
+           [],
+           ac_cv_netfilter_can_compile=yes,
+           ac_cv_netfilter_can_compile=no))
+       AC_MSG_RESULT($ac_cv_netfilter_can_compile)
+       if test $ac_cv_netfilter_can_compile = yes ; then
+         AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
+           [target host supports netfilter sniffing])
+         NETFILTER_SRC=pcap-netfilter-linux.c
+       fi
+       ;;
+*)
+       AC_MSG_RESULT(no)
+       ;;
+esac
+AC_SUBST(PCAP_SUPPORT_NETFILTER)
+AC_SUBST(NETFILTER_SRC)
+
+AC_ARG_ENABLE([bluetooth],
+[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
+,enable_bluetooth=yes)
+
+if test "x$enable_bluetooth" != "xno" ; then
+       dnl check for Bluetooth sniffing support
+       case "$host_os" in
+       linux*)
+               AC_CHECK_HEADER(bluetooth/bluetooth.h,
+               [
+                 AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
+                 BT_SRC=pcap-bt-linux.c
+                 AC_MSG_NOTICE(Bluetooth sniffing is supported)
+               ],
+               AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+               )
+               ;;
+       *)
+               AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
+               ;;
+       esac
+       AC_SUBST(PCAP_SUPPORT_BT)
+       AC_SUBST(BT_SRC)
+fi
+
+AC_ARG_ENABLE([canusb],
+[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])]
+,enable_canusb=yes)
+
+if test "x$enable_canusb" != "xno" ; then
+       dnl check for canusb support
+       case "$host_os" in
+       linux*)
+               AC_CHECK_HEADER(libusb-1.0/libusb.h,
+               [
+                   AC_DEFINE(PCAP_SUPPORT_CANUSB, 1, [target host supports canusb])
+                   CANUSB_SRC=pcap-canusb-linux.c
+                   LIBS="-lusb-1.0 $LIBS"
+                   AC_MSG_NOTICE(canusb sniffing is supported)
+               ],
+               AC_MSG_NOTICE(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
+               )
+               ;;
+       *)
+               AC_MSG_NOTICE(no canusb support implemented for $host_os)
+               ;;
+       esac
+       AC_SUBST(PCAP_SUPPORT_CANUSB)
+       AC_SUBST(CANUSB_SRC)
+fi
+
+AC_ARG_ENABLE([can],
+[AC_HELP_STRING([--enable-can],[enable CAN support @<:@default=yes, if support available@:>@])],
+,enable_can=yes)
+
+if test "x$enable_can" != "xno" ; then
+       dnl check for CAN sniffing support
+       case "$host_os" in
+       linux*)
+               AC_CHECK_HEADER(linux/can.h,
+                       [ AC_DEFINE(PCAP_SUPPORT_CAN, 1, [target host supports CAN sniffing])
+                       CAN_SRC=pcap-can-linux.c
+                       AC_MSG_NOTICE(CAN sniffing is supported)],
+                       AC_MSG_NOTICE(CAN sniffing is not supported),
+                       [#include <sys/socket.h>]
+                  )
+               ;;
+       *)
+               AC_MSG_NOTICE(no CAN sniffing support implemented for $host_os)
+               ;;
+       esac
+       AC_SUBST(PCAP_SUPPORT_CAN)
+       AC_SUBST(CAN_SRC)
+fi
+
+dnl check for hardware timestamp support
+case "$host_os" in
+linux*)
+       AC_CHECK_HEADERS([linux/net_tstamp.h])
+       ;;
+*)
+       AC_MSG_NOTICE(no hardware timestamp support implemented for $host_os)
+       ;;
+esac
+
+AC_PROG_INSTALL
+
+AC_CONFIG_HEADER(config.h)
+
+AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
+       pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
+       pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
+       pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap
+       pcap_open_dead.3pcap pcap_open_offline.3pcap
+       pcap_set_tstamp_type.3pcap)
+
+if test -f .devel ; then
+       make depend
+fi
+exit 0
diff --git a/dlpisubs.c b/dlpisubs.c
new file mode 100644 (file)
index 0000000..23c78ce
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * This code is derived from code formerly in pcap-dlpi.c, originally
+ * contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
+ * London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
+ * Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
+ */
+
+/*
+ * This file contains dlpi/libdlpi related common functions used
+ * by pcap-[dlpi,libdlpi].c.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+       "@(#) $Header: /tcpdump/master/libpcap/dlpisubs.c,v 1.3 2008-12-02 16:40:19 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef DL_IPATM
+#define DL_IPATM       0x12    /* ATM Classical IP interface */
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+       /*
+        * Size of a bufmod chunk to pass upstream; that appears to be the
+        * biggest value to which you can set it, and setting it to that value
+        * (which is bigger than what appears to be the Solaris default of 8192)
+        * reduces the number of packet drops.
+        */
+#define        CHUNKSIZE       65536
+
+       /*
+        * Size of the buffer to allocate for packet data we read; it must be
+        * large enough to hold a chunk.
+        */
+#define        PKTBUFSIZE      CHUNKSIZE
+
+#else /* HAVE_SYS_BUFMOD_H */
+
+       /*
+        * Size of the buffer to allocate for packet data we read; this is
+        * what the value used to be - there's no particular reason why it
+        * should be tied to MAXDLBUF, but we'll leave it as this for now.
+        */
+#define        MAXDLBUF        8192
+#define        PKTBUFSIZE      (MAXDLBUF * sizeof(bpf_u_int32))
+
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#include <sys/dlpi.h>
+#include <sys/stream.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+#ifdef HAVE_SYS_BUFMOD_H
+static void pcap_stream_err(const char *, int, char *);
+#endif
+
+/*
+ * Get the packet statistics.
+ */
+int
+pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
+{
+
+       /*
+        * "ps_recv" counts packets handed to the filter, not packets
+        * that passed the filter.  As filtering is done in userland,
+        * this would not include packets dropped because we ran out
+        * of buffer space; in order to make this more like other
+        * platforms (Linux 2.4 and later, BSDs with BPF), where the
+        * "packets received" count includes packets received but dropped
+        * due to running out of buffer space, and to keep from confusing
+        * applications that, for example, compute packet drop percentages,
+        * we also make it count packets dropped by "bufmod" (otherwise we
+        * might run the risk of the packet drop count being bigger than
+        * the received-packet count).
+        *
+        * "ps_drop" counts packets dropped by "bufmod" because of
+        * flow control requirements or resource exhaustion; it doesn't
+        * count packets dropped by the interface driver, or packets
+        * dropped upstream.  As filtering is done in userland, it counts
+        * packets regardless of whether they would've passed the filter.
+        *
+        * These statistics don't include packets not yet read from
+        * the kernel by libpcap, but they may include packets not
+        * yet read from libpcap by the application.
+        */
+       *ps = p->md.stat;
+
+       /*
+        * Add in the drop count, as per the above comment.
+        */
+       ps->ps_recv += ps->ps_drop;
+       return (0);
+}
+
+/*
+ * Loop through the packets and call the callback for each packet.
+ * Return the number of packets read.
+ */
+int
+pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
+       int count, u_char *bufp, int len)
+{
+       int n, caplen, origlen;
+       u_char *ep, *pk;
+       struct pcap_pkthdr pkthdr;
+#ifdef HAVE_SYS_BUFMOD_H
+       struct sb_hdr *sbp;
+#ifdef LBL_ALIGN
+       struct sb_hdr sbhdr;
+#endif
+#endif
+
+       /* Loop through packets */
+       ep = bufp + len;
+       n = 0;
+
+#ifdef HAVE_SYS_BUFMOD_H
+       while (bufp < ep) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else {
+                               p->bp = bufp;
+                               p->cc = ep - bufp;
+                               return (n);
+                       }
+               }
+#ifdef LBL_ALIGN
+               if ((long)bufp & 3) {
+                       sbp = &sbhdr;
+                       memcpy(sbp, bufp, sizeof(*sbp));
+               } else
+#endif
+                       sbp = (struct sb_hdr *)bufp;
+               p->md.stat.ps_drop = sbp->sbh_drops;
+               pk = bufp + sizeof(*sbp);
+               bufp += sbp->sbh_totlen;
+               origlen = sbp->sbh_origlen;
+               caplen = sbp->sbh_msglen;
+#else
+               origlen = len;
+               caplen = min(p->snapshot, len);
+               pk = bufp;
+               bufp += caplen;
+#endif
+               ++p->md.stat.ps_recv;
+               if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
+#ifdef HAVE_SYS_BUFMOD_H
+                       pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
+                       pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
+#else
+                       (void) gettimeofday(&pkthdr.ts, NULL);
+#endif
+                       pkthdr.len = origlen;
+                       pkthdr.caplen = caplen;
+                       /* Insure caplen does not exceed snapshot */
+                       if (pkthdr.caplen > p->snapshot)
+                               pkthdr.caplen = p->snapshot;
+                       (*callback)(user, &pkthdr, pk);
+                       if (++n >= count && count >= 0) {
+                               p->cc = ep - bufp;
+                               p->bp = bufp;
+                               return (n);
+                       }
+               }
+#ifdef HAVE_SYS_BUFMOD_H
+       }
+#endif
+       p->cc = 0;
+       return (n);
+}
+
+/*
+ * Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
+ */
+int
+pcap_process_mactype(pcap_t *p, u_int mactype)
+{
+       int retv = 0;
+
+       switch (mactype) {
+
+       case DL_CSMACD:
+       case DL_ETHER:
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+               break;
+
+       case DL_FDDI:
+               p->linktype = DLT_FDDI;
+               p->offset = 3;
+               break;
+
+       case DL_TPR:
+               /* XXX - what about DL_TPB?  Is that Token Bus?  */
+               p->linktype = DLT_IEEE802;
+               p->offset = 2;
+               break;
+
+#ifdef HAVE_SOLARIS
+       case DL_IPATM:
+               p->linktype = DLT_SUNATM;
+               p->offset = 0;  /* works for LANE and LLC encapsulation */
+               break;
+#endif
+
+       default:
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype %u",
+                   mactype);
+               retv = -1;
+       }
+
+       return (retv);
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+/*
+ * Push and configure the buffer module. Returns -1 for error, otherwise 0.
+ */
+int
+pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout)
+{
+       int retv = 0;
+
+       bpf_u_int32 ss, chunksize;
+
+       /* Non-standard call to get the data nicely buffered. */
+       if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
+               pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
+               retv = -1;
+       }
+
+       ss = snaplen;
+       if (ss > 0 &&
+           strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
+               pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
+               retv = -1;
+       }
+
+       /* Set up the bufmod timeout. */
+       if (timeout != 0) {
+               struct timeval to;
+
+               to.tv_sec = timeout / 1000;
+               to.tv_usec = (timeout * 1000) % 1000000;
+               if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
+                       pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
+                       retv = -1;
+               }
+       }
+
+       /* Set the chunk length. */
+       chunksize = CHUNKSIZE;
+       if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
+           != 0) {
+               pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
+               retv = -1;
+       }
+
+       return (retv);
+}
+#endif /* HAVE_SYS_BUFMOD_H */
+
+/*
+ * Allocate data buffer. Returns -1 if memory allocation fails, else 0.
+ */
+int
+pcap_alloc_databuf(pcap_t *p)
+{
+       p->bufsize = PKTBUFSIZE;
+       p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+       if (p->buffer == NULL) {
+               strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+               return (-1);
+       }
+
+       return (0);
+}
+
+/*
+ * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
+ * length of returned data on success.
+ */
+int
+strioctl(int fd, int cmd, int len, char *dp)
+{
+       struct strioctl str;
+       int retv;
+
+       str.ic_cmd = cmd;
+       str.ic_timout = -1;
+       str.ic_len = len;
+       str.ic_dp = dp;
+       if ((retv = ioctl(fd, I_STR, &str)) < 0)
+               return (retv);
+
+       return (str.ic_len);
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+/*
+ * Write stream error message to errbuf.
+ */
+static void
+pcap_stream_err(const char *func, int err, char *errbuf)
+{
+       snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
+}
+#endif
diff --git a/dlpisubs.h b/dlpisubs.h
new file mode 100644 (file)
index 0000000..1b57d4d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * @(#) $Header: /tcpdump/master/libpcap/dlpisubs.h,v 1.2 2008-04-04 19:37:45 guy Exp $
+ */
+
+#ifndef dlpisubs_h
+#define        dlpisubs_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Functions used by dlpisubs.c.
+ */
+int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
+int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
+int pcap_process_mactype(pcap_t *, u_int);
+#ifdef HAVE_SYS_BUFMOD_H
+int pcap_conf_bufmod(pcap_t *, int, int);
+#endif
+int pcap_alloc_databuf(pcap_t *);
+int strioctl(int, int, int, char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/etherent.c b/etherent.c
new file mode 100644 (file)
index 0000000..d9de114
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1990, 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 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
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <ctype.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static inline int xdtoi(int);
+static inline int skip_space(FILE *);
+static inline int skip_line(FILE *);
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+static inline int
+skip_space(f)
+       FILE *f;
+{
+       int c;
+
+       do {
+               c = getc(f);
+       } while (isspace(c) && c != '\n');
+
+       return c;
+}
+
+static inline int
+skip_line(f)
+       FILE *f;
+{
+       int c;
+
+       do
+               c = getc(f);
+       while (c != '\n' && c != EOF);
+
+       return c;
+}
+
+struct pcap_etherent *
+pcap_next_etherent(FILE *fp)
+{
+       register int c, d, i;
+       char *bp;
+       static struct pcap_etherent e;
+
+       memset((char *)&e, 0, sizeof(e));
+       do {
+               /* Find addr */
+               c = skip_space(fp);
+               if (c == '\n')
+                       continue;
+
+               /* If this is a comment, or first thing on line
+                  cannot be etehrnet address, skip the line. */
+               if (!isxdigit(c)) {
+                       c = skip_line(fp);
+                       continue;
+               }
+
+               /* must be the start of an address */
+               for (i = 0; i < 6; i += 1) {
+                       d = xdtoi(c);
+                       c = getc(fp);
+                       if (isxdigit(c)) {
+                               d <<= 4;
+                               d |= xdtoi(c);
+                               c = getc(fp);
+                       }
+                       e.addr[i] = d;
+                       if (c != ':')
+                               break;
+                       c = getc(fp);
+               }
+               if (c == EOF)
+                       break;
+
+               /* Must be whitespace */
+               if (!isspace(c)) {
+                       c = skip_line(fp);
+                       continue;
+               }
+               c = skip_space(fp);
+
+               /* hit end of line... */
+               if (c == '\n')
+                       continue;
+
+               if (c == '#') {
+                       c = skip_line(fp);
+                       continue;
+               }
+
+               /* pick up name */
+               bp = e.name;
+               /* Use 'd' to prevent buffer overflow. */
+               d = sizeof(e.name) - 1;
+               do {
+                       *bp++ = c;
+                       c = getc(fp);
+               } while (!isspace(c) && c != EOF && --d > 0);
+               *bp = '\0';
+
+               /* Eat trailing junk */
+               if (c != '\n')
+                       (void)skip_line(fp);
+
+               return &e;
+
+       } while (c != EOF);
+
+       return (NULL);
+}
diff --git a/ethertype.h b/ethertype.h
new file mode 100644 (file)
index 0000000..2d6bbeb
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1993, 1994, 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.14 2005-09-05 09:06:58 guy Exp $ (LBL)
+ */
+
+/*
+ * Ethernet types.
+ *
+ * We wrap the declarations with #ifdef, so that if a file includes
+ * <netinet/if_ether.h>, which may declare some of these, we don't
+ * get a bunch of complaints from the C compiler about redefinitions
+ * of these values.
+ *
+ * We declare all of them here so that no file has to include
+ * <netinet/if_ether.h> if all it needs are ETHERTYPE_ values.
+ */
+
+#ifndef ETHERTYPE_PUP
+#define        ETHERTYPE_PUP           0x0200  /* PUP protocol */
+#endif
+#ifndef ETHERTYPE_IP
+#define        ETHERTYPE_IP            0x0800  /* IP protocol */
+#endif
+#ifndef ETHERTYPE_ARP
+#define ETHERTYPE_ARP          0x0806  /* Addr. resolution protocol */
+#endif
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP       0x8035  /* reverse Addr. resolution protocol */
+#endif
+#ifndef ETHERTYPE_NS
+#define ETHERTYPE_NS           0x0600
+#endif
+#ifndef        ETHERTYPE_SPRITE
+#define        ETHERTYPE_SPRITE        0x0500
+#endif
+#ifndef ETHERTYPE_TRAIL
+#define ETHERTYPE_TRAIL                0x1000
+#endif
+#ifndef        ETHERTYPE_MOPDL
+#define        ETHERTYPE_MOPDL         0x6001
+#endif
+#ifndef        ETHERTYPE_MOPRC
+#define        ETHERTYPE_MOPRC         0x6002
+#endif
+#ifndef        ETHERTYPE_DN
+#define        ETHERTYPE_DN            0x6003
+#endif
+#ifndef        ETHERTYPE_LAT
+#define        ETHERTYPE_LAT           0x6004
+#endif
+#ifndef ETHERTYPE_SCA
+#define ETHERTYPE_SCA          0x6007
+#endif
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP       0x8035
+#endif
+#ifndef        ETHERTYPE_LANBRIDGE
+#define        ETHERTYPE_LANBRIDGE     0x8038
+#endif
+#ifndef        ETHERTYPE_DECDNS
+#define        ETHERTYPE_DECDNS        0x803c
+#endif
+#ifndef        ETHERTYPE_DECDTS
+#define        ETHERTYPE_DECDTS        0x803e
+#endif
+#ifndef        ETHERTYPE_VEXP
+#define        ETHERTYPE_VEXP          0x805b
+#endif
+#ifndef        ETHERTYPE_VPROD
+#define        ETHERTYPE_VPROD         0x805c
+#endif
+#ifndef ETHERTYPE_ATALK
+#define ETHERTYPE_ATALK                0x809b
+#endif
+#ifndef ETHERTYPE_AARP
+#define ETHERTYPE_AARP         0x80f3
+#endif
+#ifndef ETHERTYPE_8021Q
+#define ETHERTYPE_8021Q                0x8100
+#endif
+#ifndef ETHERTYPE_IPX
+#define ETHERTYPE_IPX          0x8137
+#endif
+#ifndef ETHERTYPE_IPV6
+#define ETHERTYPE_IPV6         0x86dd
+#endif
+#ifndef ETHERTYPE_MPLS
+#define ETHERTYPE_MPLS          0x8847
+#endif
+#ifndef ETHERTYPE_MPLS_MULTI
+#define ETHERTYPE_MPLS_MULTI    0x8848
+#endif
+#ifndef ETHERTYPE_PPPOED
+#define ETHERTYPE_PPPOED       0x8863
+#endif
+#ifndef ETHERTYPE_PPPOES
+#define ETHERTYPE_PPPOES       0x8864
+#endif
+#ifndef        ETHERTYPE_LOOPBACK
+#define        ETHERTYPE_LOOPBACK      0x9000
+#endif
+#ifndef ETHERTYPE_8021QINQ
+#define ETHERTYPE_8021QINQ     0x9100
+#endif
diff --git a/fad-getad.c b/fad-getad.c
new file mode 100644 (file)
index 0000000..742ae1f
--- /dev/null
@@ -0,0 +1,297 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#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
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/if.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ifaddrs.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef AF_PACKET
+# ifdef HAVE_NETPACKET_PACKET_H
+/* Solaris 11 and later, Linux distributions with newer glibc */
+#  include <netpacket/packet.h>
+# else /* HAVE_NETPACKET_PACKET_H */
+/* LynxOS, Linux distributions with older glibc */
+# ifdef __Lynx__
+/* LynxOS */
+#  include <netpacket/if_packet.h>
+# else /* __Lynx__ */
+/* Linux */
+#  include <linux/types.h>
+#  include <linux/if_packet.h>
+# endif /* __Lynx__ */
+# endif /* HAVE_NETPACKET_PACKET_H */
+#endif /* AF_PACKET */
+
+/*
+ * This is fun.
+ *
+ * In older BSD systems, socket addresses were fixed-length, and
+ * "sizeof (struct sockaddr)" gave the size of the structure.
+ * All addresses fit within a "struct sockaddr".
+ *
+ * In newer BSD systems, the socket address is variable-length, and
+ * there's an "sa_len" field giving the length of the structure;
+ * this allows socket addresses to be longer than 2 bytes of family
+ * and 14 bytes of data.
+ *
+ * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
+ * variant of the old BSD scheme (with "struct sockaddr_storage" rather
+ * than "struct sockaddr"), and some use the new BSD scheme.
+ *
+ * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
+ * macro that determines the size based on the address family.  Other
+ * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
+ * but not in the final version).  On the latter systems, we explicitly
+ * check the AF_ type to determine the length; we assume that on
+ * all those systems we have "struct sockaddr_storage".
+ */
+#ifndef SA_LEN
+#ifdef HAVE_SOCKADDR_SA_LEN
+#define SA_LEN(addr)   ((addr)->sa_len)
+#else /* HAVE_SOCKADDR_SA_LEN */
+#ifdef HAVE_SOCKADDR_STORAGE
+static size_t
+get_sa_len(struct sockaddr *addr)
+{
+       switch (addr->sa_family) {
+
+#ifdef AF_INET
+       case AF_INET:
+               return (sizeof (struct sockaddr_in));
+#endif
+
+#ifdef AF_INET6
+       case AF_INET6:
+               return (sizeof (struct sockaddr_in6));
+#endif
+
+#ifdef AF_PACKET
+       case AF_PACKET:
+               return (sizeof (struct sockaddr_ll));
+#endif
+
+       default:
+               return (sizeof (struct sockaddr));
+       }
+}
+#define SA_LEN(addr)   (get_sa_len(addr))
+#else /* HAVE_SOCKADDR_STORAGE */
+#define SA_LEN(addr)   (sizeof (struct sockaddr))
+#endif /* HAVE_SOCKADDR_STORAGE */
+#endif /* HAVE_SOCKADDR_SA_LEN */
+#endif /* SA_LEN */
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have "getifaddrs()".
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       pcap_if_t *devlist = NULL;
+       struct ifaddrs *ifap, *ifa;
+       struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
+       size_t addr_size, broadaddr_size, dstaddr_size;
+       int ret = 0;
+       char *p, *q;
+
+       /*
+        * 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.)
+        *
+        * LAN interfaces will probably have link-layer
+        * addresses; I don't know whether all implementations
+        * of "getifaddrs()" now, or in the future, will return
+        * those.
+        */
+       if (getifaddrs(&ifap) != 0) {
+               (void)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 (!(ifa->ifa_flags & IFF_UP)) {
+                       /*
+                        * No, so don't add it to the list.
+                        */
+                       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.
+                */
+               if (ifa->ifa_addr != NULL) {
+                       addr = ifa->ifa_addr;
+                       addr_size = SA_LEN(addr);
+                       netmask = ifa->ifa_netmask;
+               } else {
+                       addr = NULL;
+                       addr_size = 0;
+                       netmask = NULL;
+               }
+               if (ifa->ifa_flags & IFF_BROADCAST &&
+                   ifa->ifa_broadaddr != NULL) {
+                       broadaddr = ifa->ifa_broadaddr;
+                       broadaddr_size = SA_LEN(broadaddr);
+               } else {
+                       broadaddr = NULL;
+                       broadaddr_size = 0;
+               }
+               if (ifa->ifa_flags & IFF_POINTOPOINT &&
+                   ifa->ifa_dstaddr != NULL) {
+                       dstaddr = ifa->ifa_dstaddr;
+                       dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
+               } else {
+                       dstaddr = NULL;
+                       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,
+                   broadaddr, broadaddr_size, dstaddr, dstaddr_size,
+                   errbuf) < 0) {
+                       ret = -1;
+                       break;
+               }
+       }
+
+       freeifaddrs(ifap);
+
+       if (ret != -1) {
+               /*
+                * We haven't had any errors yet; do any platform-specific
+                * operations to add devices.
+                */
+               if (pcap_platform_finddevs(&devlist, errbuf) < 0)
+                       ret = -1;
+       }
+
+       if (ret == -1) {
+               /*
+                * We had an error; free the list we've been constructing.
+                */
+               if (devlist != NULL) {
+                       pcap_freealldevs(devlist);
+                       devlist = NULL;
+               }
+       }
+
+       *alldevsp = devlist;
+       return (ret);
+}
diff --git a/fad-gifc.c b/fad-gifc.c
new file mode 100644 (file)
index 0000000..d0a2e99
--- /dev/null
@@ -0,0 +1,433 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.12 2008-08-06 07:34:09 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <sys/time.h>                          /* concession to AIX */
+
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * This is fun.
+ *
+ * In older BSD systems, socket addresses were fixed-length, and
+ * "sizeof (struct sockaddr)" gave the size of the structure.
+ * All addresses fit within a "struct sockaddr".
+ *
+ * In newer BSD systems, the socket address is variable-length, and
+ * there's an "sa_len" field giving the length of the structure;
+ * this allows socket addresses to be longer than 2 bytes of family
+ * and 14 bytes of data.
+ *
+ * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
+ * variant of the old BSD scheme (with "struct sockaddr_storage" rather
+ * than "struct sockaddr"), and some use the new BSD scheme.
+ *
+ * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
+ * macro that determines the size based on the address family.  Other
+ * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
+ * but not in the final version).
+ *
+ * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have
+ * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the
+ * address in an entry returned by SIOCGIFCONF.
+ */
+#ifndef SA_LEN
+#ifdef HAVE_SOCKADDR_SA_LEN
+#define SA_LEN(addr)   ((addr)->sa_len)
+#else /* HAVE_SOCKADDR_SA_LEN */
+#define SA_LEN(addr)   (sizeof (struct sockaddr))
+#endif /* HAVE_SOCKADDR_SA_LEN */
+#endif /* SA_LEN */
+
+/*
+ * This is also fun.
+ *
+ * There is no ioctl that returns the amount of space required for all
+ * the data that SIOCGIFCONF could return, and if a buffer is supplied
+ * that's not large enough for all the data SIOCGIFCONF could return,
+ * on at least some platforms it just returns the data that'd fit with
+ * no indication that there wasn't enough room for all the data, much
+ * less an indication of how much more room is required.
+ *
+ * The only way to ensure that we got all the data is to pass a buffer
+ * large enough that the amount of space in the buffer *not* filled in
+ * is greater than the largest possible entry.
+ *
+ * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption
+ * that no address is more than 255 bytes (on systems where the "sa_len"
+ * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the
+ * case, and addresses are unlikely to be bigger than that in any case).
+ */
+#define MAX_SA_LEN     255
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have SIOCGIFCONF but
+ * don't have any other mechanism for getting a list of interfaces.
+ *
+ * XXX - or platforms that have other, better mechanisms but for which
+ * we don't yet have code to use that mechanism; I think there's a better
+ * way on Linux, for example.
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       pcap_if_t *devlist = NULL;
+       register int fd;
+       register struct ifreq *ifrp, *ifend, *ifnext;
+       int n;
+       struct ifconf ifc;
+       char *buf = NULL;
+       unsigned buf_size;
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
+       char *p, *q;
+#endif
+       struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
+       struct sockaddr *netmask, *broadaddr, *dstaddr;
+       size_t netmask_size, broadaddr_size, dstaddr_size;
+       int ret = 0;
+
+       /*
+        * Create a socket from which to fetch the list of interfaces.
+        */
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * Start with an 8K buffer, and keep growing the buffer until
+        * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN"
+        * bytes left over in the buffer or we fail to get the
+        * interface list for some reason other than EINVAL (which is
+        * presumed here to mean "buffer is too small").
+        */
+       buf_size = 8192;
+       for (;;) {
+               buf = malloc(buf_size);
+               if (buf == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       (void)close(fd);
+                       return (-1);
+               }
+
+               ifc.ifc_len = buf_size;
+               ifc.ifc_buf = buf;
+               memset(buf, 0, buf_size);
+               if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
+                   && errno != EINVAL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGIFCONF: %s", pcap_strerror(errno));
+                       (void)close(fd);
+                       free(buf);
+                       return (-1);
+               }
+               if (ifc.ifc_len < buf_size &&
+                   (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
+                       break;
+               free(buf);
+               buf_size *= 2;
+       }
+
+       ifrp = (struct ifreq *)buf;
+       ifend = (struct ifreq *)(buf + ifc.ifc_len);
+
+       for (; ifrp < ifend; ifrp = ifnext) {
+               /*
+                * XXX - what if this isn't an IPv4 address?  Can
+                * we still get the netmask, etc. with ioctls on
+                * an IPv4 socket?
+                *
+                * The answer is probably platform-dependent, and
+                * if the answer is "no" on more than one platform,
+                * the way you work around it is probably platform-
+                * dependent as well.
+                */
+               n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name);
+               if (n < sizeof(*ifrp))
+                       ifnext = ifrp + 1;
+               else
+                       ifnext = (struct ifreq *)((char *)ifrp + n);
+
+               /*
+                * XXX - The 32-bit compatibility layer for Linux on IA-64
+                * is slightly broken. It correctly converts the structures
+                * to and from kernel land from 64 bit to 32 bit but 
+                * doesn't update ifc.ifc_len, leaving it larger than the 
+                * amount really used. This means we read off the end 
+                * of the buffer and encounter an interface with an 
+                * "empty" name. Since this is highly unlikely to ever 
+                * occur in a valid case we can just finish looking for 
+                * interfaces if we see an empty name.
+                */
+               if (!(*ifrp->ifr_name))
+                       break;
+
+               /*
+                * Skip entries that begin with "dummy".
+                * XXX - what are these?  Is this Linux-specific?
+                * Are there platforms on which we shouldn't do this?
+                */
+               if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
+                       continue;
+
+               /*
+                * Get the flags for this interface, and skip it if it's
+                * not up.
+                */
+               strncpy(ifrflags.ifr_name, ifrp->ifr_name,
+                   sizeof(ifrflags.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+                       if (errno == ENXIO)
+                               continue;
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGIFFLAGS: %.*s: %s",
+                           (int)sizeof(ifrflags.ifr_name),
+                           ifrflags.ifr_name,
+                           pcap_strerror(errno));
+                       ret = -1;
+                       break;
+               }
+               if (!(ifrflags.ifr_flags & IFF_UP))
+                       continue;
+
+               /*
+                * Get the netmask for this address on this interface.
+                */
+               strncpy(ifrnetmask.ifr_name, ifrp->ifr_name,
+                   sizeof(ifrnetmask.ifr_name));
+               memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr,
+                   sizeof(ifrnetmask.ifr_addr));
+               if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) {
+                       if (errno == EADDRNOTAVAIL) {
+                               /*
+                                * Not available.
+                                */
+                               netmask = NULL;
+                               netmask_size = 0;
+                       } else {
+                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "SIOCGIFNETMASK: %.*s: %s",
+                                   (int)sizeof(ifrnetmask.ifr_name),
+                                   ifrnetmask.ifr_name,
+                                   pcap_strerror(errno));
+                               ret = -1;
+                               break;
+                       }
+               } else {
+                       netmask = &ifrnetmask.ifr_addr;
+                       netmask_size = SA_LEN(netmask);
+               }
+
+               /*
+                * Get the broadcast address for this address on this
+                * interface (if any).
+                */
+               if (ifrflags.ifr_flags & IFF_BROADCAST) {
+                       strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name,
+                           sizeof(ifrbroadaddr.ifr_name));
+                       memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr,
+                           sizeof(ifrbroadaddr.ifr_addr));
+                       if (ioctl(fd, SIOCGIFBRDADDR,
+                           (char *)&ifrbroadaddr) < 0) {
+                               if (errno == EADDRNOTAVAIL) {
+                                       /*
+                                        * Not available.
+                                        */
+                                       broadaddr = NULL;
+                                       broadaddr_size = 0;
+                               } else {
+                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "SIOCGIFBRDADDR: %.*s: %s",
+                                           (int)sizeof(ifrbroadaddr.ifr_name),
+                                           ifrbroadaddr.ifr_name,
+                                           pcap_strerror(errno));
+                                       ret = -1;
+                                       break;
+                               }
+                       } else {
+                               broadaddr = &ifrbroadaddr.ifr_broadaddr;
+                               broadaddr_size = SA_LEN(broadaddr);
+                       }
+               } else {
+                       /*
+                        * Not a broadcast interface, so no broadcast
+                        * address.
+                        */
+                       broadaddr = NULL;
+                       broadaddr_size = 0;
+               }
+
+               /*
+                * Get the destination address for this address on this
+                * interface (if any).
+                */
+               if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
+                       strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name,
+                           sizeof(ifrdstaddr.ifr_name));
+                       memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr,
+                           sizeof(ifrdstaddr.ifr_addr));
+                       if (ioctl(fd, SIOCGIFDSTADDR,
+                           (char *)&ifrdstaddr) < 0) {
+                               if (errno == EADDRNOTAVAIL) {
+                                       /*
+                                        * Not available.
+                                        */
+                                       dstaddr = NULL;
+                                       dstaddr_size = 0;
+                               } else {
+                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "SIOCGIFDSTADDR: %.*s: %s",
+                                           (int)sizeof(ifrdstaddr.ifr_name),
+                                           ifrdstaddr.ifr_name,
+                                           pcap_strerror(errno));
+                                       ret = -1;
+                                       break;
+                               }
+                       } else {
+                               dstaddr = &ifrdstaddr.ifr_dstaddr;
+                               dstaddr_size = SA_LEN(dstaddr);
+                       }
+               } else {
+                       /*
+                        * Not a point-to-point interface, so no destination
+                        * address.
+                        */
+                       dstaddr = NULL;
+                       dstaddr_size = 0;
+               }
+
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
+               /*
+                * If this entry has a colon followed by a number at
+                * the end, it's a logical interface.  Those are just
+                * the way you assign multiple IP addresses to a real
+                * interface, 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.
+                */
+               p = strchr(ifrp->ifr_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';
+                       }
+               }
+#endif
+
+               /*
+                * Add information for this address to the list.
+                */
+               if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
+                   ifrflags.ifr_flags, &ifrp->ifr_addr,
+                   SA_LEN(&ifrp->ifr_addr), netmask, netmask_size,
+                   broadaddr, broadaddr_size, dstaddr, dstaddr_size,
+                   errbuf) < 0) {
+                       ret = -1;
+                       break;
+               }
+       }
+       free(buf);
+       (void)close(fd);
+
+       if (ret != -1) {
+               /*
+                * We haven't had any errors yet; do any platform-specific
+                * operations to add devices.
+                */
+               if (pcap_platform_finddevs(&devlist, errbuf) < 0)
+                       ret = -1;
+       }
+
+       if (ret == -1) {
+               /*
+                * We had an error; free the list we've been constructing.
+                */
+               if (devlist != NULL) {
+                       pcap_freealldevs(devlist);
+                       devlist = NULL;
+               }
+       }
+
+       *alldevsp = devlist;
+       return (ret);
+}
diff --git a/fad-glifc.c b/fad-glifc.c
new file mode 100644 (file)
index 0000000..664bb78
--- /dev/null
@@ -0,0 +1,386 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.7 2008-01-30 09:35:48 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <sys/time.h>                          /* concession to AIX */
+
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have SIOCGLIFCONF
+ * but don't have "getifaddrs()".  (Solaris 8 and later; we use
+ * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       pcap_if_t *devlist = NULL;
+       register int fd4, fd6, fd;
+       register struct lifreq *ifrp, *ifend;
+       struct lifnum ifn;
+       struct lifconf ifc;
+       char *buf = NULL;
+       unsigned buf_size;
+#ifdef HAVE_SOLARIS
+       char *p, *q;
+#endif
+       struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
+       struct sockaddr *netmask, *broadaddr, *dstaddr;
+       int ret = 0;
+
+       /*
+        * Create a socket from which to fetch the list of interfaces,
+        * and from which to fetch IPv4 information.
+        */
+       fd4 = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd4 < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * Create a socket from which to fetch IPv6 information.
+        */
+       fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
+       if (fd6 < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               (void)close(fd4);
+               return (-1);
+       }
+
+       /*
+        * How many entries will SIOCGLIFCONF return?
+        */
+       ifn.lifn_family = AF_UNSPEC;
+       ifn.lifn_flags = 0;
+       ifn.lifn_count = 0;
+       if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "SIOCGLIFNUM: %s", pcap_strerror(errno));
+               (void)close(fd6);
+               (void)close(fd4);
+               return (-1);
+       }
+
+       /*
+        * Allocate a buffer for those entries.
+        */
+       buf_size = ifn.lifn_count * sizeof (struct lifreq);
+       buf = malloc(buf_size);
+       if (buf == NULL) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "malloc: %s", pcap_strerror(errno));
+               (void)close(fd6);
+               (void)close(fd4);
+               return (-1);
+       }
+
+       /*
+        * Get the entries.
+        */
+       ifc.lifc_len = buf_size;
+       ifc.lifc_buf = buf;
+       ifc.lifc_family = AF_UNSPEC;
+       ifc.lifc_flags = 0;
+       memset(buf, 0, buf_size);
+       if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "SIOCGLIFCONF: %s", pcap_strerror(errno));
+               (void)close(fd6);
+               (void)close(fd4);
+               free(buf);
+               return (-1);
+       }
+
+       /*
+        * Loop over the entries.
+        */
+       ifrp = (struct lifreq *)buf;
+       ifend = (struct lifreq *)(buf + ifc.lifc_len);
+
+       for (; ifrp < ifend; ifrp++) {
+               /*
+                * IPv6 or not?
+                */
+               if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
+                       fd = fd6;
+               else
+                       fd = fd4;
+
+               /*
+                * Skip entries that begin with "dummy".
+                * XXX - what are these?  Is this Linux-specific?
+                * Are there platforms on which we shouldn't do this?
+                */
+               if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
+                       continue;
+
+#ifdef HAVE_SOLARIS
+               /*
+                * Skip entries that have a ":" followed by a number
+                * at the end - those are Solaris virtual interfaces
+                * on which you can't capture.
+                */
+               p = strchr(ifrp->lifr_name, ':');
+               if (p != NULL) {
+                       /*
+                        * We have a ":"; is it followed by a number?
+                        */
+                       while (isdigit((unsigned char)*p))
+                               p++;
+                       if (*p == '\0') {
+                               /*
+                                * All digits after the ":" until the end.
+                                */
+                               continue;
+                       }
+               }
+#endif
+
+               /*
+                * Get the flags for this interface, and skip it if it's
+                * not up.
+                */
+               strncpy(ifrflags.lifr_name, ifrp->lifr_name,
+                   sizeof(ifrflags.lifr_name));
+               if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
+                       if (errno == ENXIO)
+                               continue;
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGLIFFLAGS: %.*s: %s",
+                           (int)sizeof(ifrflags.lifr_name),
+                           ifrflags.lifr_name,
+                           pcap_strerror(errno));
+                       ret = -1;
+                       break;
+               }
+               if (!(ifrflags.lifr_flags & IFF_UP))
+                       continue;
+
+               /*
+                * Get the netmask for this address on this interface.
+                */
+               strncpy(ifrnetmask.lifr_name, ifrp->lifr_name,
+                   sizeof(ifrnetmask.lifr_name));
+               memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr,
+                   sizeof(ifrnetmask.lifr_addr));
+               if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) {
+                       if (errno == EADDRNOTAVAIL) {
+                               /*
+                                * Not available.
+                                */
+                               netmask = NULL;
+                       } else {
+                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "SIOCGLIFNETMASK: %.*s: %s",
+                                   (int)sizeof(ifrnetmask.lifr_name),
+                                   ifrnetmask.lifr_name,
+                                   pcap_strerror(errno));
+                               ret = -1;
+                               break;
+                       }
+               } else
+                       netmask = (struct sockaddr *)&ifrnetmask.lifr_addr;
+
+               /*
+                * Get the broadcast address for this address on this
+                * interface (if any).
+                */
+               if (ifrflags.lifr_flags & IFF_BROADCAST) {
+                       strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name,
+                           sizeof(ifrbroadaddr.lifr_name));
+                       memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr,
+                           sizeof(ifrbroadaddr.lifr_addr));
+                       if (ioctl(fd, SIOCGLIFBRDADDR,
+                           (char *)&ifrbroadaddr) < 0) {
+                               if (errno == EADDRNOTAVAIL) {
+                                       /*
+                                        * Not available.
+                                        */
+                                       broadaddr = NULL;
+                               } else {
+                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "SIOCGLIFBRDADDR: %.*s: %s",
+                                           (int)sizeof(ifrbroadaddr.lifr_name),
+                                           ifrbroadaddr.lifr_name,
+                                           pcap_strerror(errno));
+                                       ret = -1;
+                                       break;
+                               }
+                       } else
+                               broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr;
+               } else {
+                       /*
+                        * Not a broadcast interface, so no broadcast
+                        * address.
+                        */
+                       broadaddr = NULL;
+               }
+
+               /*
+                * Get the destination address for this address on this
+                * interface (if any).
+                */
+               if (ifrflags.lifr_flags & IFF_POINTOPOINT) {
+                       strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name,
+                           sizeof(ifrdstaddr.lifr_name));
+                       memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr,
+                           sizeof(ifrdstaddr.lifr_addr));
+                       if (ioctl(fd, SIOCGLIFDSTADDR,
+                           (char *)&ifrdstaddr) < 0) {
+                               if (errno == EADDRNOTAVAIL) {
+                                       /*
+                                        * Not available.
+                                        */
+                                       dstaddr = NULL;
+                               } else {
+                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "SIOCGLIFDSTADDR: %.*s: %s",
+                                           (int)sizeof(ifrdstaddr.lifr_name),
+                                           ifrdstaddr.lifr_name,
+                                           pcap_strerror(errno));
+                                       ret = -1;
+                                       break;
+                               }
+                       } else
+                               dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr;
+               } else
+                       dstaddr = NULL;
+
+#ifdef HAVE_SOLARIS
+               /*
+                * If this entry has a colon followed by a number at
+                * the end, it's a logical interface.  Those are just
+                * the way you assign multiple IP addresses to a real
+                * interface, 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.
+                */
+               p = strchr(ifrp->lifr_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';
+                       }
+               }
+#endif
+
+               /*
+                * Add information for this address to the list.
+                */
+               if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
+                   ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr,
+                   sizeof (struct sockaddr_storage),
+                   netmask, sizeof (struct sockaddr_storage),
+                   broadaddr, sizeof (struct sockaddr_storage),
+                   dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) {
+                       ret = -1;
+                       break;
+               }
+       }
+       free(buf);
+       (void)close(fd6);
+       (void)close(fd4);
+
+       if (ret != -1) {
+               /*
+                * We haven't had any errors yet; do any platform-specific
+                * operations to add devices.
+                */
+               if (pcap_platform_finddevs(&devlist, errbuf) < 0)
+                       ret = -1;
+       }
+
+       if (ret == -1) {
+               /*
+                * We had an error; free the list we've been constructing.
+                */
+               if (devlist != NULL) {
+                       pcap_freealldevs(devlist);
+                       devlist = NULL;
+               }
+       }
+
+       *alldevsp = devlist;
+       return (ret);
+}
diff --git a/fad-null.c b/fad-null.c
new file mode 100644 (file)
index 0000000..26d791d
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.2 2003-11-15 23:23:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have no support for
+ * packet capture.
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       /*
+        * Succeed, but don't return any interfaces; we return only those
+        * we can open, and we can't open any if there's no support
+        * for packet capture.
+        */
+       *alldevsp = NULL;
+       return (0);
+}
diff --git a/fad-sita.c b/fad-sita.c
new file mode 100644 (file)
index 0000000..2619045
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  fad-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ *  Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ *  License: BSD
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of the authors may not be used to endorse or promote
+ *     products derived from this software without specific prior
+ *     written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: fad-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "pcap-int.h"
+
+#include "pcap-sita.h"
+
+extern pcap_if_t       *acn_if_list;                                                           /* pcap's list of available interfaces */
+
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) {
+
+       //printf("pcap_findalldevs()\n");                               // fulko
+
+       *alldevsp = 0;                                                                                          /* initialize the returned variables before we do anything */
+       strcpy(errbuf, "");
+       if (acn_parse_hosts_file(errbuf))                                                       /* scan the hosts file for potential IOPs */
+               {
+               //printf("pcap_findalldevs() returning BAD after parsehosts\n");                                // fulko
+               return -1;
+               }
+       //printf("pcap_findalldevs() got hostlist now finding devs\n");                         // fulko
+       if (acn_findalldevs(errbuf))                                                            /* then ask the IOPs for their monitorable devices */
+               {
+               //printf("pcap_findalldevs() returning BAD after findalldevs\n");                               // fulko
+               return -1;
+               }
+       *alldevsp = acn_if_list;
+       acn_if_list = 0;                                                                                        /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+       //printf("pcap_findalldevs() returning ZERO OK\n");                             // fulko
+       return 0;
+}
diff --git a/fad-win32.c b/fad-win32.c
new file mode 100644 (file)
index 0000000..241a926
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies 
+ * nor the names of its contributors may be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007-09-25 20:34:36 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+#include <pcap-int.h>
+#include <Packet32.h>
+
+#include <errno.h>
+       
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ */
+static int
+add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr,
+    struct sockaddr *netmask, struct sockaddr *broadaddr,
+    struct sockaddr *dstaddr, char *errbuf)
+{
+       pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
+       /*
+        * Allocate the new entry and fill it in.
+        */
+       curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t));
+       if (curaddr == NULL) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "malloc: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       curaddr->next = NULL;
+       if (addr != NULL) {
+               curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage));
+               if (curaddr->addr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->addr = NULL;
+
+       if (netmask != NULL) {
+               curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage));
+               if (curaddr->netmask == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->netmask = NULL;
+               
+       if (broadaddr != NULL) {
+               curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage));
+               if (curaddr->broadaddr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->broadaddr = NULL;
+               
+       if (dstaddr != NULL) {
+               curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage));
+               if (curaddr->dstaddr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->dstaddr = NULL;
+               
+       /*
+        * Find the end of the list of addresses.
+        */
+       for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
+               nextaddr = prevaddr->next;
+               if (nextaddr == NULL) {
+                       /*
+                        * This is the end of the list.
+                        */
+                       break;
+               }
+       }
+
+       if (prevaddr == NULL) {
+               /*
+                * The list was empty; this is the first member.
+                */
+               curdev->addresses = curaddr;
+       } else {
+               /*
+                * "prevaddr" is the last member of the list; append
+                * this member to it.
+                */
+               prevaddr->next = curaddr;
+       }
+
+       return (0);
+}
+
+
+static int
+pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
+    char *errbuf)
+{
+       pcap_if_t *curdev;
+       npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+       LONG if_addr_size;
+       int res = 0;
+
+       if_addr_size = MAX_NETWORK_ADDRESSES;
+
+       /*
+        * Add an entry for this interface, with no addresses.
+        */
+       if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
+               /*
+                * Failure.
+                */
+               return (-1);
+       }
+
+       /*
+        * Get the list of addresses for the interface.
+        */
+       if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
+               /*
+                * Failure.
+                *
+                * We don't return an error, because this can happen with
+                * NdisWan interfaces, and we want to supply them even
+                * if we can't supply their addresses.
+                *
+                * We return an entry with an empty address list.
+                */
+               return (0);
+       }
+
+       /*
+        * Now add the addresses.
+        */
+       while (if_addr_size-- > 0) {
+               /*
+                * "curdev" is an entry for this interface; add an entry for
+                * this address to its list of addresses.
+                */
+               if(curdev == NULL)
+                       break;
+               res = add_addr_to_list(curdev,
+                   (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
+                   (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
+                   (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
+                   NULL,
+                       errbuf);
+               if (res == -1) {
+                       /*
+                        * Failure.
+                        */
+                       break;
+               }
+       }
+
+       return (res);
+}
+
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * Win32 implementation, based on WinPcap
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       pcap_if_t *devlist = NULL;
+       int ret = 0;
+       const char *desc;
+       char *AdaptersName;
+       ULONG NameLength;
+       char *name;
+       
+       if (!PacketGetAdapterNames(NULL, &NameLength))
+       {
+               DWORD last_error = GetLastError();
+
+               if (last_error != ERROR_INSUFFICIENT_BUFFER)
+               {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                               "PacketGetAdapterNames: %s",
+                               pcap_win32strerror());
+                       return (-1);
+               }
+       }
+
+       if (NameLength > 0)
+               AdaptersName = (char*) malloc(NameLength);
+       else
+       {
+               *alldevsp = NULL;
+               return 0;
+       }
+       if (AdaptersName == NULL)
+       {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+               return (-1);
+       }                       
+
+       if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                       "PacketGetAdapterNames: %s",
+                       pcap_win32strerror());
+               free(AdaptersName);
+               return (-1);
+       }
+       
+       /*
+        * "PacketGetAdapterNames()" returned a list of
+        * null-terminated ASCII interface name strings,
+        * terminated by a null string, followed by a list
+        * of null-terminated ASCII interface description
+        * strings, terminated by a null string.
+        * This means there are two ASCII nulls at the end
+        * of the first list.
+        *
+        * Find the end of the first list; that's the
+        * beginning of the second list.
+        */
+       desc = &AdaptersName[0];
+       while (*desc != '\0' || *(desc + 1) != '\0')
+               desc++;
+       
+       /*
+        * Found it - "desc" points to the first of the two
+        * nulls at the end of the list of names, so the
+        * first byte of the list of descriptions is two bytes
+        * after it.
+        */
+       desc += 2;
+       
+       /*
+        * Loop over the elements in the first list.
+        */
+       name = &AdaptersName[0];
+       while (*name != '\0') {
+               /*
+                * Add an entry for this interface.
+                */
+               if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
+                       /*
+                        * Failure.
+                        */
+                       ret = -1;
+                       break;
+               }
+               name += strlen(name) + 1;
+               desc += strlen(desc) + 1;
+       }
+
+       if (ret != -1) {
+               /*
+                * We haven't had any errors yet; do any platform-specific
+                * operations to add devices.
+                */
+               if (pcap_platform_finddevs(&devlist, errbuf) < 0)
+                       ret = -1;
+       }
+       
+       if (ret == -1) {
+               /*
+                * We had an error; free the list we've been constructing.
+                */
+               if (devlist != NULL) {
+                       pcap_freealldevs(devlist);
+                       devlist = NULL;
+               }
+       }
+       
+       *alldevsp = devlist;
+       free(AdaptersName);
+       return (ret);
+}
diff --git a/gencode.c b/gencode.c
new file mode 100644 (file)
index 0000000..532229a
--- /dev/null
+++ b/gencode.c
@@ -0,0 +1,8535 @@
+/*#define CHASE_CHAIN*/
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char 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
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* WIN32 */
+
+/*
+ * XXX - why was this included even on UNIX?
+ */
+#ifdef __MINGW32__
+#include "ip6_misc.h"
+#endif
+
+#ifndef WIN32
+
+#ifdef __NetBSD__
+#include <sys/param.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#endif /* WIN32 */
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <stdarg.h>
+
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
+#include "pcap-int.h"
+
+#include "ethertype.h"
+#include "nlpid.h"
+#include "llc.h"
+#include "gencode.h"
+#include "ieee80211.h"
+#include "atmuni31.h"
+#include "sunatmpos.h"
+#include "ppp.h"
+#include "pcap/sll.h"
+#include "pcap/ipnet.h"
+#include "arcnet.h"
+#if 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
+#include <netdb.h>     /* for "struct addrinfo" */
+#endif /* WIN32 */
+#endif /*INET6*/
+#include <pcap/namedb.h>
+
+#define ETHERMTU       1500
+
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+
+#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 */
+}
+
+static void init_linktype(pcap_t *);
+
+static void init_regs(void);
+static int alloc_reg(void);
+static void free_reg(int);
+
+static struct block *root;
+
+/*
+ * Value passed to gen_load_a() to indicate what the offset argument
+ * is relative to.
+ */
+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 */
+};
+
+#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
+ * not a big deal if all this memory was wasted but if this ever
+ * goes into a library that would probably not be a good idea.
+ *
+ * XXX - this *is* in a library....
+ */
+#define NCHUNKS 16
+#define CHUNK0SIZE 1024
+struct chunk {
+       u_int n_left;
+       void *m;
+};
+
+static struct chunk chunks[NCHUNKS];
+static int cur_chunk;
+
+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);
+
+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 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);
+#ifdef INET6
+static struct block *gen_hostop6(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);
+#ifdef INET6
+static struct block *gen_host6(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);
+#ifdef INET6
+static struct block *gen_portatom6(int, bpf_int32);
+static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
+#endif
+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);
+#ifdef INET6
+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);
+#endif
+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 void *
+newchunk(n)
+       u_int n;
+{
+       struct chunk *cp;
+       int k;
+       size_t size;
+
+#ifndef __NetBSD__
+       /* XXX Round up to nearest long. */
+       n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
+#else
+       /* XXX Round up to structure boundary. */
+       n = ALIGN(n);
+#endif
+
+       cp = &chunks[cur_chunk];
+       if (n > cp->n_left) {
+               ++cp, k = ++cur_chunk;
+               if (k >= NCHUNKS)
+                       bpf_error("out of memory");
+               size = CHUNK0SIZE << k;
+               cp->m = (void *)malloc(size);
+               if (cp->m == NULL)
+                       bpf_error("out of memory");
+               memset((char *)cp->m, 0, size);
+               cp->n_left = size;
+               if (n > size)
+                       bpf_error("out of memory");
+       }
+       cp->n_left -= n;
+       return (void *)((char *)cp->m + cp->n_left);
+}
+
+static void
+freechunks()
+{
+       int i;
+
+       cur_chunk = 0;
+       for (i = 0; i < NCHUNKS; ++i)
+               if (chunks[i].m != NULL) {
+                       free(chunks[i].m);
+                       chunks[i].m = NULL;
+               }
+}
+
+/*
+ * A strdup whose allocations are freed after code generation is over.
+ */
+char *
+sdup(s)
+       register const char *s;
+{
+       int n = strlen(s) + 1;
+       char *cp = newchunk(n);
+
+       strlcpy(cp, s, n);
+       return (cp);
+}
+
+static inline struct block *
+new_block(code)
+       int code;
+{
+       struct block *p;
+
+       p = (struct block *)newchunk(sizeof(*p));
+       p->s.code = code;
+       p->head = p;
+
+       return p;
+}
+
+static inline struct slist *
+new_stmt(code)
+       int code;
+{
+       struct slist *p;
+
+       p = (struct slist *)newchunk(sizeof(*p));
+       p->s.code = code;
+
+       return p;
+}
+
+static struct block *
+gen_retblk(v)
+       int v;
+{
+       struct block *b = new_block(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)
+{
+       int result;
+
+       EnterCriticalSection(&g_PcapCompileCriticalSection);
+
+       result = pcap_compile_unsafe(p, program, buf, optimize, mask);
+
+       LeaveCriticalSection(&g_PcapCompileCriticalSection);
+       
+       return result;
+}
+
+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;
+       const char * volatile xbuf = buf;
+       u_int len;
+
+       no_optimize = 0;
+       n_errors = 0;
+       root = NULL;
+       bpf_pcap = p;
+       init_regs();
+       if (setjmp(top_ctx)) {
+#ifdef INET6
+               if (ai != NULL) {
+                       freeaddrinfo(ai);
+                       ai = NULL;
+               }
+#endif
+               lex_cleanup();
+               freechunks();
+               return (-1);
+       }
+
+       netmask = mask;
+
+       snaplen = pcap_snapshot(p);
+       if (snaplen == 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        "snaplen of 0 rejects all packets");
+               return -1;
+       }
+
+       lex_init(xbuf ? xbuf : "");
+       init_linktype(p);
+       (void)pcap_parse();
+
+       if (n_errors)
+               syntax();
+
+       if (root == NULL)
+               root = gen_retblk(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");
+       }
+       program->bf_insns = icode_to_fcode(root, &len);
+       program->bf_len = len;
+
+       lex_cleanup();
+       freechunks();
+       return (0);
+}
+
+/*
+ * entry point for using the compiler with no pcap open
+ * pass in all the stuff that is needed explicitly instead.
+ */
+int
+pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
+                   struct bpf_program *program,
+            const char *buf, int optimize, bpf_u_int32 mask)
+{
+       pcap_t *p;
+       int ret;
+
+       p = pcap_open_dead(linktype_arg, snaplen_arg);
+       if (p == NULL)
+               return (-1);
+       ret = pcap_compile(p, program, buf, optimize, mask);
+       pcap_close(p);
+       return (ret);
+}
+
+/*
+ * Clean up a "struct bpf_program" by freeing all the memory allocated
+ * in it.
+ */
+void
+pcap_freecode(struct bpf_program *program)
+{
+       program->bf_len = 0;
+       if (program->bf_insns != NULL) {
+               free((char *)program->bf_insns);
+               program->bf_insns = NULL;
+       }
+}
+
+/*
+ * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
+ * which of the jt and jf fields has been resolved and which is a pointer
+ * back to another unresolved block (or nil).  At least one of the fields
+ * in each block is already resolved.
+ */
+static void
+backpatch(list, target)
+       struct block *list, *target;
+{
+       struct block *next;
+
+       while (list) {
+               if (!list->sense) {
+                       next = JT(list);
+                       JT(list) = target;
+               } else {
+                       next = JF(list);
+                       JF(list) = target;
+               }
+               list = next;
+       }
+}
+
+/*
+ * Merge the lists in b0 and b1, using the 'sense' field to indicate
+ * which of jt and jf is the link.
+ */
+static void
+merge(b0, b1)
+       struct block *b0, *b1;
+{
+       register struct block **p = &b0;
+
+       /* Find end of list. */
+       while (*p)
+               p = !((*p)->sense) ? &JT(*p) : &JF(*p);
+
+       /* Concatenate the lists. */
+       *p = b1;
+}
+
+void
+finish_parse(p)
+       struct block *p;
+{
+       struct block *ppi_dlt_check;
+
+       /*
+        * Insert before the statements of the first (root) block any
+        * statements needed to load the lengths of any variable-length
+        * headers into registers.
+        *
+        * XXX - a fancier strategy would be to insert those before the
+        * statements of all blocks that use those lengths and that
+        * have no predecessors that use them, so that we only compute
+        * the lengths if we need them.  There might be even better
+        * approaches than that.
+        *
+        * However, those strategies would be more complicated, and
+        * as we don't generate code to compute a length if the
+        * program has no tests that use the length, and as most
+        * tests will probably use those lengths, we would just
+        * postpone computing the lengths so that it's not done
+        * for tests that fail early, and it's not clear that's
+        * worth the effort.
+        */
+       insert_compute_vloffsets(p->head);
+       
+       /*
+        * For DLT_PPI captures, generate a check of the per-packet
+        * DLT value to make sure it's DLT_IEEE802_11.
+        */
+       ppi_dlt_check = gen_ppi_dlt_check();
+       if (ppi_dlt_check != NULL)
+               gen_and(ppi_dlt_check, p);
+
+       backpatch(p, gen_retblk(snaplen));
+       p->sense = !p->sense;
+       backpatch(p, gen_retblk(0));
+       root = p->head;
+}
+
+void
+gen_and(b0, b1)
+       struct block *b0, *b1;
+{
+       backpatch(b0, b1->head);
+       b0->sense = !b0->sense;
+       b1->sense = !b1->sense;
+       merge(b1, b0);
+       b1->sense = !b1->sense;
+       b1->head = b0->head;
+}
+
+void
+gen_or(b0, b1)
+       struct block *b0, *b1;
+{
+       b0->sense = !b0->sense;
+       backpatch(b0, b1->head);
+       b0->sense = !b0->sense;
+       merge(b1, b0);
+       b1->head = b0->head;
+}
+
+void
+gen_not(b)
+       struct block *b;
+{
+       b->sense = !b->sense;
+}
+
+static struct block *
+gen_cmp(offrel, offset, size, v)
+       enum e_offrel offrel;
+       u_int offset, size;
+       bpf_int32 v;
+{
+       return gen_ncmp(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;
+{
+       return gen_ncmp(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;
+{
+       return gen_ncmp(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;
+{
+       return gen_ncmp(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;
+{
+       return gen_ncmp(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;
+{
+       return gen_ncmp(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;
+{
+       register struct block *b, *tmp;
+
+       b = NULL;
+       while (size >= 4) {
+               register const u_char *p = &v[size - 4];
+               bpf_int32 w = ((bpf_int32)p[0] << 24) |
+                   ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
+
+               tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+               size -= 4;
+       }
+       while (size >= 2) {
+               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);
+               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]);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+       }
+       return b;
+}
+
+/*
+ * AND the field of size "size" at offset "offset" relative to the header
+ * specified by "offrel" with "mask", and compare it with the value "v"
+ * with the test specified by "jtype"; if "reverse" is true, the test
+ * 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;
+{
+       struct slist *s, *s2;
+       struct block *b;
+
+       s = gen_load_a(offrel, offset, size);
+
+       if (mask != 0xffffffff) {
+               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s2->s.k = mask;
+               sappend(s, s2);
+       }
+
+       b = new_block(JMP(jtype));
+       b->stmts = s;
+       b->s.k = v;
+       if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
+               gen_not(b);
+       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;
+
+/*
+ * These are offsets for the MTP3 fields.
+ */
+static u_int off_sio;
+static u_int off_opc;
+static u_int off_dpc;
+static u_int off_sls;
+
+/*
+ * This is the offset of the first byte after the ATM pseudo_header,
+ * or -1 if there is no ATM pseudo-header.
+ */
+static u_int off_payload;
+
+/*
+ * These are offsets to the beginning of the network-layer header.
+ * They are relative to the beginning of the 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;
+
+static int linktype;
+
+static void
+init_linktype(p)
+       pcap_t *p;
+{
+       linktype = pcap_datalink(p);
+#ifdef PCAP_FDDIPAD
+       pcap_fddipad = p->fddipad;
+#endif
+
+       /*
+        * 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;
+
+       /*
+        * And that we're not doing PPPoE.
+        */
+       is_pppoes = 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;
+
+       orig_linktype = -1;
+       orig_nl = -1;
+        label_stack_depth = 0;
+
+       reg_off_ll = -1;
+       reg_off_macpl = -1;
+
+       switch (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;
+
+       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;
+
+       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;
+
+       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;
+
+       case DLT_SLIP_BSDOS:
+               /* XXX this may be the same as the DLT_PPP_BSDOS case */
+               off_linktype = -1;
+               /* XXX end */
+               off_macpl = 24;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
+               return;
+
+       case DLT_NULL:
+       case DLT_LOOP:
+               off_linktype = 0;
+               off_macpl = 4;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
+               return;
+
+       case DLT_ENC:
+               off_linktype = 0;
+               off_macpl = 12;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
+               return;
+
+       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;
+
+       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;
+
+       case DLT_PPP_BSDOS:
+               off_linktype = 5;
+               off_macpl = 24;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
+               return;
+
+       case DLT_FDDI:
+               /*
+                * FDDI doesn't really have a link-level type field.
+                * We set "off_linktype" 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.
+                * 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;
+
+       case DLT_IEEE802:
+               /*
+                * Token Ring doesn't really have a link-level type field.
+                * We set "off_linktype" 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.
+                * XXX - should we generate code to check for SNAP?
+                *
+                * XXX - the header is actually variable-length.
+                * Some various Linux patched versions gave 38
+                * as "off_linktype" and 40 as "off_nl"; however,
+                * if a token ring packet has *no* routing
+                * information, i.e. is not source-routed, the correct
+                * values are 20 and 22, as they are in the vanilla code.
+                *
+                * A packet is source-routed iff the uppermost bit
+                * of the first byte of the source address, at an
+                * offset of 8, has the uppermost bit set.  If the
+                * packet is source-routed, the total number of bytes
+                * of routing information is 2 plus bits 0x1F00 of
+                * 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;
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+               /*
+                * 802.11 doesn't really have a link-level type field.
+                * We set "off_linktype" 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.
+                * XXX - should we generate code to check for SNAP?
+                *
+                * We also handle variable-length radio headers here.
+                * The Prism header is in theory variable-length, but in
+                * practice it's always 144 bytes long.  However, some
+                * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
+                * sometimes or always supply an AVS header, so we
+                * have to check whether the radio header is a Prism
+                * 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;
+
+       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
+                * 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.
+                */
+               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;
+
+       case DLT_ATM_RFC1483:
+       case DLT_ATM_CLIP:      /* Linux ATM defines this */
+               /*
+                * assume routed, non-ISO PDUs
+                * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
+                *
+                * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
+                * or PPP with the PPP NLPID (e.g., PPPoA)?  The
+                * latter would presumably be treated the way PPPoE
+                * should be, so you can do "pppoe and udp port 2049"
+                * 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;
+
+       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;
+
+       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;
+
+       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;
+
+       case DLT_LTALK:
+               /*
+                * LocalTalk does have a 1-byte type field in the LLAP header,
+                * 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;
+
+       case DLT_IP_OVER_FC:
+               /*
+                * RFC 2625 IP-over-Fibre-Channel doesn't really have a
+                * link-level type field.  We set "off_linktype" 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.
+                * 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;
+
+       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;
+
+                /*
+                 * the only BPF-interesting FRF.16 frames are non-control frames;
+                 * Frame Relay has a variable length link-layer
+                 * 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;
+
+       case DLT_APPLE_IP_OVER_IEEE1394:
+               off_linktype = 16;
+               off_macpl = 18;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
+               return;
+
+       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;
+
+#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;
+#endif
+
+        case DLT_JUNIPER_MFR:
+        case DLT_JUNIPER_MLFR:
+        case DLT_JUNIPER_MLPPP:
+        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;
+
+       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;
+
+       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;
+
+               /* 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;
+
+       case DLT_JUNIPER_PPPOE_ATM:
+               off_linktype = 4;
+               off_macpl = 6;
+               off_nl = 0;
+               off_nl_nosnap = -1;     /* no 802.2 LLC */
+               return;
+
+       case DLT_JUNIPER_GGSN:
+               off_linktype = 6;
+               off_macpl = 12;
+               off_nl = 0;
+               off_nl_nosnap = -1;     /* no 802.2 LLC */
+               return;
+
+       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;
+
+       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;
+
+       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;
+
+       case DLT_JUNIPER_VP:
+               off_linktype = 18;
+               off_macpl = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
+       case DLT_JUNIPER_ST:
+               off_linktype = 18;
+               off_macpl = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
+       case DLT_JUNIPER_ISM:
+               off_linktype = 8;
+               off_macpl = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
+       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;
+
+       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;
+
+       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;
+
+       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;
+
+       case DLT_PFSYNC:
+               off_linktype = -1;
+               off_macpl = 4;
+               off_nl = 0;
+               off_nl_nosnap = 0;
+               return;
+
+       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;
+
+       case DLT_IPNET:
+               off_linktype = 1;
+               off_macpl = 24;         /* ipnet header length */
+               off_nl = 0;
+               off_nl_nosnap = -1;
+               return;
+
+       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;
+
+       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;
+
+       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;
+               }
+
+       }
+       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;
+}
+
+/*
+ * Load a value relative to the beginning of the MAC-layer payload.
+ */
+static struct slist *
+gen_load_macplrel(offset, size)
+       u_int offset, size;
+{
+       struct slist *s, *s2;
+
+       s = gen_off_macpl();
+
+       /*
+        * 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.
+        *
+        * Otherwise, the offset of the MAC-layer payload is constant,
+        * and is in off_macpl.
+        */
+       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.
+                */
+               s2 = new_stmt(BPF_LD|BPF_IND|size);
+               s2->s.k = 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.
+                */
+               s = new_stmt(BPF_LD|BPF_ABS|size);
+               s->s.k = off_macpl + offset;
+       }
+       return s;
+}
+
+/*
+ * 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;
+{
+       struct slist *s, *s2;
+
+       switch (offrel) {
+
+       case OR_PACKET:
+                s = new_stmt(BPF_LD|BPF_ABS|size);
+                s->s.k = offset;
+               break;
+
+       case OR_LINK:
+               s = gen_load_llrel(offset, size);
+               break;
+
+       case OR_MACPL:
+               s = gen_load_macplrel(offset, size);
+               break;
+
+       case OR_NET:
+               s = gen_load_macplrel(off_nl + offset, size);
+               break;
+
+       case OR_NET_NOSNAP:
+               s = gen_load_macplrel(off_nl_nosnap + offset, size);
+               break;
+
+       case OR_TRAN_IPV4:
+               /*
+                * Load the X register with the length of the IPv4 header
+                * (plus the offset of the link-layer header, if it's
+                * preceded by a variable-length header such as a radio
+                * header), in bytes.
+                */
+               s = gen_loadx_iphdrlen();
+
+               /*
+                * Load the item at {offset of the MAC-layer payload} +
+                * {offset, relative to the start of the MAC-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.)
+                */
+               s2 = new_stmt(BPF_LD|BPF_IND|size);
+               s2->s.k = off_macpl + off_nl + offset;
+               sappend(s, s2);
+               break;
+
+       case OR_TRAN_IPV6:
+               s = gen_load_macplrel(off_nl + 40 + offset, size);
+               break;
+
+       default:
+               abort();
+               return NULL;
+       }
+       return s;
+}
+
+/*
+ * 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.
+ */
+static struct slist *
+gen_loadx_iphdrlen()
+{
+       struct slist *s, *s2;
+
+       s = gen_off_macpl();
+       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 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;
+               sappend(s, s2);
+               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s2->s.k = 0xf;
+               sappend(s, s2);
+               s2 = new_stmt(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
+                * 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));
+       } 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;
+       }
+       return s;
+}
+
+static struct block *
+gen_uncond(rsense)
+       int rsense;
+{
+       struct block *b;
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_IMM);
+       s->s.k = !rsense;
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+
+       return b;
+}
+
+static inline struct block *
+gen_true()
+{
+       return gen_uncond(1);
+}
+
+static inline struct block *
+gen_false()
+{
+       return gen_uncond(0);
+}
+
+/*
+ * Byte-swap a 32-bit number.
+ * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
+ * big-endian platforms.)
+ */
+#define        SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+
+/*
+ * Generate code to match a particular packet type.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU.  We use that to determine whether to
+ * match the type/length field or to check the type/length field for
+ * a value <= ETHERMTU to see whether it's a type field and then do
+ * the appropriate test.
+ */
+static struct block *
+gen_ether_linktype(proto)
+       register int proto;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case LLCSAP_ISONS:
+       case LLCSAP_IP:
+       case LLCSAP_NETBEUI:
+               /*
+                * OSI protocols and NetBEUI always use 802.2 encapsulation,
+                * so we check the DSAP and SSAP.
+                *
+                * LLCSAP_IP checks for IP-over-802.2, rather
+                * than IP-over-Ethernet or IP-over-SNAP.
+                *
+                * XXX - should we check both the DSAP and the
+                * SSAP, like this, or should we check just the
+                * DSAP, as we do for other types <= ETHERMTU
+                * (i.e., other SAP values)?
+                */
+               b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+               gen_not(b0);
+               b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
+                            ((proto << 8) | proto));
+               gen_and(b0, b1);
+               return b1;
+
+       case LLCSAP_IPX:
+               /*
+                * Check for;
+                *
+                *      Ethernet_II frames, which are Ethernet
+                *      frames with a frame type of ETHERTYPE_IPX;
+                *
+                *      Ethernet_802.3 frames, which are 802.3
+                *      frames (i.e., the type/length field is
+                *      a length field, <= ETHERMTU, rather than
+                *      a type field) with the first two bytes
+                *      after the Ethernet/802.3 header being
+                *      0xFFFF;
+                *
+                *      Ethernet_802.2 frames, which are 802.3
+                *      frames with an 802.2 LLC header and
+                *      with the IPX LSAP as the DSAP in the LLC
+                *      header;
+                *
+                *      Ethernet_SNAP frames, which are 802.3
+                *      frames with an LLC header and a SNAP
+                *      header and with an OUI of 0x000000
+                *      (encapsulated Ethernet) and a protocol
+                *      ID of ETHERTYPE_IPX in the SNAP header.
+                *
+                * XXX - should we generate the same code both
+                * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
+                */
+
+               /*
+                * 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);
+               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);
+               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);
+               gen_not(b0);
+
+               /*
+                * Now add the check for 802.3 frames before the
+                * check for Ethernet_802.2 and Ethernet_802.3,
+                * as those checks should only be done on 802.3
+                * frames, not on Ethernet frames.
+                */
+               gen_and(b0, b1);
+
+               /*
+                * Now add the check for Ethernet_II frames, and
+                * do that before checking for the other frame
+                * types.
+                */
+               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
+                   (bpf_int32)ETHERTYPE_IPX);
+               gen_or(b0, b1);
+               return b1;
+
+       case ETHERTYPE_ATALK:
+       case ETHERTYPE_AARP:
+               /*
+                * EtherTalk (AppleTalk protocols on Ethernet link
+                * layer) may use 802.2 encapsulation.
+                */
+
+               /*
+                * Check for 802.2 encapsulation (EtherTalk phase 2?);
+                * 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);
+               gen_not(b0);
+
+               /*
+                * 802.2-encapsulated ETHERTYPE_ATALK packets are
+                * SNAP packets with an organization code of
+                * 0x080007 (Apple, for Appletalk) and a protocol
+                * type of ETHERTYPE_ATALK (Appletalk).
+                *
+                * 802.2-encapsulated ETHERTYPE_AARP packets are
+                * SNAP packets with an organization code of
+                * 0x000000 (encapsulated Ethernet) and a protocol
+                * type of ETHERTYPE_AARP (Appletalk ARP).
+                */
+               if (proto == ETHERTYPE_ATALK)
+                       b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+               else    /* proto == ETHERTYPE_AARP */
+                       b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+               gen_and(b0, b1);
+
+               /*
+                * Check for Ethernet encapsulation (Ethertalk
+                * phase 1?); we just check for the Ethernet
+                * protocol type.
+                */
+               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               if (proto <= ETHERMTU) {
+                       /*
+                        * This is an LLC SAP value, so the frames
+                        * that match would be 802.2 frames.
+                        * Check that the frame is an 802.2 frame
+                        * (i.e., that the length/type field is
+                        * a length field, <= ETHERMTU) and
+                        * then check the DSAP.
+                        */
+                       b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+                       gen_not(b0);
+                       b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
+                           (bpf_int32)proto);
+                       gen_and(b0, b1);
+                       return b1;
+               } else {
+                       /*
+                        * This is an Ethernet type, so compare
+                        * the length/type field with it (if
+                        * the frame is an 802.2 frame, the length
+                        * field will be <= ETHERMTU, and, as
+                        * "proto" is > ETHERMTU, this test
+                        * 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);
+               }
+       }
+}
+
+/*
+ * "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;
+{
+       switch (proto) {
+
+       case ETHERTYPE_IP:
+               return gen_cmp(OR_LINK, off_linktype, BPF_B,
+                   (bpf_int32)IPH_AF_INET);
+               /* NOTREACHED */
+
+       case ETHERTYPE_IPV6:
+               return gen_cmp(OR_LINK, off_linktype, BPF_B,
+                   (bpf_int32)IPH_AF_INET6);
+               /* NOTREACHED */
+
+       default:
+               break;
+       }
+
+       return gen_false();
+}
+
+/*
+ * Generate code to match a particular packet type.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU.  We use that to determine whether to
+ * match the type field or to check the type field for the special
+ * LINUX_SLL_P_802_2 value and then do the appropriate test.
+ */
+static struct block *
+gen_linux_sll_linktype(proto)
+       register int proto;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case LLCSAP_ISONS:
+       case LLCSAP_IP:
+       case LLCSAP_NETBEUI:
+               /*
+                * OSI protocols and NetBEUI always use 802.2 encapsulation,
+                * so we check the DSAP and SSAP.
+                *
+                * LLCSAP_IP checks for IP-over-802.2, rather
+                * than IP-over-Ethernet or IP-over-SNAP.
+                *
+                * XXX - should we check both the DSAP and the
+                * SSAP, like this, or should we check just the
+                * 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)
+                            ((proto << 8) | proto));
+               gen_and(b0, b1);
+               return b1;
+
+       case LLCSAP_IPX:
+               /*
+                *      Ethernet_II frames, which are Ethernet
+                *      frames with a frame type of ETHERTYPE_IPX;
+                *
+                *      Ethernet_802.3 frames, which have a frame
+                *      type of LINUX_SLL_P_802_3;
+                *
+                *      Ethernet_802.2 frames, which are 802.3
+                *      frames with an 802.2 LLC header (i.e, have
+                *      a frame type of LINUX_SLL_P_802_2) and
+                *      with the IPX LSAP as the DSAP in the LLC
+                *      header;
+                *
+                *      Ethernet_SNAP frames, which are 802.3
+                *      frames with an LLC header and a SNAP
+                *      header and with an OUI of 0x000000
+                *      (encapsulated Ethernet) and a protocol
+                *      ID of ETHERTYPE_IPX in the SNAP header.
+                *
+                * First, do the checks on LINUX_SLL_P_802_2
+                * frames; generate the check for either
+                * Ethernet_802.2 or Ethernet_SNAP frames, and
+                * 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);
+               gen_or(b0, b1);
+               b0 = gen_cmp(OR_LINK, off_linktype, 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);
+               gen_or(b0, b1);
+
+               /*
+                * Now add the check for Ethernet_II frames, and
+                * do that before checking for the other frame
+                * types.
+                */
+               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
+                   (bpf_int32)ETHERTYPE_IPX);
+               gen_or(b0, b1);
+               return b1;
+
+       case ETHERTYPE_ATALK:
+       case ETHERTYPE_AARP:
+               /*
+                * EtherTalk (AppleTalk protocols on Ethernet link
+                * layer) may use 802.2 encapsulation.
+                */
+
+               /*
+                * Check for 802.2 encapsulation (EtherTalk phase 2?);
+                * 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);
+
+               /*
+                * 802.2-encapsulated ETHERTYPE_ATALK packets are
+                * SNAP packets with an organization code of
+                * 0x080007 (Apple, for Appletalk) and a protocol
+                * type of ETHERTYPE_ATALK (Appletalk).
+                *
+                * 802.2-encapsulated ETHERTYPE_AARP packets are
+                * SNAP packets with an organization code of
+                * 0x000000 (encapsulated Ethernet) and a protocol
+                * type of ETHERTYPE_AARP (Appletalk ARP).
+                */
+               if (proto == ETHERTYPE_ATALK)
+                       b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+               else    /* proto == ETHERTYPE_AARP */
+                       b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+               gen_and(b0, b1);
+
+               /*
+                * Check for Ethernet encapsulation (Ethertalk
+                * phase 1?); we just check for the Ethernet
+                * protocol type.
+                */
+               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               if (proto <= ETHERMTU) {
+                       /*
+                        * This is an LLC SAP value, so the frames
+                        * that match would be 802.2 frames.
+                        * Check for the 802.2 protocol type
+                        * 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,
+                            (bpf_int32)proto);
+                       gen_and(b0, b1);
+                       return b1;
+               } else {
+                       /*
+                        * This is an Ethernet type, so compare
+                        * the length/type field with it (if
+                        * the frame is an 802.2 frame, the length
+                        * field will be <= ETHERMTU, and, as
+                        * "proto" is > ETHERMTU, this test
+                        * 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);
+               }
+       }
+}
+
+static struct slist *
+gen_load_prism_llprefixlen()
+{
+       struct slist *s1, *s2;
+       struct slist *sjeq_avs_cookie;
+       struct slist *sjcommon;
+
+       /*
+        * This code is not compatible with the optimizer, as
+        * we are generating jmp instructions within a normal
+        * slist of instructions
+        */
+       no_optimize = 1;
+
+       /*
+        * Generate code to load the length of the radio header into
+        * the register assigned to hold that length, if one has been
+        * assigned.  (If one hasn't been assigned, no code we've
+        * generated uses that prefix, so we don't need to generate any
+        * code to load it.)
+        *
+        * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
+        * or always use the AVS header rather than the Prism header.
+        * We load a 4-byte big-endian value at the beginning of the
+        * raw packet data, and see whether, when masked with 0xFFFFF000,
+        * it's equal to 0x80211000.  If so, that indicates that it's
+        * an AVS header (the masked-out bits are the version number).
+        * Otherwise, it's a Prism header.
+        *
+        * XXX - the Prism header is also, in theory, variable-length,
+        * but no known software generates headers that aren't 144
+        * bytes long.
+        */
+       if (reg_off_ll != -1) {
+               /*
+                * Load the cookie.
+                */
+               s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s1->s.k = 0;
+
+               /*
+                * AND it with 0xFFFFF000.
+                */
+               s2 = new_stmt(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->s.k = 0x80211000;
+               sappend(s1, sjeq_avs_cookie);
+
+               /*
+                * If it's AVS:
+                *
+                * 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.
+                */
+               s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s2->s.k = 4;
+               sappend(s1, s2);
+               sjeq_avs_cookie->s.jt = s2;
+
+               /*
+                * Now jump to the code to allocate a register
+                * into which to save the header length and
+                * store the length there.  (The "jump always"
+                * instruction needs to have the k field set;
+                * 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->s.k = 1;
+               sappend(s1, sjcommon);
+
+               /*
+                * Now for the code that handles the Prism header.
+                * Just load the length of the Prism header (144)
+                * 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->s.k = 144;
+               sappend(s1, s2);
+               sjeq_avs_cookie->s.jf = s2;
+
+               /*
+                * Now allocate a register to hold that value and store
+                * 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;
+               sappend(s1, s2);
+               sjcommon->s.jf = s2;
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               return (s1);
+       } else
+               return (NULL);
+}
+
+static struct slist *
+gen_load_avs_llprefixlen()
+{
+       struct slist *s1, *s2;
+
+       /*
+        * Generate code to load the length of the AVS header into
+        * the register assigned to hold that length, if one has been
+        * assigned.  (If one hasn't been assigned, no code we've
+        * generated uses that prefix, so we don't need to generate any
+        * code to load it.)
+        */
+       if (reg_off_ll != -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->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;
+               sappend(s1, s2);
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               return (s1);
+       } else
+               return (NULL);
+}
+
+static struct slist *
+gen_load_radiotap_llprefixlen()
+{
+       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 one hasn't been assigned, no code we've
+        * generated uses that prefix, so we don't need to generate any
+        * code to load it.)
+        */
+       if (reg_off_ll != -1) {
+               /*
+                * The 2 bytes at offsets of 2 and 3 from the beginning
+                * of the radiotap header are the length of the radiotap
+                * header; unfortunately, it's little-endian, so we have
+                * to load it a byte at a time and construct the value.
+                */
+
+               /*
+                * 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->s.k = 3;
+               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               sappend(s1, s2);
+               s2->s.k = 8;
+               s2 = new_stmt(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);
+               sappend(s1, s2);
+               s2->s.k = 2;
+               s2 = new_stmt(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;
+               sappend(s1, s2);
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               return (s1);
+       } else
+               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.
+ * 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;
+ * that's done in finish_parse().
+ */
+static struct slist *
+gen_load_ppi_llprefixlen()
+{
+       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) {
+               /*
+                * The 2 bytes at offsets of 2 and 3 from the beginning
+                * of the radiotap header are the length of the radiotap
+                * header; unfortunately, it's little-endian, so we have
+                * to load it a byte at a time and construct the value.
+                */
+
+               /*
+                * 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->s.k = 3;
+               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               sappend(s1, s2);
+               s2->s.k = 8;
+               s2 = new_stmt(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);
+               sappend(s1, s2);
+               s2->s.k = 2;
+               s2 = new_stmt(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;
+               sappend(s1, s2);
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               return (s1);
+       } else
+               return (NULL);
+}
+
+/*
+ * Load a value relative to the beginning of the link-layer header after the 802.11
+ * header, i.e. LLC_SNAP.
+ * 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_802_11_header_len(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_tsft_datapad, *sjset_notsft_datapad;
+       struct slist *s_roundup;
+
+       if (reg_off_macpl == -1) {
+               /*
+                * No register has been assigned to the offset of
+                * the MAC-layer payload, which means nobody needs
+                * it; don't bother computing it - just return
+                * what we already have.
+                */
+               return (s);
+       }
+
+       /*
+        * This code is not compatible with the optimizer, as
+        * we are generating jmp instructions within a normal
+        * slist of instructions
+        */
+       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".
+        */
+       if (s == NULL) {
+               /*
+                * There is no variable-length header preceding the
+                * link-layer header.
+                *
+                * 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.
+                */
+               s = new_stmt(BPF_LDX|BPF_IMM);
+               s->s.k = off_ll;
+       }
+
+       /*
+        * 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,
+        * which is at the offset in the X register, with an indexed load.
+        */
+       s2 = new_stmt(BPF_MISC|BPF_TXA);
+       sappend(s, s2);
+       s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+       s2->s.k = 24;
+       sappend(s, s2);
+       s2 = new_stmt(BPF_ST);
+       s2->s.k = reg_off_macpl;
+       sappend(s, s2);
+
+       s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+       s2->s.k = 0;
+       sappend(s, s2);
+
+       /*
+        * Check the Frame Control field to see if this is a data frame;
+        * 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->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_2->s.k = 0x04;
+       sappend(s, sjset_data_frame_2);
+       sjset_data_frame_1->s.jf = snext;
+
+       /*
+        * If b2 is not set, this is a data frame; test the QoS bit.
+        * Otherwise, go to the first statement of the rest of the
+        * program.
+        */
+       sjset_data_frame_2->s.jt = snext;
+       sjset_data_frame_2->s.jf = sjset_qos = new_stmt(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
+        * 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;
+       sappend(s, s2);
+       s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+       s2->s.k = 2;
+       sappend(s, s2);
+       s2 = new_stmt(BPF_ST);
+       s2->s.k = reg_off_macpl;
+       sappend(s, s2);
+
+       /*
+        * If we have a radiotap header, look at it to see whether
+        * there's Atheros padding between the MAC-layer header
+        * and the payload.
+        *
+        * Note: all of the fields in the radiotap header are
+        * little-endian, so we byte-swap all of the values
+        * we test against, as they will be loaded as big-endian
+        * values.
+        */
+       if (linktype == DLT_IEEE802_11_RADIO) {
+               /*
+                * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
+                * in the presence flag?
+                */
+               sjset_qos->s.jf = s2 = new_stmt(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);
+
+               /*
+                * If not, skip all of this.
+                */
+               sjset_radiotap_flags->s.jf = 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);
+
+               /*
+                * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
+                * at an offset of 16 from the beginning of the raw packet
+                * data (8 bytes for the radiotap header and 8 bytes for
+                * the TSFT field).
+                *
+                * 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->s.k = 16;
+               sappend(s, s2);
+
+               sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
+               sjset_tsft_datapad->s.k = 0x20;
+               sappend(s, sjset_tsft_datapad);
+
+               /*
+                * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
+                * at an offset of 8 from the beginning of the raw packet
+                * data (8 bytes for the radiotap header).
+                *
+                * 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->s.k = 8;
+               sappend(s, s2);
+
+               sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
+               sjset_notsft_datapad->s.k = 0x20;
+               sappend(s, sjset_notsft_datapad);
+
+               /*
+                * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
+                * set, round the length of the 802.11 header to
+                * a multiple of 4.  Do that by adding 3 and then
+                * 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;
+               sappend(s, s_roundup);
+               s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+               s2->s.k = 3;
+               sappend(s, s2);
+               s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
+               s2->s.k = ~3;
+               sappend(s, s2);
+               s2 = new_stmt(BPF_ST);
+               s2->s.k = reg_off_macpl;
+               sappend(s, s2);
+
+               sjset_tsft_datapad->s.jt = s_roundup;
+               sjset_tsft_datapad->s.jf = snext;
+               sjset_notsft_datapad->s.jt = s_roundup;
+               sjset_notsft_datapad->s.jf = snext;
+       } else
+               sjset_qos->s.jf = snext;
+
+       return s;
+}
+
+static void
+insert_compute_vloffsets(b)
+       struct block *b;
+{
+       struct slist *s;
+
+       /*
+        * 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.
+        */
+       switch (linktype) {
+
+       case DLT_PRISM_HEADER:
+               s = gen_load_prism_llprefixlen();
+               break;
+
+       case DLT_IEEE802_11_RADIO_AVS:
+               s = gen_load_avs_llprefixlen();
+               break;
+
+       case DLT_IEEE802_11_RADIO:
+               s = gen_load_radiotap_llprefixlen();
+               break;
+
+       case DLT_PPI:
+               s = gen_load_ppi_llprefixlen();
+               break;
+
+       default:
+               s = NULL;
+               break;
+       }
+
+       /*
+        * For link-layer types that have a variable-length link-layer
+        * header, generate code to load the offset of the MAC-layer
+        * payload into the register assigned to that offset, if any.
+        */
+       switch (linktype) {
+
+       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);
+               break;
+       }
+
+       /*
+        * If we have any offset-loading code, append all the
+        * existing statements in the block to those statements,
+        * and make the resulting list the list of statements
+        * for the block.
+        */
+       if (s != NULL) {
+               sappend(s, b->stmts);
+               b->stmts = s;
+       }
+}
+
+static struct block *
+gen_ppi_dlt_check(void)
+{
+       struct slist *s_load_dlt;
+       struct block *b;
+
+       if (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->s.k = 4;
+
+               b = new_block(JMP(BPF_JEQ));
+
+               b->stmts = s_load_dlt;
+               b->s.k = SWAPLONG(DLT_IEEE802_11);
+       }
+       else
+       {
+               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;
+       }
+}
+
+/*
+ * 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.
+ */
+static struct slist *
+gen_off_macpl(void)
+{
+       struct slist *s;
+
+       if (off_macpl_is_variable) {
+               if (reg_off_macpl == -1) {
+                       /*
+                        * We haven't yet assigned a register for the offset
+                        * of the MAC-layer payload; allocate one.
+                        */
+                       reg_off_macpl = alloc_reg();
+               }
+
+               /*
+                * Load the register containing the offset of the MAC-layer
+                * payload into the X register.
+                */
+               s = new_stmt(BPF_LDX|BPF_MEM);
+               s->s.k = reg_off_macpl;
+               return s;
+       } else {
+               /*
+                * That offset isn't variable, so we don't need to
+                * generate any code.
+                */
+               return NULL;
+       }
+}
+
+/*
+ * Map an Ethernet type to the equivalent PPP type.
+ */
+static int
+ethertype_to_ppptype(proto)
+       int proto;
+{
+       switch (proto) {
+
+       case ETHERTYPE_IP:
+               proto = PPP_IP;
+               break;
+
+#ifdef INET6
+       case ETHERTYPE_IPV6:
+               proto = PPP_IPV6;
+               break;
+#endif
+
+       case ETHERTYPE_DN:
+               proto = PPP_DECNET;
+               break;
+
+       case ETHERTYPE_ATALK:
+               proto = PPP_APPLE;
+               break;
+
+       case ETHERTYPE_NS:
+               proto = PPP_NS;
+               break;
+
+       case LLCSAP_ISONS:
+               proto = PPP_OSI;
+               break;
+
+       case LLCSAP_8021D:
+               /*
+                * I'm assuming the "Bridging PDU"s that go
+                * over PPP are Spanning Tree Protocol
+                * Bridging PDUs.
+                */
+               proto = PPP_BRPDU;
+               break;
+
+       case LLCSAP_IPX:
+               proto = PPP_IPX;
+               break;
+       }
+       return (proto);
+}
+
+/*
+ * Generate code to match a particular packet type by matching the
+ * link-layer type field or fields in the 802.2 LLC header.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU.
+ */
+static struct block *
+gen_linktype(proto)
+       register int proto;
+{
+       struct block *b0, *b1, *b2;
+
+       /* are we checking MPLS-encapsulated packets? */
+       if (label_stack_depth > 0) {
+               switch (proto) {
+               case ETHERTYPE_IP:
+               case PPP_IP:
+                       /* FIXME add other L3 proto IDs */
+                       return gen_mpls_linktype(Q_IP); 
+
+               case ETHERTYPE_IPV6:
+               case PPP_IPV6:
+                       /* FIXME add other L3 proto IDs */
+                       return gen_mpls_linktype(Q_IPV6); 
+
+               default:
+                       bpf_error("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) {
+
+       case DLT_EN10MB:
+       case DLT_NETANALYZER:
+       case DLT_NETANALYZER_TRANSPARENT:
+               return gen_ether_linktype(proto);
+               /*NOTREACHED*/
+               break;
+
+       case DLT_C_HDLC:
+               switch (proto) {
+
+               case LLCSAP_ISONS:
+                       proto = (proto << 8 | LLCSAP_ISONS);
+                       /* fall through */
+
+               default:
+                       return gen_cmp(OR_LINK, off_linktype, BPF_H,
+                           (bpf_int32)proto);
+                       /*NOTREACHED*/
+                       break;
+               }
+               break;
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+       case DLT_PPI:
+               /*
+                * Check that we have a data frame.
+                */
+               b0 = gen_check_802_11_data_frame();
+
+               /*
+                * Now check for the specified link-layer type.
+                */
+               b1 = gen_llc_linktype(proto);
+               gen_and(b0, b1);
+               return b1;
+               /*NOTREACHED*/
+               break;
+
+       case DLT_FDDI:
+               /*
+                * XXX - check for asynchronous frames, as per RFC 1103.
+                */
+               return gen_llc_linktype(proto);
+               /*NOTREACHED*/
+               break;
+
+       case DLT_IEEE802:
+               /*
+                * XXX - check for LLC PDUs, as per IEEE 802.5.
+                */
+               return gen_llc_linktype(proto);
+               /*NOTREACHED*/
+               break;
+
+       case DLT_ATM_RFC1483:
+       case DLT_ATM_CLIP:
+       case DLT_IP_OVER_FC:
+               return gen_llc_linktype(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.
+                *
+                * We assume LANE means Ethernet, not Token Ring.
+                */
+               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;
+               }
+               /*NOTREACHED*/
+               break;
+
+       case DLT_LINUX_SLL:
+               return gen_linux_sll_linktype(proto);
+               /*NOTREACHED*/
+               break;
+
+       case DLT_SLIP:
+       case DLT_SLIP_BSDOS:
+       case DLT_RAW:
+               /*
+                * These types don't provide any type field; packets
+                * are always IPv4 or IPv6.
+                *
+                * XXX - for IPv4, check for a version number of 4, and,
+                * for IPv6, check for a version number of 6?
+                */
+               switch (proto) {
+
+               case ETHERTYPE_IP:
+                       /* Check for a version number of 4. */
+                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
+#ifdef INET6
+               case ETHERTYPE_IPV6:
+                       /* Check for a version number of 6. */
+                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
+#endif
+
+               default:
+                       return gen_false();             /* always false */
+               }
+               /*NOTREACHED*/
+               break;
+
+       case DLT_IPV4:
+               /*
+                * Raw IPv4, so no type field.
+                */
+               if (proto == ETHERTYPE_IP)
+                       return gen_true();              /* always true */
+
+               /* Checking for something other than IPv4; always false */
+               return gen_false();
+               /*NOTREACHED*/
+               break;
+
+       case DLT_IPV6:
+               /*
+                * Raw IPv6, so no type field.
+                */
+#ifdef INET6
+               if (proto == ETHERTYPE_IPV6)
+                       return gen_true();              /* always true */
+#endif
+
+               /* Checking for something other than IPv6; always false */
+               return gen_false();
+               /*NOTREACHED*/
+               break;
+
+       case DLT_PPP:
+       case DLT_PPP_PPPD:
+       case DLT_PPP_SERIAL:
+       case DLT_PPP_ETHER:
+               /*
+                * We use Ethernet protocol types inside libpcap;
+                * 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);
+               /*NOTREACHED*/
+               break;
+
+       case DLT_PPP_BSDOS:
+               /*
+                * We use Ethernet protocol types inside libpcap;
+                * map them to the corresponding PPP protocol types.
+                */
+               switch (proto) {
+
+               case ETHERTYPE_IP:
+                       /*
+                        * 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);
+                       gen_or(b0, b1);
+                       b0 = gen_cmp(OR_LINK, off_linktype, 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,
+                               (bpf_int32)proto);
+               }
+               /*NOTREACHED*/
+               break;
+
+       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;
+
+#ifdef INET6
+               case ETHERTYPE_IPV6:
+                       proto = AF_INET6;
+                       break;
+#endif
+
+               default:
+                       /*
+                        * Not a type on which we support filtering.
+                        * 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_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
+
+#ifdef HAVE_NET_PFVAR_H
+       case DLT_PFLOG:
+               /*
+                * af field is host byte order in contrast to the rest of
+                * the packet.
+                */
+               if (proto == ETHERTYPE_IP)
+                       return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+                           BPF_B, (bpf_int32)AF_INET));
+#ifdef INET6
+               else if (proto == ETHERTYPE_IPV6)
+                       return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+                           BPF_B, (bpf_int32)AF_INET6));
+#endif /* INET6 */
+               else
+                       return gen_false();
+               /*NOTREACHED*/
+               break;
+#endif /* HAVE_NET_PFVAR_H */
+
+       case DLT_ARCNET:
+       case DLT_ARCNET_LINUX:
+               /*
+                * XXX should we check for first fragment if the protocol
+                * uses PHDS?
+                */
+               switch (proto) {
+
+               default:
+                       return gen_false();
+
+#ifdef INET6
+               case ETHERTYPE_IPV6:
+                       return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+                               (bpf_int32)ARCTYPE_INET6));
+#endif /* INET6 */
+
+               case ETHERTYPE_IP:
+                       b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+                                    (bpf_int32)ARCTYPE_IP);
+                       b1 = gen_cmp(OR_LINK, off_linktype, 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,
+                                    (bpf_int32)ARCTYPE_ARP);
+                       b1 = gen_cmp(OR_LINK, off_linktype, 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,
+                                       (bpf_int32)ARCTYPE_REVARP));
+
+               case ETHERTYPE_ATALK:
+                       return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+                                       (bpf_int32)ARCTYPE_ATALK));
+               }
+               /*NOTREACHED*/
+               break;
+
+       case DLT_LTALK:
+               switch (proto) {
+               case ETHERTYPE_ATALK:
+                       return gen_true();
+               default:
+                       return gen_false();
+               }
+               /*NOTREACHED*/
+               break;
+
+       case DLT_FRELAY:
+               /*
+                * XXX - assumes a 2-byte Frame Relay header with
+                * DLCI and flags.  What if the address is longer?
+                */
+               switch (proto) {
+
+               case ETHERTYPE_IP:
+                       /*
+                        * Check for the special NLPID for IP.
+                        */
+                       return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
+
+#ifdef INET6
+               case ETHERTYPE_IPV6:
+                       /*
+                        * Check for the special NLPID for IPv6.
+                        */
+                       return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
+#endif
+
+               case LLCSAP_ISONS:
+                       /*
+                        * Check for several OSI protocols.
+                        *
+                        * Frame Relay packets typically have an OSI
+                        * NLPID at the beginning; we check for each
+                        * of them.
+                        *
+                        * What we check for is the NLPID and a frame
+                        * 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);
+                       gen_or(b1, b2);
+                       gen_or(b0, b2);
+                       return b2;
+
+               default:
+                       return gen_false();
+               }
+               /*NOTREACHED*/
+               break;
+
+       case DLT_MFR:
+               bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
+
+        case DLT_JUNIPER_MFR:
+        case DLT_JUNIPER_MLFR:
+        case DLT_JUNIPER_MLPPP:
+       case DLT_JUNIPER_ATM1:
+       case DLT_JUNIPER_ATM2:
+       case DLT_JUNIPER_PPPOE:
+       case DLT_JUNIPER_PPPOE_ATM:
+        case DLT_JUNIPER_GGSN:
+        case DLT_JUNIPER_ES:
+        case DLT_JUNIPER_MONITOR:
+        case DLT_JUNIPER_SERVICES:
+        case DLT_JUNIPER_ETHER:
+        case DLT_JUNIPER_PPP:
+        case DLT_JUNIPER_FRELAY:
+        case DLT_JUNIPER_CHDLC:
+        case DLT_JUNIPER_VP:
+        case DLT_JUNIPER_ST:
+        case DLT_JUNIPER_ISM:
+        case DLT_JUNIPER_VS:
+        case DLT_JUNIPER_SRX_E2E:
+        case DLT_JUNIPER_FIBRECHANNEL:
+       case DLT_JUNIPER_ATM_CEMIC:
+
+               /* just lets verify the magic number for now -
+                * on ATM we may have up to 6 different encapsulations on the wire
+                * and need a lot of heuristics to figure out that the payload
+                * might be;
+                *
+                * FIXME encapsulation specific BPF_ filters
+                */
+               return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+
+       case DLT_IPNET:
+               return gen_ipnet_linktype(proto);
+
+       case DLT_LINUX_IRDA:
+               bpf_error("IrDA link-layer type filtering not implemented");
+
+       case DLT_DOCSIS:
+               bpf_error("DOCSIS link-layer type filtering not implemented");
+
+       case DLT_MTP2:
+       case DLT_MTP2_WITH_PHDR:
+               bpf_error("MTP2 link-layer type filtering not implemented");
+
+       case DLT_ERF:
+               bpf_error("ERF link-layer type filtering not implemented");
+
+       case DLT_PFSYNC:
+               bpf_error("PFSYNC link-layer type filtering not implemented");
+
+       case DLT_LINUX_LAPD:
+               bpf_error("LAPD link-layer type filtering not implemented");
+
+       case DLT_USB:
+       case DLT_USB_LINUX:
+       case DLT_USB_LINUX_MMAPPED:
+               bpf_error("USB link-layer type filtering not implemented");
+
+       case DLT_BLUETOOTH_HCI_H4:
+       case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
+               bpf_error("Bluetooth link-layer type filtering not implemented");
+
+       case DLT_CAN20B:
+       case DLT_CAN_SOCKETCAN:
+               bpf_error("CAN link-layer type filtering not implemented");
+
+       case DLT_IEEE802_15_4:
+       case DLT_IEEE802_15_4_LINUX:
+       case DLT_IEEE802_15_4_NONASK_PHY:
+       case DLT_IEEE802_15_4_NOFCS:
+               bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
+
+       case DLT_IEEE802_16_MAC_CPS_RADIO:
+               bpf_error("IEEE 802.16 link-layer type filtering not implemented");
+
+       case DLT_SITA:
+               bpf_error("SITA link-layer type filtering not implemented");
+
+       case DLT_RAIF1:
+               bpf_error("RAIF1 link-layer type filtering not implemented");
+
+       case DLT_IPMB:
+               bpf_error("IPMB link-layer type filtering not implemented");
+
+       case DLT_AX25_KISS:
+               bpf_error("AX.25 link-layer type filtering not implemented");
+       }
+
+       /*
+        * All the types that have no encapsulation should either be
+        * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if
+        * all packets are IP packets, or should be handled in some
+        * special case, if none of them are (if some are and some
+        * aren't, the lack of encapsulation is a problem, as we'd
+        * have to find some other way of determining the packet type).
+        *
+        * Therefore, if "off_linktype" is -1, there's an error.
+        */
+       if (off_linktype == (u_int)-1)
+               abort();
+
+       /*
+        * Any type not handled above should always have an Ethernet
+        * type at an offset of "off_linktype".
+        */
+       return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+}
+
+/*
+ * Check for an LLC SNAP packet with a given organization code and
+ * protocol type; we check the entire contents of the 802.2 LLC and
+ * snap headers, checking for DSAP and SSAP of SNAP and a control
+ * field of 0x03 in the LLC header, and for the specified organization
+ * code and protocol type in the SNAP header.
+ */
+static struct block *
+gen_snap(orgcode, ptype)
+       bpf_u_int32 orgcode;
+       bpf_u_int32 ptype;
+{
+       u_char snapblock[8];
+
+       snapblock[0] = LLCSAP_SNAP;     /* DSAP = SNAP */
+       snapblock[1] = LLCSAP_SNAP;     /* SSAP = SNAP */
+       snapblock[2] = 0x03;            /* control = UI */
+       snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
+       snapblock[4] = (orgcode >> 8);  /* middle 8 bits of organization code */
+       snapblock[5] = (orgcode >> 0);  /* lower 8 bits of organization code */
+       snapblock[6] = (ptype >> 8);    /* upper 8 bits of protocol type */
+       snapblock[7] = (ptype >> 0);    /* lower 8 bits of protocol type */
+       return gen_bcmp(OR_MACPL, 0, 8, snapblock);
+}
+
+/*
+ * Generate code to match a particular packet type, for link-layer types
+ * using 802.2 LLC headers.
+ *
+ * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
+ * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU.  We use that to determine whether to
+ * match the DSAP or both DSAP and LSAP or to check the OUI and
+ * protocol ID in a SNAP header.
+ */
+static struct block *
+gen_llc_linktype(proto)
+       int proto;
+{
+       /*
+        * XXX - handle token-ring variable-length header.
+        */
+       switch (proto) {
+
+       case LLCSAP_IP:
+       case LLCSAP_ISONS:
+       case LLCSAP_NETBEUI:
+               /*
+                * XXX - should we check both the DSAP and the
+                * SSAP, like this, or should we check just the
+                * DSAP, as we do for other types <= ETHERMTU
+                * (i.e., other SAP values)?
+                */
+               return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32)
+                            ((proto << 8) | proto));
+
+       case LLCSAP_IPX:
+               /*
+                * XXX - are there ever SNAP frames for IPX on
+                * non-Ethernet 802.x networks?
+                */
+               return gen_cmp(OR_MACPL, 0, BPF_B,
+                   (bpf_int32)LLCSAP_IPX);
+
+       case ETHERTYPE_ATALK:
+               /*
+                * 802.2-encapsulated ETHERTYPE_ATALK packets are
+                * SNAP packets with an organization code of
+                * 0x080007 (Apple, for Appletalk) and a protocol
+                * type of ETHERTYPE_ATALK (Appletalk).
+                *
+                * XXX - check for an organization code of
+                * encapsulated Ethernet as well?
+                */
+               return gen_snap(0x080007, ETHERTYPE_ATALK);
+
+       default:
+               /*
+                * XXX - we don't have to check for IPX 802.3
+                * here, but should we check for the IPX Ethertype?
+                */
+               if (proto <= ETHERMTU) {
+                       /*
+                        * This is an LLC SAP value, so check
+                        * the DSAP.
+                        */
+                       return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto);
+               } else {
+                       /*
+                        * This is an Ethernet type; we assume that it's
+                        * unlikely that it'll appear in the right place
+                        * at random, and therefore check only the
+                        * location that would hold the Ethernet type
+                        * in a SNAP frame with an organization code of
+                        * 0x000000 (encapsulated Ethernet).
+                        *
+                        * XXX - if we were to check for the SNAP DSAP and
+                        * LSAP, as per XXX, and were also to check for an
+                        * organization code of 0x000000 (encapsulated
+                        * Ethernet), we'd do
+                        *
+                        *      return gen_snap(0x000000, proto);
+                        *
+                        * here; for now, we don't, as per the above.
+                        * I don't know whether it's worth the extra CPU
+                        * time to do the right check or not.
+                        */
+                       return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto);
+               }
+       }
+}
+
+static struct block *
+gen_hostop(addr, mask, dir, proto, src_off, dst_off)
+       bpf_u_int32 addr;
+       bpf_u_int32 mask;
+       int dir, proto;
+       u_int src_off, dst_off;
+{
+       struct block *b0, *b1;
+       u_int offset;
+
+       switch (dir) {
+
+       case Q_SRC:
+               offset = src_off;
+               break;
+
+       case Q_DST:
+               offset = dst_off;
+               break;
+
+       case Q_AND:
+               b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               abort();
+       }
+       b0 = gen_linktype(proto);
+       b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
+       gen_and(b0, b1);
+       return b1;
+}
+
+#ifdef INET6
+static struct block *
+gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
+       struct in6_addr *addr;
+       struct in6_addr *mask;
+       int dir, proto;
+       u_int src_off, dst_off;
+{
+       struct block *b0, *b1;
+       u_int offset;
+       u_int32_t *a, *m;
+
+       switch (dir) {
+
+       case Q_SRC:
+               offset = src_off;
+               break;
+
+       case Q_DST:
+               offset = dst_off;
+               break;
+
+       case Q_AND:
+               b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               abort();
+       }
+       /* this order is important */
+       a = (u_int32_t *)addr;
+       m = (u_int32_t *)mask;
+       b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
+       b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
+       gen_and(b0, b1);
+       b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
+       gen_and(b0, b1);
+       b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
+       gen_and(b0, b1);
+       b0 = gen_linktype(proto);
+       gen_and(b0, b1);
+       return b1;
+}
+#endif /*INET6*/
+
+static struct block *
+gen_ehostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       register struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+               return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
+
+       case Q_AND:
+               b0 = gen_ehostop(eaddr, Q_SRC);
+               b1 = gen_ehostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_ehostop(eaddr, Q_SRC);
+               b1 = gen_ehostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ADDR1:
+               bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
+               break;
+
+       case Q_ADDR2:
+               bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
+               break;
+
+       case Q_ADDR3:
+               bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
+               break;
+
+       case Q_ADDR4:
+               bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
+               break;
+
+       case Q_RA:
+               bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
+               break;
+
+       case Q_TA:
+               bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
+               break;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Like gen_ehostop, but for DLT_FDDI
+ */
+static struct block *
+gen_fhostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+#ifdef PCAP_FDDIPAD
+               return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
+#endif
+
+       case Q_DST:
+#ifdef PCAP_FDDIPAD
+               return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
+#endif
+
+       case Q_AND:
+               b0 = gen_fhostop(eaddr, Q_SRC);
+               b1 = gen_fhostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_fhostop(eaddr, Q_SRC);
+               b1 = gen_fhostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ADDR1:
+               bpf_error("'addr1' is only supported on 802.11");
+               break;
+
+       case Q_ADDR2:
+               bpf_error("'addr2' is only supported on 802.11");
+               break;
+
+       case Q_ADDR3:
+               bpf_error("'addr3' is only supported on 802.11");
+               break;
+
+       case Q_ADDR4:
+               bpf_error("'addr4' is only supported on 802.11");
+               break;
+
+       case Q_RA:
+               bpf_error("'ra' is only supported on 802.11");
+               break;
+
+       case Q_TA:
+               bpf_error("'ta' is only supported on 802.11");
+               break;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
+ */
+static struct block *
+gen_thostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       register struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+               return gen_bcmp(OR_LINK, 8, 6, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(OR_LINK, 2, 6, eaddr);
+
+       case Q_AND:
+               b0 = gen_thostop(eaddr, Q_SRC);
+               b1 = gen_thostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_thostop(eaddr, Q_SRC);
+               b1 = gen_thostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ADDR1:
+               bpf_error("'addr1' is only supported on 802.11");
+               break;
+
+       case Q_ADDR2:
+               bpf_error("'addr2' is only supported on 802.11");
+               break;
+
+       case Q_ADDR3:
+               bpf_error("'addr3' is only supported on 802.11");
+               break;
+
+       case Q_ADDR4:
+               bpf_error("'addr4' is only supported on 802.11");
+               break;
+
+       case Q_RA:
+               bpf_error("'ra' is only supported on 802.11");
+               break;
+
+       case Q_TA:
+               bpf_error("'ta' is only supported on 802.11");
+               break;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
+ * various 802.11 + radio headers.
+ */
+static struct block *
+gen_wlanhostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       register struct block *b0, *b1, *b2;
+       register struct slist *s;
+
+#ifdef ENABLE_WLAN_FILTERING_PATCH
+       /*
+        * TODO GV 20070613
+        * We need to disable the optimizer because the optimizer is buggy
+        * and wipes out some LD instructions generated by the below
+        * code to validate the Frame Control bits
+        */
+       no_optimize = 1;
+#endif /* ENABLE_WLAN_FILTERING_PATCH */
+
+       switch (dir) {
+       case Q_SRC:
+               /*
+                * Oh, yuk.
+                *
+                *      For control frames, there is no SA.
+                *
+                *      For management frames, SA is at an
+                *      offset of 10 from the beginning of
+                *      the packet.
+                *
+                *      For data frames, SA is at an offset
+                *      of 10 from the beginning of the packet
+                *      if From DS is clear, at an offset of
+                *      16 from the beginning of the packet
+                *      if From DS is set and To DS is clear,
+                *      and an offset of 24 from the beginning
+                *      of the packet if From DS is set and To DS
+                *      is set.
+                */
+
+               /*
+                * Generate the tests to be done for data frames
+                * with From DS set.
+                *
+                * First, check for To DS set, i.e. check "link[1] & 0x01".
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x01; /* To DS */
+               b1->stmts = s;
+
+               /*
+                * If To DS is set, the SA is at 24.
+                */
+               b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+               gen_and(b1, b0);
+
+               /*
+                * Now, check for To DS not set, i.e. check
+                * "!(link[1] & 0x01)".
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b2 = new_block(JMP(BPF_JSET));
+               b2->s.k = 0x01; /* To DS */
+               b2->stmts = s;
+               gen_not(b2);
+
+               /*
+                * If To DS is not set, the SA is at 16.
+                */
+               b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+               gen_and(b2, b1);
+
+               /*
+                * Now OR together the last two checks.  That gives
+                * the complete set of checks for data frames with
+                * From DS set.
+                */
+               gen_or(b1, b0);
+
+               /*
+                * Now check for From DS being set, and AND that with
+                * the ORed-together checks.
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x02; /* From DS */
+               b1->stmts = s;
+               gen_and(b1, b0);
+
+               /*
+                * Now check for data frames with From DS not set.
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b2 = new_block(JMP(BPF_JSET));
+               b2->s.k = 0x02; /* From DS */
+               b2->stmts = s;
+               gen_not(b2);
+
+               /*
+                * If From DS isn't set, the SA is at 10.
+                */
+               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+               gen_and(b2, b1);
+
+               /*
+                * Now OR together the checks for data frames with
+                * From DS not set and for data frames with From DS
+                * set; that gives the checks done for data frames.
+                */
+               gen_or(b1, b0);
+
+               /*
+                * Now check for a data frame.
+                * I.e, check "link[0] & 0x08".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x08;
+               b1->stmts = s;
+
+               /*
+                * AND that with the checks done for data frames.
+                */
+               gen_and(b1, b0);
+
+               /*
+                * If the high-order bit of the type value is 0, this
+                * is a management frame.
+                * I.e, check "!(link[0] & 0x08)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b2 = new_block(JMP(BPF_JSET));
+               b2->s.k = 0x08;
+               b2->stmts = s;
+               gen_not(b2);
+
+               /*
+                * For management frames, the SA is at 10.
+                */
+               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+               gen_and(b2, b1);
+
+               /*
+                * OR that with the checks done for data frames.
+                * That gives the checks done for management and
+                * data frames.
+                */
+               gen_or(b1, b0);
+
+               /*
+                * If the low-order bit of the type value is 1,
+                * this is either a control frame or a frame
+                * with a reserved type, and thus not a
+                * frame with an SA.
+                *
+                * I.e., check "!(link[0] & 0x04)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x04;
+               b1->stmts = s;
+               gen_not(b1);
+
+               /*
+                * AND that with the checks for data and management
+                * frames.
+                */
+               gen_and(b1, b0);
+               return b0;
+
+       case Q_DST:
+               /*
+                * Oh, yuk.
+                *
+                *      For control frames, there is no DA.
+                *
+                *      For management frames, DA is at an
+                *      offset of 4 from the beginning of
+                *      the packet.
+                *
+                *      For data frames, DA is at an offset
+                *      of 4 from the beginning of the packet
+                *      if To DS is clear and at an offset of
+                *      16 from the beginning of the packet
+                *      if To DS is set.
+                */
+
+               /*
+                * Generate the tests to be done for data frames.
+                *
+                * First, check for To DS set, i.e. "link[1] & 0x01".
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x01; /* To DS */
+               b1->stmts = s;
+
+               /*
+                * If To DS is set, the DA is at 16.
+                */
+               b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+               gen_and(b1, b0);
+
+               /*
+                * Now, check for To DS not set, i.e. check
+                * "!(link[1] & 0x01)".
+                */
+               s = gen_load_a(OR_LINK, 1, BPF_B);
+               b2 = new_block(JMP(BPF_JSET));
+               b2->s.k = 0x01; /* To DS */
+               b2->stmts = s;
+               gen_not(b2);
+
+               /*
+                * If To DS is not set, the DA is at 4.
+                */
+               b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+               gen_and(b2, b1);
+
+               /*
+                * Now OR together the last two checks.  That gives
+                * the complete set of checks for data frames.
+                */
+               gen_or(b1, b0);
+
+               /*
+                * Now check for a data frame.
+                * I.e, check "link[0] & 0x08".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x08;
+               b1->stmts = s;
+
+               /*
+                * AND that with the checks done for data frames.
+                */
+               gen_and(b1, b0);
+
+               /*
+                * If the high-order bit of the type value is 0, this
+                * is a management frame.
+                * I.e, check "!(link[0] & 0x08)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b2 = new_block(JMP(BPF_JSET));
+               b2->s.k = 0x08;
+               b2->stmts = s;
+               gen_not(b2);
+
+               /*
+                * For management frames, the DA is at 4.
+                */
+               b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+               gen_and(b2, b1);
+
+               /*
+                * OR that with the checks done for data frames.
+                * That gives the checks done for management and
+                * data frames.
+                */
+               gen_or(b1, b0);
+
+               /*
+                * If the low-order bit of the type value is 1,
+                * this is either a control frame or a frame
+                * with a reserved type, and thus not a
+                * frame with an SA.
+                *
+                * I.e., check "!(link[0] & 0x04)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x04;
+               b1->stmts = s;
+               gen_not(b1);
+
+               /*
+                * AND that with the checks for data and management
+                * frames.
+                */
+               gen_and(b1, b0);
+               return b0;
+
+       case Q_RA:
+               /*
+                * Not present in management frames; addr1 in other
+                * frames.
+                */
+
+               /*
+                * If the high-order bit of the type value is 0, this
+                * is a management frame.
+                * I.e, check "(link[0] & 0x08)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x08;
+               b1->stmts = s;
+
+               /*
+                * Check addr1.
+                */
+               b0 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+
+               /*
+                * AND that with the check of addr1.
+                */
+               gen_and(b1, b0);
+               return (b0);
+
+       case Q_TA:
+               /*
+                * Not present in management frames; addr2, if present,
+                * in other frames.
+                */
+
+               /*
+                * Not present in CTS or ACK control frames.
+                */
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b1);
+               b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b2);
+               gen_and(b1, b2);
+               gen_or(b0, b2);
+
+               /*
+                * If the high-order bit of the type value is 0, this
+                * is a management frame.
+                * I.e, check "(link[0] & 0x08)".
+                */
+               s = gen_load_a(OR_LINK, 0, BPF_B);
+               b1 = new_block(JMP(BPF_JSET));
+               b1->s.k = 0x08;
+               b1->stmts = s;
+
+               /*
+                * AND that with the check for frames other than
+                * CTS and ACK frames.
+                */
+               gen_and(b1, b2);
+
+               /*
+                * Check addr2.
+                */
+               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+               gen_and(b2, b1);
+               return b1;
+
+       /*
+        * XXX - add BSSID keyword?
+        */
+       case Q_ADDR1:
+               return (gen_bcmp(OR_LINK, 4, 6, eaddr));
+
+       case Q_ADDR2:
+               /*
+                * Not present in CTS or ACK control frames.
+                */
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b1);
+               b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b2);
+               gen_and(b1, b2);
+               gen_or(b0, b2);
+               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+               gen_and(b2, b1);
+               return b1;
+
+       case Q_ADDR3:
+               /*
+                * Not present in control frames.
+                */
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ADDR4:
+               /*
+                * Present only if the direction mask has both "From DS"
+                * and "To DS" set.  Neither control frames nor management
+                * frames should have both of those set, so we don't
+                * check the frame type.
+                */
+               b0 = gen_mcmp(OR_LINK, 1, BPF_B,
+                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+               b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_AND:
+               b0 = gen_wlanhostop(eaddr, Q_SRC);
+               b1 = gen_wlanhostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_wlanhostop(eaddr, Q_SRC);
+               b1 = gen_wlanhostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
+ * (We assume that the addresses are IEEE 48-bit MAC addresses,
+ * as the RFC states.)
+ */
+static struct block *
+gen_ipfchostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       register struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+               return gen_bcmp(OR_LINK, 10, 6, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(OR_LINK, 2, 6, eaddr);
+
+       case Q_AND:
+               b0 = gen_ipfchostop(eaddr, Q_SRC);
+               b1 = gen_ipfchostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_ipfchostop(eaddr, Q_SRC);
+               b1 = gen_ipfchostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ADDR1:
+               bpf_error("'addr1' is only supported on 802.11");
+               break;
+
+       case Q_ADDR2:
+               bpf_error("'addr2' is only supported on 802.11");
+               break;
+
+       case Q_ADDR3:
+               bpf_error("'addr3' is only supported on 802.11");
+               break;
+
+       case Q_ADDR4:
+               bpf_error("'addr4' is only supported on 802.11");
+               break;
+
+       case Q_RA:
+               bpf_error("'ra' is only supported on 802.11");
+               break;
+
+       case Q_TA:
+               bpf_error("'ta' is only supported on 802.11");
+               break;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * This is quite tricky because there may be pad bytes in front of the
+ * DECNET header, and then there are two possible data packet formats that
+ * carry both src and dst addresses, plus 5 packet types in a format that
+ * carries only the src node, plus 2 types that use a different format and
+ * also carry just the src node.
+ *
+ * Yuck.
+ *
+ * Instead of doing those all right, we just look for data packets with
+ * 0 or 1 bytes of padding.  If you want to look at other packets, that
+ * will require a lot more hacking.
+ *
+ * To add support for filtering on DECNET "areas" (network numbers)
+ * one would want to add a "mask" argument to this routine.  That would
+ * make the filter even more inefficient, although one could be clever
+ * and not generate masking instructions if the mask is 0xFFFF.
+ */
+static struct block *
+gen_dnhostop(addr, dir)
+       bpf_u_int32 addr;
+       int dir;
+{
+       struct block *b0, *b1, *b2, *tmp;
+       u_int offset_lh;        /* offset if long header is received */
+       u_int offset_sh;        /* offset if short header is received */
+
+       switch (dir) {
+
+       case Q_DST:
+               offset_sh = 1;  /* follows flags */
+               offset_lh = 7;  /* flgs,darea,dsubarea,HIORD */
+               break;
+
+       case Q_SRC:
+               offset_sh = 3;  /* follows flags, dstnode */
+               offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
+               break;
+
+       case Q_AND:
+               /* Inefficient because we do our Calvinball dance twice */
+               b0 = gen_dnhostop(addr, Q_SRC);
+               b1 = gen_dnhostop(addr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               /* Inefficient because we do our Calvinball dance twice */
+               b0 = gen_dnhostop(addr, Q_SRC);
+               b1 = gen_dnhostop(addr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ISO:
+               bpf_error("ISO host filtering not implemented");
+
+       default:
+               abort();
+       }
+       b0 = gen_linktype(ETHERTYPE_DN);
+       /* Check for pad = 1, long header case */
+       tmp = gen_mcmp(OR_NET, 2, BPF_H,
+           (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
+       b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
+           BPF_H, (bpf_int32)ntohs((u_short)addr));
+       gen_and(tmp, b1);
+       /* Check for pad = 0, long header case */
+       tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+       b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 1, short header case */
+       tmp = gen_mcmp(OR_NET, 2, BPF_H,
+           (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
+       b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 0, short header case */
+       tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+       b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+
+       /* Combine with test for linktype */
+       gen_and(b0, b1);
+       return b1;
+}
+
+/*
+ * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
+ * test the bottom-of-stack bit, and then check the version number
+ * field in the IP header.
+ */
+static struct block *
+gen_mpls_linktype(proto)
+       int proto;
+{
+       struct block *b0, *b1;
+
+        switch (proto) {
+
+        case Q_IP:
+                /* match the bottom-of-stack bit */
+                b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+                /* match the IPv4 version number */
+                b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0);
+                gen_and(b0, b1);
+                return b1;
+       case Q_IPV6:
+                /* match the bottom-of-stack bit */
+                b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+                /* match the IPv4 version number */
+                b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0);
+                gen_and(b0, b1);
+                return b1;
+       default:
+                abort();
+        }
+}
+
+static struct block *
+gen_host(addr, mask, proto, dir, type)
+       bpf_u_int32 addr;
+       bpf_u_int32 mask;
+       int proto;
+       int dir;
+       int type;
+{
+       struct block *b0, *b1;
+       const char *typestr;
+
+       if (type == Q_NET)
+               typestr = "net";
+       else
+               typestr = "host";
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+               b0 = gen_host(addr, mask, Q_IP, dir, type);
+               /*
+                * Only check for non-IPv4 addresses if we're not
+                * checking MPLS-encapsulated packets.
+                */
+               if (label_stack_depth == 0) {
+                       b1 = gen_host(addr, mask, Q_ARP, dir, type);
+                       gen_or(b0, b1);
+                       b0 = gen_host(addr, mask, Q_RARP, dir, type);
+                       gen_or(b1, b0);
+               }
+               return b0;
+
+       case Q_IP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
+
+       case Q_RARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
+
+       case Q_ARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
+
+       case Q_TCP:
+               bpf_error("'tcp' modifier applied to %s", typestr);
+
+       case Q_SCTP:
+               bpf_error("'sctp' modifier applied to %s", typestr);
+
+       case Q_UDP:
+               bpf_error("'udp' modifier applied to %s", typestr);
+
+       case Q_ICMP:
+               bpf_error("'icmp' modifier applied to %s", typestr);
+
+       case Q_IGMP:
+               bpf_error("'igmp' modifier applied to %s", typestr);
+
+       case Q_IGRP:
+               bpf_error("'igrp' modifier applied to %s", typestr);
+
+       case Q_PIM:
+               bpf_error("'pim' modifier applied to %s", typestr);
+
+       case Q_VRRP:
+               bpf_error("'vrrp' modifier applied to %s", typestr);
+
+       case Q_CARP:
+               bpf_error("'carp' modifier applied to %s", typestr);
+
+       case Q_ATALK:
+               bpf_error("ATALK host filtering not implemented");
+
+       case Q_AARP:
+               bpf_error("AARP host filtering not implemented");
+
+       case Q_DECNET:
+               return gen_dnhostop(addr, dir);
+
+       case Q_SCA:
+               bpf_error("SCA host filtering not implemented");
+
+       case Q_LAT:
+               bpf_error("LAT host filtering not implemented");
+
+       case Q_MOPDL:
+               bpf_error("MOPDL host filtering not implemented");
+
+       case Q_MOPRC:
+               bpf_error("MOPRC host filtering not implemented");
+
+#ifdef INET6
+       case Q_IPV6:
+               bpf_error("'ip6' modifier applied to ip host");
+
+       case Q_ICMPV6:
+               bpf_error("'icmp6' modifier applied to %s", typestr);
+#endif /* INET6 */
+
+       case Q_AH:
+               bpf_error("'ah' modifier applied to %s", typestr);
+
+       case Q_ESP:
+               bpf_error("'esp' modifier applied to %s", typestr);
+
+       case Q_ISO:
+               bpf_error("ISO host filtering not implemented");
+
+       case Q_ESIS:
+               bpf_error("'esis' modifier applied to %s", typestr);
+
+       case Q_ISIS:
+               bpf_error("'isis' modifier applied to %s", typestr);
+
+       case Q_CLNP:
+               bpf_error("'clnp' modifier applied to %s", typestr);
+
+       case Q_STP:
+               bpf_error("'stp' modifier applied to %s", typestr);
+
+       case Q_IPX:
+               bpf_error("IPX host filtering not implemented");
+
+       case Q_NETBEUI:
+               bpf_error("'netbeui' modifier applied to %s", typestr);
+
+       case Q_RADIO:
+               bpf_error("'radio' modifier applied to %s", typestr);
+
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+
+#ifdef INET6
+static struct block *
+gen_host6(addr, mask, proto, dir, type)
+       struct in6_addr *addr;
+       struct in6_addr *mask;
+       int proto;
+       int dir;
+       int type;
+{
+       const char *typestr;
+
+       if (type == Q_NET)
+               typestr = "net";
+       else
+               typestr = "host";
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+               return gen_host6(addr, mask, Q_IPV6, dir, type);
+
+       case Q_IP:
+               bpf_error("'ip' modifier applied to ip6 %s", typestr);
+
+       case Q_RARP:
+               bpf_error("'rarp' modifier applied to ip6 %s", typestr);
+
+       case Q_ARP:
+               bpf_error("'arp' modifier applied to ip6 %s", typestr);
+
+       case Q_SCTP:
+               bpf_error("'sctp' modifier applied to %s", typestr);
+
+       case Q_TCP:
+               bpf_error("'tcp' modifier applied to %s", typestr);
+
+       case Q_UDP:
+               bpf_error("'udp' modifier applied to %s", typestr);
+
+       case Q_ICMP:
+               bpf_error("'icmp' modifier applied to %s", typestr);
+
+       case Q_IGMP:
+               bpf_error("'igmp' modifier applied to %s", typestr);
+
+       case Q_IGRP:
+               bpf_error("'igrp' modifier applied to %s", typestr);
+
+       case Q_PIM:
+               bpf_error("'pim' modifier applied to %s", typestr);
+
+       case Q_VRRP:
+               bpf_error("'vrrp' modifier applied to %s", typestr);
+
+       case Q_CARP:
+               bpf_error("'carp' modifier applied to %s", typestr);
+
+       case Q_ATALK:
+               bpf_error("ATALK host filtering not implemented");
+
+       case Q_AARP:
+               bpf_error("AARP host filtering not implemented");
+
+       case Q_DECNET:
+               bpf_error("'decnet' modifier applied to ip6 %s", typestr);
+
+       case Q_SCA:
+               bpf_error("SCA host filtering not implemented");
+
+       case Q_LAT:
+               bpf_error("LAT host filtering not implemented");
+
+       case Q_MOPDL:
+               bpf_error("MOPDL host filtering not implemented");
+
+       case Q_MOPRC:
+               bpf_error("MOPRC host filtering not implemented");
+
+       case Q_IPV6:
+               return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
+
+       case Q_ICMPV6:
+               bpf_error("'icmp6' modifier applied to %s", typestr);
+
+       case Q_AH:
+               bpf_error("'ah' modifier applied to %s", typestr);
+
+       case Q_ESP:
+               bpf_error("'esp' modifier applied to %s", typestr);
+
+       case Q_ISO:
+               bpf_error("ISO host filtering not implemented");
+
+       case Q_ESIS:
+               bpf_error("'esis' modifier applied to %s", typestr);
+
+       case Q_ISIS:
+               bpf_error("'isis' modifier applied to %s", typestr);
+
+       case Q_CLNP:
+               bpf_error("'clnp' modifier applied to %s", typestr);
+
+       case Q_STP:
+               bpf_error("'stp' modifier applied to %s", typestr);
+
+       case Q_IPX:
+               bpf_error("IPX host filtering not implemented");
+
+       case Q_NETBEUI:
+               bpf_error("'netbeui' modifier applied to %s", typestr);
+
+       case Q_RADIO:
+               bpf_error("'radio' modifier applied to %s", typestr);
+
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+#endif /*INET6*/
+
+#ifndef INET6
+static struct block *
+gen_gateway(eaddr, alist, proto, dir)
+       const u_char *eaddr;
+       bpf_u_int32 **alist;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       if (dir != 0)
+               bpf_error("direction applied to 'gateway'");
+
+       switch (proto) {
+       case Q_DEFAULT:
+       case Q_IP:
+       case Q_ARP:
+       case Q_RARP:
+               switch (linktype) {
+               case DLT_EN10MB:
+               case DLT_NETANALYZER:
+               case DLT_NETANALYZER_TRANSPARENT:
+                       b0 = gen_ehostop(eaddr, Q_OR);
+                       break;
+               case DLT_FDDI:
+                       b0 = gen_fhostop(eaddr, Q_OR);
+                       break;
+               case DLT_IEEE802:
+                       b0 = gen_thostop(eaddr, Q_OR);
+                       break;
+               case DLT_IEEE802_11:
+               case DLT_PRISM_HEADER:
+               case DLT_IEEE802_11_RADIO_AVS:
+               case DLT_IEEE802_11_RADIO:
+               case DLT_PPI:
+                       b0 = gen_wlanhostop(eaddr, Q_OR);
+                       break;
+               case DLT_SUNATM:
+                       if (!is_lane)
+                               bpf_error(
+                                   "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+                       /*
+                        * Check that the packet doesn't begin with an
+                        * LE Control marker.  (We've already generated
+                        * a test for LANE.)
+                        */
+                       b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+                           BPF_H, 0xFF00);
+                       gen_not(b1);
+
+                       /*
+                        * Now check the MAC address.
+                        */
+                       b0 = gen_ehostop(eaddr, Q_OR);
+                       gen_and(b1, b0);
+                       break;
+               case DLT_IP_OVER_FC:
+                       b0 = gen_ipfchostop(eaddr, Q_OR);
+                       break;
+               default:
+                       bpf_error(
+                           "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+               }
+               b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
+               while (*alist) {
+                       tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
+                           Q_HOST);
+                       gen_or(b1, tmp);
+                       b1 = tmp;
+               }
+               gen_not(b1);
+               gen_and(b0, b1);
+               return b1;
+       }
+       bpf_error("illegal modifier of 'gateway'");
+       /* NOTREACHED */
+}
+#endif
+
+struct block *
+gen_proto_abbrev(proto)
+       int proto;
+{
+       struct block *b0;
+       struct block *b1;
+
+       switch (proto) {
+
+       case Q_SCTP:
+               b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+       case Q_TCP:
+               b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+       case Q_UDP:
+               b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+       case Q_ICMP:
+               b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
+               break;
+
+#ifndef        IPPROTO_IGMP
+#define        IPPROTO_IGMP    2
+#endif
+
+       case Q_IGMP:
+               b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
+               break;
+
+#ifndef        IPPROTO_IGRP
+#define        IPPROTO_IGRP    9
+#endif
+       case Q_IGRP:
+               b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
+               break;
+
+#ifndef IPPROTO_PIM
+#define IPPROTO_PIM    103
+#endif
+
+       case Q_PIM:
+               b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+#ifndef IPPROTO_VRRP
+#define IPPROTO_VRRP   112
+#endif
+
+       case Q_VRRP:
+               b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
+               break;
+
+#ifndef IPPROTO_CARP
+#define IPPROTO_CARP   112
+#endif
+
+       case Q_CARP:
+               b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
+               break;
+
+       case Q_IP:
+               b1 =  gen_linktype(ETHERTYPE_IP);
+               break;
+
+       case Q_ARP:
+               b1 =  gen_linktype(ETHERTYPE_ARP);
+               break;
+
+       case Q_RARP:
+               b1 =  gen_linktype(ETHERTYPE_REVARP);
+               break;
+
+       case Q_LINK:
+               bpf_error("link layer applied in wrong context");
+
+       case Q_ATALK:
+               b1 =  gen_linktype(ETHERTYPE_ATALK);
+               break;
+
+       case Q_AARP:
+               b1 =  gen_linktype(ETHERTYPE_AARP);
+               break;
+
+       case Q_DECNET:
+               b1 =  gen_linktype(ETHERTYPE_DN);
+               break;
+
+       case Q_SCA:
+               b1 =  gen_linktype(ETHERTYPE_SCA);
+               break;
+
+       case Q_LAT:
+               b1 =  gen_linktype(ETHERTYPE_LAT);
+               break;
+
+       case Q_MOPDL:
+               b1 =  gen_linktype(ETHERTYPE_MOPDL);
+               break;
+
+       case Q_MOPRC:
+               b1 =  gen_linktype(ETHERTYPE_MOPRC);
+               break;
+
+#ifdef INET6
+       case Q_IPV6:
+               b1 = gen_linktype(ETHERTYPE_IPV6);
+               break;
+
+#ifndef IPPROTO_ICMPV6
+#define IPPROTO_ICMPV6 58
+#endif
+       case Q_ICMPV6:
+               b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
+               break;
+#endif /* INET6 */
+
+#ifndef IPPROTO_AH
+#define IPPROTO_AH     51
+#endif
+       case Q_AH:
+               b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP    50
+#endif
+       case Q_ESP:
+               b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
+#ifdef INET6
+               b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
+               gen_or(b0, b1);
+#endif
+               break;
+
+       case Q_ISO:
+               b1 = gen_linktype(LLCSAP_ISONS);
+               break;
+
+       case Q_ESIS:
+               b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+               break;
+
+       case Q_ISIS:
+               b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+               break;
+
+       case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
+               b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
+               b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
+               b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_LSP:
+               b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_SNP:
+               b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_CSNP:
+               b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_ISIS_PSNP:
+               b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+               b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+               gen_or(b0, b1);
+               break;
+
+       case Q_CLNP:
+               b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+               break;
+
+       case Q_STP:
+               b1 = gen_linktype(LLCSAP_8021D);
+               break;
+
+       case Q_IPX:
+               b1 = gen_linktype(LLCSAP_IPX);
+               break;
+
+       case Q_NETBEUI:
+               b1 = gen_linktype(LLCSAP_NETBEUI);
+               break;
+
+       case Q_RADIO:
+               bpf_error("'radio' is not a valid protocol type");
+
+       default:
+               abort();
+       }
+       return b1;
+}
+
+static struct block *
+gen_ipfrag()
+{
+       struct slist *s;
+       struct block *b;
+
+       /* not IPv4 frag other than the first frag */
+       s = gen_load_a(OR_NET, 6, BPF_H);
+       b = new_block(JMP(BPF_JSET));
+       b->s.k = 0x1fff;
+       b->stmts = s;
+       gen_not(b);
+
+       return b;
+}
+
+/*
+ * Generate a comparison to a port value in the transport-layer header
+ * at the specified offset from the beginning of that header.
+ *
+ * XXX - this handles a variable-length prefix preceding the link-layer
+ * header, such as the radiotap or AVS radio prefix, but doesn't handle
+ * variable-length link-layer headers (such as Token Ring or 802.11
+ * headers).
+ */
+static struct block *
+gen_portatom(off, v)
+       int off;
+       bpf_int32 v;
+{
+       return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
+}
+
+#ifdef INET6
+static struct block *
+gen_portatom6(off, v)
+       int off;
+       bpf_int32 v;
+{
+       return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
+}
+#endif/*INET6*/
+
+struct block *
+gen_portop(port, proto, dir)
+       int port, proto, dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip proto 'proto' and not a fragment other than the first fragment */
+       tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
+       b0 = gen_ipfrag();
+       gen_and(tmp, b0);
+
+       switch (dir) {
+       case Q_SRC:
+               b1 = gen_portatom(0, (bpf_int32)port);
+               break;
+
+       case Q_DST:
+               b1 = gen_portatom(2, (bpf_int32)port);
+               break;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               tmp = gen_portatom(0, (bpf_int32)port);
+               b1 = gen_portatom(2, (bpf_int32)port);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_AND:
+               tmp = gen_portatom(0, (bpf_int32)port);
+               b1 = gen_portatom(2, (bpf_int32)port);
+               gen_and(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+
+       return b1;
+}
+
+static struct block *
+gen_port(port, ip_proto, dir)
+       int port;
+       int ip_proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /*
+        * ether proto ip
+        *
+        * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+        * not LLC encapsulation with LLCSAP_IP.
+        *
+        * For IEEE 802 networks - which includes 802.5 token ring
+        * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+        * says that SNAP encapsulation is used, not LLC encapsulation
+        * with LLCSAP_IP.
+        *
+        * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+        * RFC 2225 say that SNAP encapsulation is used, not LLC
+        * encapsulation with LLCSAP_IP.
+        *
+        * So we always check for ETHERTYPE_IP.
+        */
+       b0 =  gen_linktype(ETHERTYPE_IP);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               b1 = gen_portop(port, ip_proto, dir);
+               break;
+
+       case PROTO_UNDEF:
+               tmp = gen_portop(port, IPPROTO_TCP, dir);
+               b1 = gen_portop(port, IPPROTO_UDP, dir);
+               gen_or(tmp, b1);
+               tmp = gen_portop(port, IPPROTO_SCTP, dir);
+               gen_or(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+
+#ifdef INET6
+struct block *
+gen_portop6(port, proto, dir)
+       int port, proto, dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip6 proto 'proto' */
+       /* XXX - catch the first fragment of a fragmented packet? */
+       b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+
+       switch (dir) {
+       case Q_SRC:
+               b1 = gen_portatom6(0, (bpf_int32)port);
+               break;
+
+       case Q_DST:
+               b1 = gen_portatom6(2, (bpf_int32)port);
+               break;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               tmp = gen_portatom6(0, (bpf_int32)port);
+               b1 = gen_portatom6(2, (bpf_int32)port);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_AND:
+               tmp = gen_portatom6(0, (bpf_int32)port);
+               b1 = gen_portatom6(2, (bpf_int32)port);
+               gen_and(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+
+       return b1;
+}
+
+static struct block *
+gen_port6(port, ip_proto, dir)
+       int port;
+       int ip_proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* link proto ip6 */
+       b0 =  gen_linktype(ETHERTYPE_IPV6);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               b1 = gen_portop6(port, ip_proto, dir);
+               break;
+
+       case PROTO_UNDEF:
+               tmp = gen_portop6(port, IPPROTO_TCP, dir);
+               b1 = gen_portop6(port, IPPROTO_UDP, dir);
+               gen_or(tmp, b1);
+               tmp = gen_portop6(port, IPPROTO_SCTP, dir);
+               gen_or(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+#endif /* INET6 */
+
+/* gen_portrange code */
+static struct block *
+gen_portrangeatom(off, v1, v2)
+       int off;
+       bpf_int32 v1, v2;
+{
+       struct block *b1, *b2;
+
+       if (v1 > v2) {
+               /*
+                * Reverse the order of the ports, so v1 is the lower one.
+                */
+               bpf_int32 vtemp;
+
+               vtemp = v1;
+               v1 = v2;
+               v2 = vtemp;
+       }
+
+       b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
+       b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
+
+       gen_and(b1, b2); 
+
+       return b2;
+}
+
+struct block *
+gen_portrangeop(port1, port2, proto, dir)
+       int port1, port2;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip proto 'proto' and not a fragment other than the first fragment */
+       tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
+       b0 = gen_ipfrag();
+       gen_and(tmp, b0);
+
+       switch (dir) {
+       case Q_SRC:
+               b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+               break;
+
+       case Q_DST:
+               b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+               break;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+               b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_AND:
+               tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+               b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+               gen_and(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+
+       return b1;
+}
+
+static struct block *
+gen_portrange(port1, port2, ip_proto, dir)
+       int port1, port2;
+       int ip_proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* link proto ip */
+       b0 =  gen_linktype(ETHERTYPE_IP);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               b1 = gen_portrangeop(port1, port2, ip_proto, dir);
+               break;
+
+       case PROTO_UNDEF:
+               tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
+               b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
+               gen_or(tmp, b1);
+               tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
+               gen_or(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+
+#ifdef INET6
+static struct block *
+gen_portrangeatom6(off, v1, v2)
+       int off;
+       bpf_int32 v1, v2;
+{
+       struct block *b1, *b2;
+
+       if (v1 > v2) {
+               /*
+                * Reverse the order of the ports, so v1 is the lower one.
+                */
+               bpf_int32 vtemp;
+
+               vtemp = v1;
+               v1 = v2;
+               v2 = vtemp;
+       }
+
+       b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
+       b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
+
+       gen_and(b1, b2); 
+
+       return b2;
+}
+
+struct block *
+gen_portrangeop6(port1, port2, proto, dir)
+       int port1, port2;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip6 proto 'proto' */
+       /* XXX - catch the first fragment of a fragmented packet? */
+       b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+
+       switch (dir) {
+       case Q_SRC:
+               b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+               break;
+
+       case Q_DST:
+               b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+               break;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+               b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_AND:
+               tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+               b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+               gen_and(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+
+       return b1;
+}
+
+static struct block *
+gen_portrange6(port1, port2, ip_proto, dir)
+       int port1, port2;
+       int ip_proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* link proto ip6 */
+       b0 =  gen_linktype(ETHERTYPE_IPV6);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
+               break;
+
+       case PROTO_UNDEF:
+               tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
+               b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
+               gen_or(tmp, b1);
+               tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
+               gen_or(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+#endif /* INET6 */
+
+static int
+lookup_proto(name, proto)
+       register const char *name;
+       register int proto;
+{
+       register int v;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_IP:
+       case Q_IPV6:
+               v = pcap_nametoproto(name);
+               if (v == PROTO_UNDEF)
+                       bpf_error("unknown ip proto '%s'", name);
+               break;
+
+       case Q_LINK:
+               /* XXX should look up h/w protocol type based on linktype */
+               v = pcap_nametoeproto(name);
+               if (v == PROTO_UNDEF) {
+                       v = pcap_nametollc(name);
+                       if (v == PROTO_UNDEF)
+                               bpf_error("unknown ether proto '%s'", name);
+               }
+               break;
+
+       case Q_ISO:
+               if (strcmp(name, "esis") == 0)
+                       v = ISO9542_ESIS;
+               else if (strcmp(name, "isis") == 0)
+                       v = ISO10589_ISIS;
+               else if (strcmp(name, "clnp") == 0)
+                       v = ISO8473_CLNP;
+               else
+                       bpf_error("unknown osi proto '%s'", name);
+               break;
+
+       default:
+               v = PROTO_UNDEF;
+               break;
+       }
+       return v;
+}
+
+#if 0
+struct stmt *
+gen_joinsp(s, n)
+       struct stmt **s;
+       int n;
+{
+       return NULL;
+}
+#endif
+
+static struct block *
+gen_protochain(v, proto, dir)
+       int v;
+       int proto;
+       int dir;
+{
+#ifdef NO_PROTOCHAIN
+       return gen_proto(v, proto, dir);
+#else
+       struct block *b0, *b;
+       struct slist *s[100];
+       int fix2, fix3, fix4, fix5;
+       int ahcheck, again, end;
+       int i, max;
+       int reg2 = alloc_reg();
+
+       memset(s, 0, sizeof(s));
+       fix2 = fix3 = fix4 = fix5 = 0;
+
+       switch (proto) {
+       case Q_IP:
+       case Q_IPV6:
+               break;
+       case Q_DEFAULT:
+               b0 = gen_protochain(v, Q_IP, dir);
+               b = gen_protochain(v, Q_IPV6, dir);
+               gen_or(b0, b);
+               return b;
+       default:
+               bpf_error("bad protocol applied for 'protochain'");
+               /*NOTREACHED*/
+       }
+
+       /*
+        * We don't handle variable-length prefixes before the link-layer
+        * header, or variable-length link-layer headers, here yet.
+        * We might want to add BPF instructions to do the protochain
+        * work, to simplify that and, on platforms that have a BPF
+        * interpreter with the new instructions, let the filtering
+        * be done in the kernel.  (We already require a modified BPF
+        * engine to do the protochain stuff, to support backward
+        * branches, and backward branch support is unlikely to appear
+        * in kernel BPF engines.)
+        */
+       switch (linktype) {
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+       case DLT_PPI:
+               bpf_error("'protochain' not supported with 802.11");
+       }
+
+       no_optimize = 1; /*this code is not compatible with optimzer yet */
+
+       /*
+        * s[0] is a dummy entry to protect other BPF insn from damage
+        * by s[fix] = foo with uninitialized variable "fix".  It is somewhat
+        * hard to find interdependency made by jump table fixup.
+        */
+       i = 0;
+       s[i] = new_stmt(0);     /*dummy*/
+       i++;
+
+       switch (proto) {
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+
+               /* A = ip->ip_p */
+               s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s[i]->s.k = off_macpl + off_nl + 9;
+               i++;
+               /* X = ip->ip_hl << 2 */
+               s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+               s[i]->s.k = off_macpl + off_nl;
+               i++;
+               break;
+#ifdef INET6
+       case Q_IPV6:
+               b0 = gen_linktype(ETHERTYPE_IPV6);
+
+               /* A = ip6->ip_nxt */
+               s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s[i]->s.k = off_macpl + off_nl + 6;
+               i++;
+               /* X = sizeof(struct ip6_hdr) */
+               s[i] = new_stmt(BPF_LDX|BPF_IMM);
+               s[i]->s.k = 40;
+               i++;
+               break;
+#endif
+       default:
+               bpf_error("unsupported proto to gen_protochain");
+               /*NOTREACHED*/
+       }
+
+       /* again: if (A == v) goto end; else fall through; */
+       again = i;
+       s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+       s[i]->s.k = v;
+       s[i]->s.jt = NULL;              /*later*/
+       s[i]->s.jf = NULL;              /*update in next stmt*/
+       fix5 = i;
+       i++;
+
+#ifndef IPPROTO_NONE
+#define IPPROTO_NONE   59
+#endif
+       /* if (A == IPPROTO_NONE) goto end */
+       s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+       s[i]->s.jt = NULL;      /*later*/
+       s[i]->s.jf = NULL;      /*update in next stmt*/
+       s[i]->s.k = IPPROTO_NONE;
+       s[fix5]->s.jf = s[i];
+       fix2 = i;
+       i++;
+
+#ifdef INET6
+       if (proto == Q_IPV6) {
+               int v6start, v6end, v6advance, j;
+
+               v6start = i;
+               /* if (A == IPPROTO_HOPOPTS) goto v6advance */
+               s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+               s[i]->s.jt = NULL;      /*later*/
+               s[i]->s.jf = NULL;      /*update in next stmt*/
+               s[i]->s.k = IPPROTO_HOPOPTS;
+               s[fix2]->s.jf = s[i];
+               i++;
+               /* if (A == IPPROTO_DSTOPTS) goto v6advance */
+               s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+               s[i]->s.jt = NULL;      /*later*/
+               s[i]->s.jf = NULL;      /*update in next stmt*/
+               s[i]->s.k = IPPROTO_DSTOPTS;
+               i++;
+               /* if (A == IPPROTO_ROUTING) goto v6advance */
+               s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+               s[i]->s.jt = NULL;      /*later*/
+               s[i]->s.jf = NULL;      /*update in next stmt*/
+               s[i]->s.k = IPPROTO_ROUTING;
+               i++;
+               /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
+               s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+               s[i]->s.jt = NULL;      /*later*/
+               s[i]->s.jf = NULL;      /*later*/
+               s[i]->s.k = IPPROTO_FRAGMENT;
+               fix3 = i;
+               v6end = i;
+               i++;
+
+               /* v6advance: */
+               v6advance = i;
+
+               /*
+                * in short,
+                * A = P[X + packet head];
+                * X = X + (P[X + packet head + 1] + 1) * 8;
+                */
+               /* A = P[X + packet head] */
+               s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
+               s[i]->s.k = off_macpl + off_nl;
+               i++;
+               /* MEM[reg2] = A */
+               s[i] = new_stmt(BPF_ST);
+               s[i]->s.k = reg2;
+               i++;
+               /* A = P[X + packet head + 1]; */
+               s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
+               s[i]->s.k = off_macpl + off_nl + 1;
+               i++;
+               /* A += 1 */
+               s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+               s[i]->s.k = 1;
+               i++;
+               /* A *= 8 */
+               s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+               s[i]->s.k = 8;
+               i++;
+               /* A += X */
+               s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
+               s[i]->s.k = 0;
+               i++;
+               /* X = A; */
+               s[i] = new_stmt(BPF_MISC|BPF_TAX);
+               i++;
+               /* A = MEM[reg2] */
+               s[i] = new_stmt(BPF_LD|BPF_MEM);
+               s[i]->s.k = reg2;
+               i++;
+
+               /* goto again; (must use BPF_JA for backward jump) */
+               s[i] = new_stmt(BPF_JMP|BPF_JA);
+               s[i]->s.k = again - i - 1;
+               s[i - 1]->s.jf = s[i];
+               i++;
+
+               /* fixup */
+               for (j = v6start; j <= v6end; j++)
+                       s[j]->s.jt = s[v6advance];
+       } else
+#endif
+       {
+               /* nop */
+               s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+               s[i]->s.k = 0;
+               s[fix2]->s.jf = s[i];
+               i++;
+       }
+
+       /* ahcheck: */
+       ahcheck = i;
+       /* if (A == IPPROTO_AH) then fall through; else goto end; */
+       s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+       s[i]->s.jt = NULL;      /*later*/
+       s[i]->s.jf = NULL;      /*later*/
+       s[i]->s.k = IPPROTO_AH;
+       if (fix3)
+               s[fix3]->s.jf = s[ahcheck];
+       fix4 = i;
+       i++;
+
+       /*
+        * in short,
+        * A = P[X];
+        * X = X + (P[X + 1] + 2) * 4;
+        */
+       /* A = X */
+       s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+       i++;
+       /* A = P[X + packet head]; */
+       s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
+       s[i]->s.k = off_macpl + off_nl;
+       i++;
+       /* MEM[reg2] = A */
+       s[i] = new_stmt(BPF_ST);
+       s[i]->s.k = reg2;
+       i++;
+       /* A = X */
+       s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+       i++;
+       /* A += 1 */
+       s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+       s[i]->s.k = 1;
+       i++;
+       /* X = A */
+       s[i] = new_stmt(BPF_MISC|BPF_TAX);
+       i++;
+       /* A = P[X + packet head] */
+       s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
+       s[i]->s.k = off_macpl + off_nl;
+       i++;
+       /* A += 2 */
+       s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+       s[i]->s.k = 2;
+       i++;
+       /* A *= 4 */
+       s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+       s[i]->s.k = 4;
+       i++;
+       /* X = A; */
+       s[i] = new_stmt(BPF_MISC|BPF_TAX);
+       i++;
+       /* A = MEM[reg2] */
+       s[i] = new_stmt(BPF_LD|BPF_MEM);
+       s[i]->s.k = reg2;
+       i++;
+
+       /* goto again; (must use BPF_JA for backward jump) */
+       s[i] = new_stmt(BPF_JMP|BPF_JA);
+       s[i]->s.k = again - i - 1;
+       i++;
+
+       /* end: nop */
+       end = i;
+       s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+       s[i]->s.k = 0;
+       s[fix2]->s.jt = s[end];
+       s[fix4]->s.jf = s[end];
+       s[fix5]->s.jt = s[end];
+       i++;
+
+       /*
+        * make slist chain
+        */
+       max = i;
+       for (i = 0; i < max - 1; i++)
+               s[i]->next = s[i + 1];
+       s[max - 1]->next = NULL;
+
+       /*
+        * emit final check
+        */
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s[1];        /*remember, s[0] is dummy*/
+       b->s.k = v;
+
+       free_reg(reg2);
+
+       gen_and(b0, b);
+       return b;
+#endif
+}
+
+static struct block *
+gen_check_802_11_data_frame()
+{
+       struct slist *s;
+       struct block *b0, *b1;
+
+       /*
+        * A data frame has the 0x08 bit (b3) in the frame control field set
+        * and the 0x04 bit (b2) clear.
+        */
+       s = gen_load_a(OR_LINK, 0, BPF_B);
+       b0 = new_block(JMP(BPF_JSET));
+       b0->s.k = 0x08;
+       b0->stmts = s;
+       
+       s = gen_load_a(OR_LINK, 0, BPF_B);
+       b1 = new_block(JMP(BPF_JSET));
+       b1->s.k = 0x04;
+       b1->stmts = s;
+       gen_not(b1);
+
+       gen_and(b1, b0);
+
+       return b0;
+}
+
+/*
+ * Generate code that checks whether the packet is a packet for protocol
+ * <proto> and whether the type field in that protocol's header has
+ * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
+ * IP packet and checks the protocol number in the IP header against <v>.
+ *
+ * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
+ * against Q_IP and Q_IPV6.
+ */
+static struct block *
+gen_proto(v, proto, dir)
+       int v;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1;
+#ifdef INET6
+#ifndef CHASE_CHAIN
+       struct block *b2;
+#endif
+#endif
+
+       if (dir != Q_DEFAULT)
+               bpf_error("direction applied to 'proto'");
+
+       switch (proto) {
+       case Q_DEFAULT:
+#ifdef INET6
+               b0 = gen_proto(v, Q_IP, dir);
+               b1 = gen_proto(v, Q_IPV6, dir);
+               gen_or(b0, b1);
+               return b1;
+#else
+               /*FALLTHROUGH*/
+#endif
+       case Q_IP:
+               /*
+                * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+                * not LLC encapsulation with LLCSAP_IP.
+                *
+                * For IEEE 802 networks - which includes 802.5 token ring
+                * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+                * says that SNAP encapsulation is used, not LLC encapsulation
+                * with LLCSAP_IP.
+                *
+                * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+                * RFC 2225 say that SNAP encapsulation is used, not LLC
+                * encapsulation with LLCSAP_IP.
+                *
+                * So we always check for ETHERTYPE_IP.
+                */
+               b0 = gen_linktype(ETHERTYPE_IP);
+#ifndef CHASE_CHAIN
+               b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
+#else
+               b1 = gen_protochain(v, Q_IP);
+#endif
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ISO:
+               switch (linktype) {
+
+               case DLT_FRELAY:
+                       /*
+                        * Frame Relay packets typically have an OSI
+                        * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
+                        * generates code to check for all the OSI
+                        * NLPIDs, so calling it and then adding a check
+                        * for the particular NLPID for which we're
+                        * looking is bogus, as we can just check for
+                        * the NLPID.
+                        *
+                        * What we check for is the NLPID and a frame
+                        * control field value of UI, i.e. 0x03 followed
+                        * by the NLPID.
+                        *
+                        * XXX - assumes a 2-byte Frame Relay header with
+                        * DLCI and flags.  What if the address is longer?
+                        *
+                        * XXX - what about SNAP-encapsulated frames?
+                        */
+                       return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v);
+                       /*NOTREACHED*/
+                       break;
+
+               case DLT_C_HDLC:
+                       /*
+                        * Cisco uses an Ethertype lookalike - for OSI,
+                        * it's 0xfefe.
+                        */
+                       b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
+                       /* OSI in C-HDLC is stuffed with a fudge byte */
+                       b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
+                       gen_and(b0, b1);
+                       return b1;
+
+               default:
+                       b0 = gen_linktype(LLCSAP_ISONS);
+                       b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
+                       gen_and(b0, b1);
+                       return b1;
+               }
+
+       case Q_ISIS:
+               b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+               /*
+                * 4 is the offset of the PDU type relative to the IS-IS
+                * header.
+                */
+               b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ARP:
+               bpf_error("arp does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_RARP:
+               bpf_error("rarp does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_ATALK:
+               bpf_error("atalk encapsulation is not specifiable");
+               /* NOTREACHED */
+
+       case Q_DECNET:
+               bpf_error("decnet encapsulation is not specifiable");
+               /* NOTREACHED */
+
+       case Q_SCA:
+               bpf_error("sca does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_LAT:
+               bpf_error("lat does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_MOPRC:
+               bpf_error("moprc does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_MOPDL:
+               bpf_error("mopdl does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_LINK:
+               return gen_linktype(v);
+
+       case Q_UDP:
+               bpf_error("'udp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_TCP:
+               bpf_error("'tcp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_SCTP:
+               bpf_error("'sctp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_ICMP:
+               bpf_error("'icmp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_IGMP:
+               bpf_error("'igmp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_IGRP:
+               bpf_error("'igrp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_PIM:
+               bpf_error("'pim proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_VRRP:
+               bpf_error("'vrrp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_CARP:
+               bpf_error("'carp proto' is bogus");
+               /* NOTREACHED */
+
+#ifdef INET6
+       case Q_IPV6:
+               b0 = gen_linktype(ETHERTYPE_IPV6);
+#ifndef CHASE_CHAIN
+               /*
+                * Also check for a fragment header before the final
+                * header.
+                */
+               b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
+               b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
+               gen_and(b2, b1);
+               b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+               gen_or(b2, b1);
+#else
+               b1 = gen_protochain(v, Q_IPV6);
+#endif
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ICMPV6:
+               bpf_error("'icmp6 proto' is bogus");
+#endif /* INET6 */
+
+       case Q_AH:
+               bpf_error("'ah proto' is bogus");
+
+       case Q_ESP:
+               bpf_error("'ah proto' is bogus");
+
+       case Q_STP:
+               bpf_error("'stp proto' is bogus");
+
+       case Q_IPX:
+               bpf_error("'ipx proto' is bogus");
+
+       case Q_NETBEUI:
+               bpf_error("'netbeui proto' is bogus");
+
+       case Q_RADIO:
+               bpf_error("'radio proto' is bogus");
+
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+}
+
+struct block *
+gen_scode(name, q)
+       register const char *name;
+       struct qual q;
+{
+       int proto = q.proto;
+       int dir = q.dir;
+       int tproto;
+       u_char *eaddr;
+       bpf_u_int32 mask, addr;
+#ifndef INET6
+       bpf_u_int32 **alist;
+#else
+       int tproto6;
+       struct sockaddr_in *sin4;
+       struct sockaddr_in6 *sin6;
+       struct addrinfo *res, *res0;
+       struct in6_addr mask128;
+#endif /*INET6*/
+       struct block *b, *tmp;
+       int port, real_proto;
+       int port1, port2;
+
+       switch (q.addr) {
+
+       case Q_NET:
+               addr = pcap_nametonetaddr(name);
+               if (addr == 0)
+                       bpf_error("unknown network '%s'", name);
+               /* Left justify network addr and calculate its network mask */
+               mask = 0xffffffff;
+               while (addr && (addr & 0xff000000) == 0) {
+                       addr <<= 8;
+                       mask <<= 8;
+               }
+               return gen_host(addr, mask, proto, dir, q.addr);
+
+       case Q_DEFAULT:
+       case Q_HOST:
+               if (proto == Q_LINK) {
+                       switch (linktype) {
+
+                       case DLT_EN10MB:
+                       case DLT_NETANALYZER:
+                       case DLT_NETANALYZER_TRANSPARENT:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown ether host '%s'", name);
+                               b = gen_ehostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
+
+                       case DLT_FDDI:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown FDDI host '%s'", name);
+                               b = gen_fhostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
+
+                       case DLT_IEEE802:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown token ring host '%s'", name);
+                               b = gen_thostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
+
+                       case DLT_IEEE802_11:
+                       case DLT_PRISM_HEADER:
+                       case DLT_IEEE802_11_RADIO_AVS:
+                       case DLT_IEEE802_11_RADIO:
+                       case DLT_PPI:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown 802.11 host '%s'", name);
+                               b = gen_wlanhostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
+
+                       case DLT_IP_OVER_FC:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown Fibre Channel host '%s'", name);
+                               b = gen_ipfchostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
+
+                       case DLT_SUNATM:
+                               if (!is_lane)
+                                       break;
+
+                               /*
+                                * Check that the packet doesn't begin
+                                * with an LE Control marker.  (We've
+                                * already generated a test for LANE.)
+                                */
+                               tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+                                   BPF_H, 0xFF00);
+                               gen_not(tmp);
+
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown ether host '%s'", name);
+                               b = gen_ehostop(eaddr, dir);
+                               gen_and(tmp, b);
+                               free(eaddr);
+                               return b;
+                       }
+
+                       bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
+               } else if (proto == Q_DECNET) {
+                       unsigned short dn_addr = __pcap_nametodnaddr(name);
+                       /*
+                        * I don't think DECNET hosts can be multihomed, so
+                        * there is no need to build up a list of addresses
+                        */
+                       return (gen_host(dn_addr, 0, proto, dir, q.addr));
+               } else {
+#ifndef INET6
+                       alist = pcap_nametoaddr(name);
+                       if (alist == NULL || *alist == NULL)
+                               bpf_error("unknown host '%s'", name);
+                       tproto = proto;
+                       if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT)
+                               tproto = Q_IP;
+                       b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
+                       while (*alist) {
+                               tmp = gen_host(**alist++, 0xffffffff,
+                                              tproto, dir, q.addr);
+                               gen_or(b, tmp);
+                               b = tmp;
+                       }
+                       return b;
+#else
+                       memset(&mask128, 0xff, sizeof(mask128));
+                       res0 = res = pcap_nametoaddrinfo(name);
+                       if (res == NULL)
+                               bpf_error("unknown host '%s'", name);
+                       ai = res;
+                       b = tmp = NULL;
+                       tproto = tproto6 = proto;
+                       if (off_linktype == -1 && tproto == Q_DEFAULT) {
+                               tproto = Q_IP;
+                               tproto6 = Q_IPV6;
+                       }
+                       for (res = res0; res; res = res->ai_next) {
+                               switch (res->ai_family) {
+                               case AF_INET:
+                                       if (tproto == Q_IPV6)
+                                               continue;
+
+                                       sin4 = (struct sockaddr_in *)
+                                               res->ai_addr;
+                                       tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
+                                               0xffffffff, tproto, dir, q.addr);
+                                       break;
+                               case AF_INET6:
+                                       if (tproto6 == Q_IP)
+                                               continue;
+
+                                       sin6 = (struct sockaddr_in6 *)
+                                               res->ai_addr;
+                                       tmp = gen_host6(&sin6->sin6_addr,
+                                               &mask128, tproto6, dir, q.addr);
+                                       break;
+                               default:
+                                       continue;
+                               }
+                               if (b)
+                                       gen_or(b, tmp);
+                               b = tmp;
+                       }
+                       ai = NULL;
+                       freeaddrinfo(res0);
+                       if (b == NULL) {
+                               bpf_error("unknown host '%s'%s", name,
+                                   (proto == Q_DEFAULT)
+                                       ? ""
+                                       : " for specified address family");
+                       }
+                       return b;
+#endif /*INET6*/
+               }
+
+       case Q_PORT:
+               if (proto != Q_DEFAULT &&
+                   proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
+                       bpf_error("illegal qualifier of 'port'");
+               if (pcap_nametoport(name, &port, &real_proto) == 0)
+                       bpf_error("unknown port '%s'", name);
+               if (proto == Q_UDP) {
+                       if (real_proto == IPPROTO_TCP)
+                               bpf_error("port '%s' is tcp", name);
+                       else if (real_proto == IPPROTO_SCTP)
+                               bpf_error("port '%s' is sctp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_UDP;
+               }
+               if (proto == Q_TCP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port '%s' is udp", name);
+
+                       else if (real_proto == IPPROTO_SCTP)
+                               bpf_error("port '%s' is sctp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_TCP;
+               }
+               if (proto == Q_SCTP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port '%s' is udp", name);
+
+                       else if (real_proto == IPPROTO_TCP)
+                               bpf_error("port '%s' is tcp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_SCTP;
+               }
+               if (port < 0)
+                       bpf_error("illegal port number %d < 0", port);
+               if (port > 65535)
+                       bpf_error("illegal port number %d > 65535", port);
+#ifndef INET6
+               return gen_port(port, real_proto, dir);
+#else
+               b = gen_port(port, real_proto, dir);
+               gen_or(gen_port6(port, real_proto, dir), b);
+               return b;
+#endif /* INET6 */
+
+       case Q_PORTRANGE:
+               if (proto != Q_DEFAULT &&
+                   proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
+                       bpf_error("illegal qualifier of 'portrange'");
+               if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0) 
+                       bpf_error("unknown port in range '%s'", name);
+               if (proto == Q_UDP) {
+                       if (real_proto == IPPROTO_TCP)
+                               bpf_error("port in range '%s' is tcp", name);
+                       else if (real_proto == IPPROTO_SCTP)
+                               bpf_error("port in range '%s' is sctp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_UDP;
+               }
+               if (proto == Q_TCP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port in range '%s' is udp", name);
+                       else if (real_proto == IPPROTO_SCTP)
+                               bpf_error("port in range '%s' is sctp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_TCP;
+               }
+               if (proto == Q_SCTP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port in range '%s' is udp", name);
+                       else if (real_proto == IPPROTO_TCP)
+                               bpf_error("port in range '%s' is tcp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_SCTP;      
+               }
+               if (port1 < 0)
+                       bpf_error("illegal port number %d < 0", port1);
+               if (port1 > 65535)
+                       bpf_error("illegal port number %d > 65535", port1);
+               if (port2 < 0)
+                       bpf_error("illegal port number %d < 0", port2);
+               if (port2 > 65535)
+                       bpf_error("illegal port number %d > 65535", port2);
+
+#ifndef INET6
+               return gen_portrange(port1, port2, real_proto, dir);
+#else
+               b = gen_portrange(port1, port2, real_proto, dir);
+               gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
+               return b;
+#endif /* INET6 */
+
+       case Q_GATEWAY:
+#ifndef INET6
+               eaddr = pcap_ether_hostton(name);
+               if (eaddr == NULL)
+                       bpf_error("unknown ether host: %s", name);
+
+               alist = pcap_nametoaddr(name);
+               if (alist == NULL || *alist == NULL)
+                       bpf_error("unknown host '%s'", name);
+               b = gen_gateway(eaddr, alist, proto, dir);
+               free(eaddr);
+               return b;
+#else
+               bpf_error("'gateway' not supported in this configuration");
+#endif /*INET6*/
+
+       case Q_PROTO:
+               real_proto = lookup_proto(name, proto);
+               if (real_proto >= 0)
+                       return gen_proto(real_proto, proto, dir);
+               else
+                       bpf_error("unknown protocol: %s", name);
+
+       case Q_PROTOCHAIN:
+               real_proto = lookup_proto(name, proto);
+               if (real_proto >= 0)
+                       return gen_protochain(real_proto, proto, dir);
+               else
+                       bpf_error("unknown protocol: %s", name);
+
+       case Q_UNDEF:
+               syntax();
+               /* NOTREACHED */
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+struct block *
+gen_mcode(s1, s2, masklen, q)
+       register const char *s1, *s2;
+       register int masklen;
+       struct qual q;
+{
+       register int nlen, mlen;
+       bpf_u_int32 n, m;
+
+       nlen = __pcap_atoin(s1, &n);
+       /* Promote short ipaddr */
+       n <<= 32 - nlen;
+
+       if (s2 != NULL) {
+               mlen = __pcap_atoin(s2, &m);
+               /* Promote short ipaddr */
+               m <<= 32 - mlen;
+               if ((n & ~m) != 0)
+                       bpf_error("non-network bits set in \"%s mask %s\"",
+                           s1, s2);
+       } else {
+               /* Convert mask len to mask */
+               if (masklen > 32)
+                       bpf_error("mask length must be <= 32");
+               if (masklen == 0) {
+                       /*
+                        * X << 32 is not guaranteed by C to be 0; it's
+                        * undefined.
+                        */
+                       m = 0;
+               } else
+                       m = 0xffffffff << (32 - masklen);
+               if ((n & ~m) != 0)
+                       bpf_error("non-network bits set in \"%s/%d\"",
+                           s1, masklen);
+       }
+
+       switch (q.addr) {
+
+       case Q_NET:
+               return gen_host(n, m, q.proto, q.dir, q.addr);
+
+       default:
+               bpf_error("Mask syntax for networks only");
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+       return NULL;
+}
+
+struct block *
+gen_ncode(s, v, q)
+       register const char *s;
+       bpf_u_int32 v;
+       struct qual q;
+{
+       bpf_u_int32 mask;
+       int proto = q.proto;
+       int dir = q.dir;
+       register int vlen;
+
+       if (s == NULL)
+               vlen = 32;
+       else if (q.proto == Q_DECNET)
+               vlen = __pcap_atodn(s, &v);
+       else
+               vlen = __pcap_atoin(s, &v);
+
+       switch (q.addr) {
+
+       case Q_DEFAULT:
+       case Q_HOST:
+       case Q_NET:
+               if (proto == Q_DECNET)
+                       return gen_host(v, 0, proto, dir, q.addr);
+               else if (proto == Q_LINK) {
+                       bpf_error("illegal link layer address");
+               } else {
+                       mask = 0xffffffff;
+                       if (s == NULL && q.addr == Q_NET) {
+                               /* Promote short net number */
+                               while (v && (v & 0xff000000) == 0) {
+                                       v <<= 8;
+                                       mask <<= 8;
+                               }
+                       } else {
+                               /* Promote short ipaddr */
+                               v <<= 32 - vlen;
+                               mask <<= 32 - vlen;
+                       }
+                       return gen_host(v, mask, proto, dir, q.addr);
+               }
+
+       case Q_PORT:
+               if (proto == Q_UDP)
+                       proto = IPPROTO_UDP;
+               else if (proto == Q_TCP)
+                       proto = IPPROTO_TCP;
+               else if (proto == Q_SCTP)
+                       proto = IPPROTO_SCTP;
+               else if (proto == Q_DEFAULT)
+                       proto = PROTO_UNDEF;
+               else
+                       bpf_error("illegal qualifier of 'port'");
+
+               if (v > 65535)
+                       bpf_error("illegal port number %u > 65535", v);
+
+#ifndef INET6
+               return gen_port((int)v, proto, dir);
+#else
+           {
+               struct block *b;
+               b = gen_port((int)v, proto, dir);
+               gen_or(gen_port6((int)v, proto, dir), b);
+               return b;
+           }
+#endif /* INET6 */
+
+       case Q_PORTRANGE:
+               if (proto == Q_UDP)
+                       proto = IPPROTO_UDP;
+               else if (proto == Q_TCP)
+                       proto = IPPROTO_TCP;
+               else if (proto == Q_SCTP)
+                       proto = IPPROTO_SCTP;
+               else if (proto == Q_DEFAULT)
+                       proto = PROTO_UNDEF;
+               else
+                       bpf_error("illegal qualifier of 'portrange'");
+
+               if (v > 65535)
+                       bpf_error("illegal port number %u > 65535", v);
+
+#ifndef INET6
+               return gen_portrange((int)v, (int)v, proto, dir);
+#else
+           {
+               struct block *b;
+               b = gen_portrange((int)v, (int)v, proto, dir);
+               gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
+               return b;
+           }
+#endif /* INET6 */
+
+       case Q_GATEWAY:
+               bpf_error("'gateway' requires a name");
+               /* NOTREACHED */
+
+       case Q_PROTO:
+               return gen_proto((int)v, proto, dir);
+
+       case Q_PROTOCHAIN:
+               return gen_protochain((int)v, proto, dir);
+
+       case Q_UNDEF:
+               syntax();
+               /* NOTREACHED */
+
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+}
+
+#ifdef INET6
+struct block *
+gen_mcode6(s1, s2, masklen, q)
+       register const char *s1, *s2;
+       register int masklen;
+       struct qual q;
+{
+       struct addrinfo *res;
+       struct in6_addr *addr;
+       struct in6_addr mask;
+       struct block *b;
+       u_int32_t *a, *m;
+
+       if (s2)
+               bpf_error("no mask %s supported", s2);
+
+       res = pcap_nametoaddrinfo(s1);
+       if (!res)
+               bpf_error("invalid ip6 address %s", s1);
+       ai = res;
+       if (res->ai_next)
+               bpf_error("%s resolved to multiple address", s1);
+       addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+
+       if (sizeof(mask) * 8 < masklen)
+               bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+       memset(&mask, 0, sizeof(mask));
+       memset(&mask, 0xff, masklen / 8);
+       if (masklen % 8) {
+               mask.s6_addr[masklen / 8] =
+                       (0xff << (8 - masklen % 8)) & 0xff;
+       }
+
+       a = (u_int32_t *)addr;
+       m = (u_int32_t *)&mask;
+       if ((a[0] & ~m[0]) || (a[1] & ~m[1])
+        || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
+               bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
+       }
+
+       switch (q.addr) {
+
+       case Q_DEFAULT:
+       case Q_HOST:
+               if (masklen != 128)
+                       bpf_error("Mask syntax for networks only");
+               /* FALLTHROUGH */
+
+       case Q_NET:
+               b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
+               ai = NULL;
+               freeaddrinfo(res);
+               return b;
+
+       default:
+               bpf_error("invalid qualifier against IPv6 address");
+               /* NOTREACHED */
+       }
+       return NULL;
+}
+#endif /*INET6*/
+
+struct block *
+gen_ecode(eaddr, q)
+       register const u_char *eaddr;
+       struct qual q;
+{
+       struct block *b, *tmp;
+
+       if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+               switch (linktype) {
+               case DLT_EN10MB:
+               case DLT_NETANALYZER:
+               case DLT_NETANALYZER_TRANSPARENT:
+                       return gen_ehostop(eaddr, (int)q.dir);
+               case DLT_FDDI:
+                       return gen_fhostop(eaddr, (int)q.dir);
+               case DLT_IEEE802:
+                       return gen_thostop(eaddr, (int)q.dir);
+               case DLT_IEEE802_11:
+               case DLT_PRISM_HEADER:
+               case DLT_IEEE802_11_RADIO_AVS:
+               case DLT_IEEE802_11_RADIO:
+               case DLT_PPI:
+                       return gen_wlanhostop(eaddr, (int)q.dir);
+               case DLT_SUNATM:
+                       if (is_lane) {
+                               /*
+                                * Check that the packet doesn't begin with an
+                                * LE Control marker.  (We've already generated
+                                * a test for LANE.)
+                                */
+                               tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
+                                       0xFF00);
+                               gen_not(tmp);
+
+                               /*
+                                * Now check the MAC address.
+                                */
+                               b = gen_ehostop(eaddr, (int)q.dir);
+                               gen_and(tmp, b);
+                               return b;
+                       }
+                       break;
+               case DLT_IP_OVER_FC:
+                       return gen_ipfchostop(eaddr, (int)q.dir);
+               default:
+                       bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+                       break;
+               }
+       }
+       bpf_error("ethernet address used in non-ether expression");
+       /* NOTREACHED */
+       return NULL;
+}
+
+void
+sappend(s0, s1)
+       struct slist *s0, *s1;
+{
+       /*
+        * This is definitely not the best way to do this, but the
+        * lists will rarely get long.
+        */
+       while (s0->next)
+               s0 = s0->next;
+       s0->next = s1;
+}
+
+static struct slist *
+xfer_to_x(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = new_stmt(BPF_LDX|BPF_MEM);
+       s->s.k = a->regno;
+       return s;
+}
+
+static struct slist *
+xfer_to_a(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_MEM);
+       s->s.k = a->regno;
+       return s;
+}
+
+/*
+ * Modify "index" to use the value stored into its register as an
+ * offset relative to the beginning of the header for the protocol
+ * "proto", and allocate a register and put an item "size" bytes long
+ * (1, 2, or 4) at that offset into that register, making it the register
+ * for "index".
+ */
+struct arth *
+gen_load(proto, inst, size)
+       int proto;
+       struct arth *inst;
+       int size;
+{
+       struct slist *s, *tmp;
+       struct block *b;
+       int regno = alloc_reg();
+
+       free_reg(inst->regno);
+       switch (size) {
+
+       default:
+               bpf_error("data size must be 1, 2, or 4");
+
+       case 1:
+               size = BPF_B;
+               break;
+
+       case 2:
+               size = BPF_H;
+               break;
+
+       case 4:
+               size = BPF_W;
+               break;
+       }
+       switch (proto) {
+       default:
+               bpf_error("unsupported index operation");
+
+       case Q_RADIO:
+               /*
+                * The offset is relative to the beginning of the packet
+                * data, if we have a radio header.  (If we don't, this
+                * is an error.)
+                */
+               if (linktype != DLT_IEEE802_11_RADIO_AVS &&
+                   linktype != DLT_IEEE802_11_RADIO &&
+                   linktype != DLT_PRISM_HEADER)
+                       bpf_error("radio information not present in capture");
+
+               /*
+                * Load into the X register the offset computed into the
+                * register specified by "index".
+                */
+               s = xfer_to_x(inst);
+
+               /*
+                * Load the item at that offset.
+                */
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               sappend(s, tmp);
+               sappend(inst->s, s);
+               break;
+
+       case Q_LINK:
+               /*
+                * The offset is relative to the beginning of
+                * the link-layer header.
+                *
+                * XXX - what about ATM LANE?  Should the index be
+                * relative to the beginning of the AAL5 frame, so
+                * that 0 refers to the beginning of the LE Control
+                * field, or relative to the beginning of the LAN
+                * frame, so that 0 refers, for Ethernet LANE, to
+                * the beginning of the destination address?
+                */
+               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.  Add to it the offset computed
+                * into the register specified by "index", and move that
+                * into the X register.  Otherwise, just load into the X
+                * register the offset computed into the register specified
+                * by "index".
+                */
+               if (s != NULL) {
+                       sappend(s, xfer_to_a(inst));
+                       sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
+                       sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+               } else
+                       s = xfer_to_x(inst);
+
+               /*
+                * Load the item at the sum of the offset we've put in the
+                * X register and the offset of the start of the link
+                * layer header (which is 0 if the radio header is
+                * variable-length; that header length is what we put
+                * into the X register and then added to the index).
+                */
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               tmp->s.k = off_ll;
+               sappend(s, tmp);
+               sappend(inst->s, s);
+               break;
+
+       case Q_IP:
+       case Q_ARP:
+       case Q_RARP:
+       case Q_ATALK:
+       case Q_DECNET:
+       case Q_SCA:
+       case Q_LAT:
+       case Q_MOPRC:
+       case Q_MOPDL:
+#ifdef INET6
+       case Q_IPV6:
+#endif
+               /*
+                * The offset is relative to the beginning of
+                * the network-layer header.
+                * XXX - are there any cases where we want
+                * off_nl_nosnap?
+                */
+               s = gen_off_macpl();
+
+               /*
+                * If "s" is non-null, it has code to arrange that the
+                * X register contains the offset of the MAC-layer
+                * payload.  Add to it the offset computed into the
+                * register specified by "index", and move that into
+                * the X register.  Otherwise, just load into the X
+                * register the offset computed into the register specified
+                * by "index".
+                */
+               if (s != NULL) {
+                       sappend(s, xfer_to_a(inst));
+                       sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
+                       sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+               } else
+                       s = xfer_to_x(inst);
+
+               /*
+                * Load the item at the sum of the offset we've put in the
+                * X register, the offset of the start of the network
+                * layer header from the beginning of the MAC-layer
+                * payload, and the purported offset of the start of the
+                * MAC-layer payload (which might be 0 if there's a
+                * variable-length prefix before the link-layer header
+                * or the link-layer header itself is variable-length;
+                * the variable-length offset of the start of the
+                * MAC-layer payload is what we put into the X register
+                * and then added to the index).
+                */
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               tmp->s.k = off_macpl + off_nl;
+               sappend(s, tmp);
+               sappend(inst->s, s);
+
+               /*
+                * Do the computation only if the packet contains
+                * the protocol in question.
+                */
+               b = gen_proto_abbrev(proto);
+               if (inst->b)
+                       gen_and(inst->b, b);
+               inst->b = b;
+               break;
+
+       case Q_SCTP:
+       case Q_TCP:
+       case Q_UDP:
+       case Q_ICMP:
+       case Q_IGMP:
+       case Q_IGRP:
+       case Q_PIM:
+       case Q_VRRP:
+       case Q_CARP:
+               /*
+                * The offset is relative to the beginning of
+                * the transport-layer header.
+                *
+                * Load the X register with the length of the IPv4 header
+                * (plus the offset of the link-layer header, if it's
+                * a variable-length header), in bytes.
+                *
+                * XXX - are there any cases where we want
+                * off_nl_nosnap?
+                * XXX - we should, if we're built with
+                * IPv6 support, generate code to load either
+                * IPv4, IPv6, or both, as appropriate.
+                */
+               s = gen_loadx_iphdrlen();
+
+               /*
+                * The X register now contains the sum of the length
+                * of any variable-length header preceding the link-layer
+                * header, any variable-length link-layer header, and the
+                * length of the network-layer header.
+                *
+                * Load into the A register the offset relative to
+                * the beginning of the transport layer header,
+                * add the X register to that, move that to the
+                * X register, and load with an offset from the
+                * X register equal to the offset of the network
+                * layer header relative to the beginning of
+                * the MAC-layer payload plus the fixed-length
+                * portion of the offset of the MAC-layer payload
+                * from the beginning of the raw packet data.
+                */
+               sappend(s, xfer_to_a(inst));
+               sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
+               sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+               sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
+               tmp->s.k = off_macpl + off_nl;
+               sappend(inst->s, s);
+
+               /*
+                * Do the computation only if the packet contains
+                * the protocol in question - which is true only
+                * if this is an IP datagram and is the first or
+                * only fragment of that datagram.
+                */
+               gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+               if (inst->b)
+                       gen_and(inst->b, b);
+#ifdef INET6
+               gen_and(gen_proto_abbrev(Q_IP), b);
+#endif
+               inst->b = b;
+               break;
+#ifdef INET6
+       case Q_ICMPV6:
+               bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
+               /*NOTREACHED*/
+#endif
+       }
+       inst->regno = regno;
+       s = new_stmt(BPF_ST);
+       s->s.k = regno;
+       sappend(inst->s, s);
+
+       return inst;
+}
+
+struct block *
+gen_relation(code, a0, a1, reversed)
+       int code;
+       struct arth *a0, *a1;
+       int reversed;
+{
+       struct slist *s0, *s1, *s2;
+       struct block *b, *tmp;
+
+       s0 = xfer_to_x(a1);
+       s1 = xfer_to_a(a0);
+       if (code == BPF_JEQ) {
+               s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
+               b = new_block(JMP(code));
+               sappend(s1, s2);
+       }
+       else
+               b = new_block(BPF_JMP|code|BPF_X);
+       if (reversed)
+               gen_not(b);
+
+       sappend(s0, s1);
+       sappend(a1->s, s0);
+       sappend(a0->s, a1->s);
+
+       b->stmts = a0->s;
+
+       free_reg(a0->regno);
+       free_reg(a1->regno);
+
+       /* 'and' together protocol checks */
+       if (a0->b) {
+               if (a1->b) {
+                       gen_and(a0->b, tmp = a1->b);
+               }
+               else
+                       tmp = a0->b;
+       } else
+               tmp = a1->b;
+
+       if (tmp)
+               gen_and(tmp, b);
+
+       return b;
+}
+
+struct arth *
+gen_loadlen()
+{
+       int regno = alloc_reg();
+       struct arth *a = (struct arth *)newchunk(sizeof(*a));
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_LEN);
+       s->next = new_stmt(BPF_ST);
+       s->next->s.k = regno;
+       a->s = s;
+       a->regno = regno;
+
+       return a;
+}
+
+struct arth *
+gen_loadi(val)
+       int val;
+{
+       struct arth *a;
+       struct slist *s;
+       int reg;
+
+       a = (struct arth *)newchunk(sizeof(*a));
+
+       reg = alloc_reg();
+
+       s = new_stmt(BPF_LD|BPF_IMM);
+       s->s.k = val;
+       s->next = new_stmt(BPF_ST);
+       s->next->s.k = reg;
+       a->s = s;
+       a->regno = reg;
+
+       return a;
+}
+
+struct arth *
+gen_neg(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = xfer_to_a(a);
+       sappend(a->s, s);
+       s = new_stmt(BPF_ALU|BPF_NEG);
+       s->s.k = 0;
+       sappend(a->s, s);
+       s = new_stmt(BPF_ST);
+       s->s.k = a->regno;
+       sappend(a->s, s);
+
+       return a;
+}
+
+struct arth *
+gen_arth(code, a0, a1)
+       int code;
+       struct arth *a0, *a1;
+{
+       struct slist *s0, *s1, *s2;
+
+       s0 = xfer_to_x(a1);
+       s1 = xfer_to_a(a0);
+       s2 = new_stmt(BPF_ALU|BPF_X|code);
+
+       sappend(s1, s2);
+       sappend(s0, s1);
+       sappend(a1->s, s0);
+       sappend(a0->s, a1->s);
+
+       free_reg(a0->regno);
+       free_reg(a1->regno);
+
+       s0 = new_stmt(BPF_ST);
+       a0->regno = s0->s.k = alloc_reg();
+       sappend(a0->s, s0);
+
+       return a0;
+}
+
+/*
+ * Here we handle simple allocation of the scratch registers.
+ * If too many registers are alloc'd, the allocator punts.
+ */
+static int regused[BPF_MEMWORDS];
+static int curreg;
+
+/*
+ * Initialize the table of used registers and the current register.
+ */
+static void
+init_regs()
+{
+       curreg = 0;
+       memset(regused, 0, sizeof regused);
+}
+
+/*
+ * Return the next free register.
+ */
+static int
+alloc_reg()
+{
+       int n = BPF_MEMWORDS;
+
+       while (--n >= 0) {
+               if (regused[curreg])
+                       curreg = (curreg + 1) % BPF_MEMWORDS;
+               else {
+                       regused[curreg] = 1;
+                       return curreg;
+               }
+       }
+       bpf_error("too many registers needed to evaluate expression");
+       /* NOTREACHED */
+       return 0;
+}
+
+/*
+ * Return a register to the table so it can
+ * be used later.
+ */
+static void
+free_reg(n)
+       int n;
+{
+       regused[n] = 0;
+}
+
+static struct block *
+gen_len(jmp, n)
+       int jmp, n;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LD|BPF_LEN);
+       b = new_block(JMP(jmp));
+       b->stmts = s;
+       b->s.k = n;
+
+       return b;
+}
+
+struct block *
+gen_greater(n)
+       int n;
+{
+       return gen_len(BPF_JGE, n);
+}
+
+/*
+ * Actually, this is less than or equal.
+ */
+struct block *
+gen_less(n)
+       int n;
+{
+       struct block *b;
+
+       b = gen_len(BPF_JGT, n);
+       gen_not(b);
+
+       return b;
+}
+
+/*
+ * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
+ * the beginning of the link-layer header.
+ * XXX - that means you can't test values in the radiotap header, but
+ * as that header is difficult if not impossible to parse generally
+ * without a loop, that might not be a severe problem.  A new keyword
+ * "radio" could be added for that, although what you'd really want
+ * would be a way of testing particular radio header values, which
+ * would generate code appropriate to the radio header in question.
+ */
+struct block *
+gen_byteop(op, idx, val)
+       int op, idx, val;
+{
+       struct block *b;
+       struct slist *s;
+
+       switch (op) {
+       default:
+               abort();
+
+       case '=':
+               return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+
+       case '<':
+               b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+               return b;
+
+       case '>':
+               b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+               return b;
+
+       case '|':
+               s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
+               break;
+
+       case '&':
+               s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               break;
+       }
+       s->s.k = val;
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       gen_not(b);
+
+       return b;
+}
+
+static u_char abroadcast[] = { 0x0 };
+
+struct block *
+gen_broadcast(proto)
+       int proto;
+{
+       bpf_u_int32 hostmask;
+       struct block *b0, *b1, *b2;
+       static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_LINK:
+               switch (linktype) {
+               case DLT_ARCNET:
+               case DLT_ARCNET_LINUX:
+                       return gen_ahostop(abroadcast, Q_DST);
+               case DLT_EN10MB:
+               case DLT_NETANALYZER:
+               case DLT_NETANALYZER_TRANSPARENT:
+                       return gen_ehostop(ebroadcast, Q_DST);
+               case DLT_FDDI:
+                       return gen_fhostop(ebroadcast, Q_DST);
+               case DLT_IEEE802:
+                       return gen_thostop(ebroadcast, Q_DST);
+               case DLT_IEEE802_11:
+               case DLT_PRISM_HEADER:
+               case DLT_IEEE802_11_RADIO_AVS:
+               case DLT_IEEE802_11_RADIO:
+               case DLT_PPI:
+                       return gen_wlanhostop(ebroadcast, Q_DST);
+               case DLT_IP_OVER_FC:
+                       return gen_ipfchostop(ebroadcast, Q_DST);
+               case DLT_SUNATM:
+                       if (is_lane) {
+                               /*
+                                * Check that the packet doesn't begin with an
+                                * LE Control marker.  (We've already generated
+                                * a test for LANE.)
+                                */
+                               b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+                                   BPF_H, 0xFF00);
+                               gen_not(b1);
+
+                               /*
+                                * Now check the MAC address.
+                                */
+                               b0 = gen_ehostop(ebroadcast, Q_DST);
+                               gen_and(b1, b0);
+                               return b0;
+                       }
+                       break;
+               default:
+                       bpf_error("not a broadcast link");
+               }
+               break;
+
+       case Q_IP:
+               /*
+                * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
+                * as an indication that we don't know the netmask, and fail
+                * in that case.
+                */
+               if (netmask == PCAP_NETMASK_UNKNOWN)
+                       bpf_error("netmask not known, so 'ip broadcast' not supported");
+               b0 = gen_linktype(ETHERTYPE_IP);
+               hostmask = ~netmask;
+               b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
+               b2 = gen_mcmp(OR_NET, 16, BPF_W,
+                             (bpf_int32)(~0 & hostmask), hostmask);
+               gen_or(b1, b2);
+               gen_and(b0, b2);
+               return b2;
+       }
+       bpf_error("only link-layer/IP broadcast filters supported");
+       /* NOTREACHED */
+       return NULL;
+}
+
+/*
+ * Generate code to test the low-order bit of a MAC address (that's
+ * the bottom bit of the *first* byte).
+ */
+static struct block *
+gen_mac_multicast(offset)
+       int offset;
+{
+       register struct block *b0;
+       register struct slist *s;
+
+       /* link[offset] & 1 != 0 */
+       s = gen_load_a(OR_LINK, offset, BPF_B);
+       b0 = new_block(JMP(BPF_JSET));
+       b0->s.k = 1;
+       b0->stmts = s;
+       return b0;
+}
+
+struct block *
+gen_multicast(proto)
+       int proto;
+{
+       register struct block *b0, *b1, *b2;
+       register struct slist *s;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_LINK:
+               switch (linktype) {
+               case DLT_ARCNET:
+               case DLT_ARCNET_LINUX:
+                       /* all ARCnet multicasts use the same address */
+                       return gen_ahostop(abroadcast, Q_DST);
+               case DLT_EN10MB:
+               case DLT_NETANALYZER:
+               case DLT_NETANALYZER_TRANSPARENT:
+                       /* ether[0] & 1 != 0 */
+                       return gen_mac_multicast(0);
+               case DLT_FDDI:
+                       /*
+                        * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
+                        *
+                        * XXX - was that referring to bit-order issues?
+                        */
+                       /* fddi[1] & 1 != 0 */
+                       return gen_mac_multicast(1);
+               case DLT_IEEE802:
+                       /* tr[2] & 1 != 0 */
+                       return gen_mac_multicast(2);
+               case DLT_IEEE802_11:
+               case DLT_PRISM_HEADER:
+               case DLT_IEEE802_11_RADIO_AVS:
+               case DLT_IEEE802_11_RADIO:
+               case DLT_PPI:
+                       /*
+                        * Oh, yuk.
+                        *
+                        *      For control frames, there is no DA.
+                        *
+                        *      For management frames, DA is at an
+                        *      offset of 4 from the beginning of
+                        *      the packet.
+                        *
+                        *      For data frames, DA is at an offset
+                        *      of 4 from the beginning of the packet
+                        *      if To DS is clear and at an offset of
+                        *      16 from the beginning of the packet
+                        *      if To DS is set.
+                        */
+
+                       /*
+                        * Generate the tests to be done for data frames.
+                        *
+                        * First, check for To DS set, i.e. "link[1] & 0x01".
+                        */
+                       s = gen_load_a(OR_LINK, 1, BPF_B);
+                       b1 = new_block(JMP(BPF_JSET));
+                       b1->s.k = 0x01; /* To DS */
+                       b1->stmts = s;
+
+                       /*
+                        * If To DS is set, the DA is at 16.
+                        */
+                       b0 = gen_mac_multicast(16);
+                       gen_and(b1, b0);
+
+                       /*
+                        * Now, check for To DS not set, i.e. check
+                        * "!(link[1] & 0x01)".
+                        */
+                       s = gen_load_a(OR_LINK, 1, BPF_B);
+                       b2 = new_block(JMP(BPF_JSET));
+                       b2->s.k = 0x01; /* To DS */
+                       b2->stmts = s;
+                       gen_not(b2);
+
+                       /*
+                        * If To DS is not set, the DA is at 4.
+                        */
+                       b1 = gen_mac_multicast(4);
+                       gen_and(b2, b1);
+
+                       /*
+                        * Now OR together the last two checks.  That gives
+                        * the complete set of checks for data frames.
+                        */
+                       gen_or(b1, b0);
+
+                       /*
+                        * Now check for a data frame.
+                        * I.e, check "link[0] & 0x08".
+                        */
+                       s = gen_load_a(OR_LINK, 0, BPF_B);
+                       b1 = new_block(JMP(BPF_JSET));
+                       b1->s.k = 0x08;
+                       b1->stmts = s;
+
+                       /*
+                        * AND that with the checks done for data frames.
+                        */
+                       gen_and(b1, b0);
+
+                       /*
+                        * If the high-order bit of the type value is 0, this
+                        * is a management frame.
+                        * I.e, check "!(link[0] & 0x08)".
+                        */
+                       s = gen_load_a(OR_LINK, 0, BPF_B);
+                       b2 = new_block(JMP(BPF_JSET));
+                       b2->s.k = 0x08;
+                       b2->stmts = s;
+                       gen_not(b2);
+
+                       /*
+                        * For management frames, the DA is at 4.
+                        */
+                       b1 = gen_mac_multicast(4);
+                       gen_and(b2, b1);
+
+                       /*
+                        * OR that with the checks done for data frames.
+                        * That gives the checks done for management and
+                        * data frames.
+                        */
+                       gen_or(b1, b0);
+
+                       /*
+                        * If the low-order bit of the type value is 1,
+                        * this is either a control frame or a frame
+                        * with a reserved type, and thus not a
+                        * frame with an SA.
+                        *
+                        * I.e., check "!(link[0] & 0x04)".
+                        */
+                       s = gen_load_a(OR_LINK, 0, BPF_B);
+                       b1 = new_block(JMP(BPF_JSET));
+                       b1->s.k = 0x04;
+                       b1->stmts = s;
+                       gen_not(b1);
+
+                       /*
+                        * AND that with the checks for data and management
+                        * frames.
+                        */
+                       gen_and(b1, b0);
+                       return b0;
+               case DLT_IP_OVER_FC:
+                       b0 = gen_mac_multicast(2);
+                       return b0;
+               case DLT_SUNATM:
+                       if (is_lane) {
+                               /*
+                                * Check that the packet doesn't begin with an
+                                * LE Control marker.  (We've already generated
+                                * a test for LANE.)
+                                */
+                               b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+                                   BPF_H, 0xFF00);
+                               gen_not(b1);
+
+                               /* ether[off_mac] & 1 != 0 */
+                               b0 = gen_mac_multicast(off_mac);
+                               gen_and(b1, b0);
+                               return b0;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               /* Link not known to support multicasts */
+               break;
+
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
+               gen_and(b0, b1);
+               return b1;
+
+#ifdef INET6
+       case Q_IPV6:
+               b0 = gen_linktype(ETHERTYPE_IPV6);
+               b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
+               gen_and(b0, b1);
+               return b1;
+#endif /* INET6 */
+       }
+       bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+       /* NOTREACHED */
+       return NULL;
+}
+
+/*
+ * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
+ * Outbound traffic is sent by this machine, while inbound traffic is
+ * sent by a remote machine (and may include packets destined for a
+ * unicast or multicast link-layer address we are not subscribing to).
+ * These are the same definitions implemented by pcap_setdirection().
+ * Capturing only unicast traffic destined for this host is probably
+ * better accomplished using a higher-layer filter.
+ */
+struct block *
+gen_inbound(dir)
+       int dir;
+{
+       register struct block *b0;
+
+       /*
+        * Only some data link types support inbound/outbound qualifiers.
+        */
+       switch (linktype) {
+       case DLT_SLIP:
+               b0 = gen_relation(BPF_JEQ,
+                         gen_load(Q_LINK, gen_loadi(0), 1),
+                         gen_loadi(0),
+                         dir);
+               break;
+
+       case DLT_IPNET:
+               if (dir) {
+                       /* match outgoing packets */
+                       b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND);
+               } else {
+                       /* match incoming packets */
+                       b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND);
+               }
+               break;
+
+       case DLT_LINUX_SLL:
+               /* match outgoing packets */
+               b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
+               if (!dir) {
+                       /* to filter on inbound traffic, invert the match */
+                       gen_not(b0);
+               }
+               break;
+
+#ifdef HAVE_NET_PFVAR_H
+       case DLT_PFLOG:
+               b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
+                   (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
+               break;
+#endif
+
+       case DLT_PPP_PPPD:
+               if (dir) {
+                       /* match outgoing packets */
+                       b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
+               } else {
+                       /* match incoming packets */
+                       b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
+               }
+               break;
+
+        case DLT_JUNIPER_MFR:
+        case DLT_JUNIPER_MLFR:
+        case DLT_JUNIPER_MLPPP:
+       case DLT_JUNIPER_ATM1:
+       case DLT_JUNIPER_ATM2:
+       case DLT_JUNIPER_PPPOE:
+       case DLT_JUNIPER_PPPOE_ATM:
+        case DLT_JUNIPER_GGSN:
+        case DLT_JUNIPER_ES:
+        case DLT_JUNIPER_MONITOR:
+        case DLT_JUNIPER_SERVICES:
+        case DLT_JUNIPER_ETHER:
+        case DLT_JUNIPER_PPP:
+        case DLT_JUNIPER_FRELAY:
+        case DLT_JUNIPER_CHDLC:
+        case DLT_JUNIPER_VP:
+        case DLT_JUNIPER_ST:
+        case DLT_JUNIPER_ISM:
+        case DLT_JUNIPER_VS:
+        case DLT_JUNIPER_SRX_E2E:
+        case DLT_JUNIPER_FIBRECHANNEL:
+       case DLT_JUNIPER_ATM_CEMIC:
+
+               /* juniper flags (including direction) are stored
+                * the byte after the 3-byte magic number */
+               if (dir) {
+                       /* match outgoing packets */
+                       b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
+               } else {
+                       /* match incoming packets */
+                       b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
+               }
+               break;
+
+       default:
+               /*
+                * If we have packet meta-data indicating a direction,
+                * check it, otherwise give up as this link-layer type
+                * has nothing in the packet data.
+                */
+#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+               /*
+                * We infer that this is Linux with PF_PACKET support.
+                * If this is a *live* capture, we can look at
+                * special meta-data in the filter expression;
+                * if it's a savefile, we can't.
+                */
+               if (bpf_pcap->sf.rfile != NULL) {
+                       /* We have a FILE *, so this is a savefile */
+                       bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
+                           linktype);
+                       b0 = NULL;
+                       /* NOTREACHED */
+               }
+               /* match outgoing packets */
+               b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+                            PACKET_OUTGOING);
+               if (!dir) {
+                       /* to filter on inbound traffic, invert the match */
+                       gen_not(b0);
+               }
+#else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
+               bpf_error("inbound/outbound not supported on linktype %d",
+                   linktype);
+               b0 = NULL;
+               /* NOTREACHED */
+#endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
+       }
+       return (b0);
+}
+
+#ifdef HAVE_NET_PFVAR_H
+/* PF firewall log matched interface */
+struct block *
+gen_pf_ifname(const char *ifname)
+{
+       struct block *b0;
+       u_int len, off;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("ifname supported only on PF linktype");
+               /* NOTREACHED */
+       }
+       len = sizeof(((struct pfloghdr *)0)->ifname);
+       off = offsetof(struct pfloghdr, ifname);
+       if (strlen(ifname) >= len) {
+               bpf_error("ifname interface names can only be %d characters",
+                   len-1);
+               /* NOTREACHED */
+       }
+       b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
+       return (b0);
+}
+
+/* PF firewall log ruleset name */
+struct block *
+gen_pf_ruleset(char *ruleset)
+{
+       struct block *b0;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("ruleset supported only on PF linktype");
+               /* NOTREACHED */
+       }
+
+       if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
+               bpf_error("ruleset names can only be %ld characters",
+                   (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
+               /* NOTREACHED */
+       }
+
+       b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
+           strlen(ruleset), (const u_char *)ruleset);
+       return (b0);
+}
+
+/* PF firewall log rule number */
+struct block *
+gen_pf_rnr(int rnr)
+{
+       struct block *b0;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("rnr supported only on PF linktype");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
+                (bpf_int32)rnr);
+       return (b0);
+}
+
+/* PF firewall log sub-rule number */
+struct block *
+gen_pf_srnr(int srnr)
+{
+       struct block *b0;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("srnr supported only on PF linktype");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
+           (bpf_int32)srnr);
+       return (b0);
+}
+
+/* PF firewall log reason code */
+struct block *
+gen_pf_reason(int reason)
+{
+       struct block *b0;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("reason supported only on PF linktype");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
+           (bpf_int32)reason);
+       return (b0);
+}
+
+/* PF firewall log action */
+struct block *
+gen_pf_action(int action)
+{
+       struct block *b0;
+
+       if (linktype != DLT_PFLOG) {
+               bpf_error("action supported only on PF linktype");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
+           (bpf_int32)action);
+       return (b0);
+}
+#else /* !HAVE_NET_PFVAR_H */
+struct block *
+gen_pf_ifname(const char *ifname)
+{
+       bpf_error("libpcap was compiled without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_ruleset(char *ruleset)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_rnr(int rnr)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_srnr(int srnr)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_reason(int reason)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_action(int action)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+#endif /* HAVE_NET_PFVAR_H */
+
+/* IEEE 802.11 wireless header */
+struct block *
+gen_p80211_type(int type, int mask)
+{
+       struct block *b0;
+
+       switch (linktype) {
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+               b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type,
+                   (bpf_int32)mask);
+               break;
+
+       default:
+               bpf_error("802.11 link-layer types supported only on 802.11");
+               /* NOTREACHED */
+       }
+
+       return (b0);
+}
+
+struct block *
+gen_p80211_fcdir(int fcdir)
+{
+       struct block *b0;
+
+       switch (linktype) {
+
+       case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO_AVS:
+       case DLT_IEEE802_11_RADIO:
+               break;
+
+       default:
+               bpf_error("frame direction supported only with 802.11 headers");
+               /* NOTREACHED */
+       }
+
+       b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir,
+               (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
+
+       return (b0);
+}
+
+struct block *
+gen_acode(eaddr, q)
+       register const u_char *eaddr;
+       struct qual q;
+{
+       switch (linktype) {
+
+       case DLT_ARCNET:
+       case DLT_ARCNET_LINUX:
+               if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
+                   q.proto == Q_LINK)
+                       return (gen_ahostop(eaddr, (int)q.dir));
+               else {
+                       bpf_error("ARCnet address used in non-arc expression");
+                       /* NOTREACHED */
+               }
+               break;
+
+       default:
+               bpf_error("aid supported only on ARCnet");
+               /* NOTREACHED */
+       }
+       bpf_error("ARCnet address used in non-arc expression");
+       /* NOTREACHED */
+       return NULL;
+}
+
+static struct block *
+gen_ahostop(eaddr, dir)
+       register const u_char *eaddr;
+       register int dir;
+{
+       register struct block *b0, *b1;
+
+       switch (dir) {
+       /* src comes first, different from Ethernet */
+       case Q_SRC:
+               return gen_bcmp(OR_LINK, 0, 1, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(OR_LINK, 1, 1, eaddr);
+
+       case Q_AND:
+               b0 = gen_ahostop(eaddr, Q_SRC);
+               b1 = gen_ahostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_ahostop(eaddr, Q_SRC);
+               b1 = gen_ahostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       case Q_ADDR1:
+               bpf_error("'addr1' is only supported on 802.11");
+               break;
+
+       case Q_ADDR2:
+               bpf_error("'addr2' is only supported on 802.11");
+               break;
+
+       case Q_ADDR3:
+               bpf_error("'addr3' is only supported on 802.11");
+               break;
+
+       case Q_ADDR4:
+               bpf_error("'addr4' is only supported on 802.11");
+               break;
+
+       case Q_RA:
+               bpf_error("'ra' is only supported on 802.11");
+               break;
+
+       case Q_TA:
+               bpf_error("'ta' is only supported on 802.11");
+               break;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * support IEEE 802.1Q VLAN trunk over ethernet
+ */
+struct block *
+gen_vlan(vlan_num)
+       int vlan_num;
+{
+       struct  block   *b0, *b1;
+
+       /* can't check for VLAN-encapsulated packets inside MPLS */
+       if (label_stack_depth > 0)
+               bpf_error("no VLAN match after MPLS");
+
+       /*
+        * Check for a VLAN packet, and then change the offsets to point
+        * to the type and data fields within the VLAN packet.  Just
+        * increment the offsets, so that we can support a hierarchy, e.g.
+        * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
+        * VLAN 100.
+        *
+        * XXX - this is a bit of a kludge.  If we were to split the
+        * compiler into a parser that parses an expression and
+        * generates an expression tree, and a code generator that
+        * takes an expression tree (which could come from our
+        * parser or from some other parser) and generates BPF code,
+        * we could perhaps make the offsets parameters of routines
+        * and, in the handler for an "AND" node, pass to subnodes
+        * other than the VLAN node the adjusted offsets.
+        *
+        * This would mean that "vlan" would, instead of changing the
+        * behavior of *all* tests after it, change only the behavior
+        * of tests ANDed with it.  That would change the documented
+        * semantics of "vlan", which might break some expressions.
+        * However, it would mean that "(vlan and ip) or ip" would check
+        * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
+        * checking only for VLAN-encapsulated IP, so that could still
+        * be considered worth doing; it wouldn't break expressions
+        * that are of the form "vlan and ..." or "vlan N and ...",
+        * which I suspect are the most common expressions involving
+        * "vlan".  "vlan or ..." doesn't necessarily do what the user
+        * would really want, now, as all the "or ..." tests would
+        * be done assuming a VLAN, even though the "or" could be viewed
+        * as meaning "or, if this isn't a VLAN packet...".
+        */
+       orig_nl = off_nl;
+
+       switch (linktype) {
+
+       case DLT_EN10MB:
+       case DLT_NETANALYZER:
+       case DLT_NETANALYZER_TRANSPARENT:
+               /* check for VLAN, including QinQ */
+               b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
+                   (bpf_int32)ETHERTYPE_8021Q);
+               b1 = gen_cmp(OR_LINK, off_linktype, BPF_H,
+                   (bpf_int32)ETHERTYPE_8021QINQ);
+               gen_or(b0,b1);
+               b0 = b1;
+
+               /* If a specific VLAN is requested, check VLAN id */
+               if (vlan_num >= 0) {
+                       b1 = gen_mcmp(OR_MACPL, 0, BPF_H,
+                           (bpf_int32)vlan_num, 0x0fff);
+                       gen_and(b0, b1);
+                       b0 = b1;
+               }
+
+               off_macpl += 4;
+               off_linktype += 4;
+#if 0
+               off_nl_nosnap += 4;
+               off_nl += 4;
+#endif
+               break;
+
+       default:
+               bpf_error("no VLAN support for data link type %d",
+                     linktype);
+               /*NOTREACHED*/
+       }
+
+       return (b0);
+}
+
+/*
+ * support for MPLS
+ */
+struct block *
+gen_mpls(label_num)
+       int label_num;
+{
+       struct  block   *b0,*b1;
+
+       /*
+        * Change the offsets to point to the type and data fields within
+        * the MPLS packet.  Just increment the offsets, so that we
+        * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
+        * capture packets with an outer label of 100000 and an inner
+        * label of 1024.
+        *
+        * XXX - this is a bit of a kludge.  See comments in gen_vlan().
+        */
+        orig_nl = off_nl;
+
+        if (label_stack_depth > 0) {
+            /* just match the bottom-of-stack bit clear */
+            b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01);
+        } else {
+            /*
+             * Indicate that we're checking MPLS-encapsulated headers,
+             * to make sure higher level code generators don't try to
+             * match against IP-related protocols such as Q_ARP, Q_RARP
+             * etc.
+             */
+            switch (linktype) {
+                
+            case DLT_C_HDLC: /* fall through */
+            case DLT_EN10MB:
+            case DLT_NETANALYZER:
+            case DLT_NETANALYZER_TRANSPARENT:
+                    b0 = gen_linktype(ETHERTYPE_MPLS);
+                    break;
+                
+            case DLT_PPP:
+                    b0 = gen_linktype(PPP_MPLS_UCAST);
+                    break;
+                
+                    /* FIXME add other DLT_s ...
+                     * for Frame-Relay/and ATM this may get messy due to SNAP headers
+                     * leave it for now */
+                
+            default:
+                    bpf_error("no MPLS support for data link type %d",
+                          linktype);
+                    b0 = NULL;
+                    /*NOTREACHED*/
+                    break;
+            }
+        }
+
+       /* If a specific MPLS label is requested, check it */
+       if (label_num >= 0) {
+               label_num = label_num << 12; /* label is shifted 12 bits on the wire */
+               b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num,
+                   0xfffff000); /* only compare the first 20 bits */
+               gen_and(b0, b1);
+               b0 = b1;
+       }
+
+        off_nl_nosnap += 4;
+        off_nl += 4;
+        label_stack_depth++;
+       return (b0);
+}
+
+/*
+ * Support PPPOE discovery and session.
+ */
+struct block *
+gen_pppoed()
+{
+       /* check for PPPoE discovery */
+       return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
+}
+
+struct block *
+gen_pppoes()
+{
+       struct block *b0;
+
+       /*
+        * Test against the PPPoE session link-layer type.
+        */
+       b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
+
+       /*
+        * Change the offsets to point to the type and data fields within
+        * the PPP packet, and note that this is PPPoE rather than
+        * raw PPP.
+        *
+        * XXX - this is a bit of a kludge.  If we were to split the
+        * compiler into a parser that parses an expression and
+        * generates an expression tree, and a code generator that
+        * takes an expression tree (which could come from our
+        * parser or from some other parser) and generates BPF code,
+        * we could perhaps make the offsets parameters of routines
+        * and, in the handler for an "AND" node, pass to subnodes
+        * other than the PPPoE node the adjusted offsets.
+        *
+        * This would mean that "pppoes" would, instead of changing the
+        * behavior of *all* tests after it, change only the behavior
+        * of tests ANDed with it.  That would change the documented
+        * semantics of "pppoes", which might break some expressions.
+        * However, it would mean that "(pppoes and ip) or ip" would check
+        * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
+        * checking only for VLAN-encapsulated IP, so that could still
+        * be considered worth doing; it wouldn't break expressions
+        * that are of the form "pppoes and ..." which I suspect are the
+        * most common expressions involving "pppoes".  "pppoes or ..."
+        * doesn't necessarily do what the user would really want, now,
+        * as all the "or ..." tests would be done assuming PPPoE, even
+        * though the "or" could be viewed as meaning "or, if this isn't
+        * a PPPoE packet...".
+        */
+       orig_linktype = off_linktype;   /* save original values */
+       orig_nl = off_nl;
+       is_pppoes = 1;
+
+       /*
+        * The "network-layer" protocol is PPPoE, which has a 6-byte
+        * PPPoE header, followed by a PPP packet.
+        *
+        * There is no HDLC encapsulation for the PPP packet (it's
+        * encapsulated in PPPoES instead), so the link-layer type
+        * starts at the first byte of the PPP packet.  For PPPoE,
+        * that offset is relative to the beginning of the total
+        * link-layer payload, including any 802.2 LLC header, so
+        * it's 6 bytes past off_nl.
+        */
+       off_linktype = off_nl + 6;
+
+       /*
+        * The network-layer offsets are relative to the beginning
+        * of the MAC-layer payload; that's past the 6-byte
+        * PPPoE header and the 2-byte PPP header.
+        */
+       off_nl = 6+2;
+       off_nl_nosnap = 6+2;
+
+       return b0;
+}
+
+struct block *
+gen_atmfield_code(atmfield, jvalue, jtype, reverse)
+       int atmfield;
+       bpf_int32 jvalue;
+       bpf_u_int32 jtype;
+       int reverse;
+{
+       struct block *b0;
+
+       switch (atmfield) {
+
+       case A_VPI:
+               if (!is_atm)
+                       bpf_error("'vpi' supported only on raw ATM");
+               if (off_vpi == (u_int)-1)
+                       abort();
+               b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype,
+                   reverse, jvalue);
+               break;
+
+       case A_VCI:
+               if (!is_atm)
+                       bpf_error("'vci' supported only on raw ATM");
+               if (off_vci == (u_int)-1)
+                       abort();
+               b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype,
+                   reverse, jvalue);
+               break;
+
+       case A_PROTOTYPE:
+               if (off_proto == (u_int)-1)
+                       abort();        /* XXX - this isn't on FreeBSD */
+               b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype,
+                   reverse, jvalue);
+               break;
+
+       case A_MSGTYPE:
+               if (off_payload == (u_int)-1)
+                       abort();
+               b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B,
+                   0xffffffff, jtype, reverse, jvalue);
+               break;
+
+       case A_CALLREFTYPE:
+               if (!is_atm)
+                       bpf_error("'callref' supported only on raw ATM");
+               if (off_proto == (u_int)-1)
+                       abort();
+               b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff,
+                   jtype, reverse, jvalue);
+               break;
+
+       default:
+               abort();
+       }
+       return b0;
+}
+
+struct block *
+gen_atmtype_abbrev(type)
+       int type;
+{
+       struct block *b0, *b1;
+
+       switch (type) {
+
+       case A_METAC:
+               /* Get all packets in Meta signalling Circuit */
+               if (!is_atm)
+                       bpf_error("'metac' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_BCC:
+               /* Get all packets in Broadcast Circuit*/
+               if (!is_atm)
+                       bpf_error("'bcc' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_OAMF4SC:
+               /* Get all cells in Segment OAM F4 circuit*/
+               if (!is_atm)
+                       bpf_error("'oam4sc' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_OAMF4EC:
+               /* Get all cells in End-to-End OAM F4 Circuit*/
+               if (!is_atm)
+                       bpf_error("'oam4ec' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_SC:
+               /*  Get all packets in connection Signalling Circuit */
+               if (!is_atm)
+                       bpf_error("'sc' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_ILMIC:
+               /* Get all packets in ILMI Circuit */
+               if (!is_atm)
+                       bpf_error("'ilmic' supported only on raw ATM");
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_LANE:
+               /* Get all LANE packets */
+               if (!is_atm)
+                       bpf_error("'lane' supported only on raw ATM");
+               b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
+
+               /*
+                * Arrange that all subsequent tests assume LANE
+                * rather than LLC-encapsulated packets, and set
+                * the offsets appropriately for LANE-encapsulated
+                * Ethernet.
+                *
+                * "off_mac" is the offset of the Ethernet header,
+                * which is 2 bytes past the ATM pseudo-header
+                * (skipping the pseudo-header and 2-byte LE Client
+                * field).  The other offsets are Ethernet offsets
+                * relative to "off_mac".
+                */
+               is_lane = 1;
+               off_mac = off_payload + 2;      /* MAC header */
+               off_linktype = off_mac + 12;
+               off_macpl = off_mac + 14;       /* Ethernet */
+               off_nl = 0;                     /* Ethernet II */
+               off_nl_nosnap = 3;              /* 802.3+802.2 */
+               break;
+
+       case A_LLC:
+               /* Get all LLC-encapsulated packets */
+               if (!is_atm)
+                       bpf_error("'llc' supported only on raw ATM");
+               b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+               is_lane = 0;
+               break;
+
+       default:
+               abort();
+       }
+       return b1;
+}
+
+/* 
+ * Filtering for MTP2 messages based on li value
+ * FISU, length is null
+ * LSSU, length is 1 or 2
+ * MSU, length is 3 or more
+ */
+struct block *
+gen_mtp2type_abbrev(type)
+       int type;
+{
+       struct block *b0, *b1;
+
+       switch (type) {
+
+       case M_FISU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_ERF) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'fisu' supported only on MTP2");
+               /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
+               break;
+
+       case M_LSSU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_ERF) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'lssu' supported only on MTP2");
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
+               b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
+               gen_and(b1, b0);
+               break;
+
+       case M_MSU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_ERF) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'msu' supported only on MTP2");
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
+               break;
+
+       default:
+               abort();
+       }
+       return b0;
+}
+
+struct block *
+gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
+       int mtp3field;
+       bpf_u_int32 jvalue;
+       bpf_u_int32 jtype;
+       int reverse;
+{
+       struct block *b0;
+       bpf_u_int32 val1 , val2 , val3;
+
+       switch (mtp3field) {
+
+       case M_SIO:
+               if (off_sio == (u_int)-1)
+                       bpf_error("'sio' supported only on SS7");
+               /* sio coded on 1 byte so max value 255 */
+               if(jvalue > 255)
+                       bpf_error("sio value %u too big; max value = 255",
+                           jvalue);
+               b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
+                   (u_int)jtype, reverse, (u_int)jvalue);
+               break;
+
+        case M_OPC:
+               if (off_opc == (u_int)-1)
+                       bpf_error("'opc' supported only on SS7");
+               /* opc coded on 14 bits so max value 16383 */
+               if (jvalue > 16383)
+                       bpf_error("opc value %u too big; max value = 16383",
+                           jvalue);
+               /* the following instructions are made to convert jvalue
+                * to the form used to write opc in an ss7 message*/
+               val1 = jvalue & 0x00003c00;
+               val1 = val1 >>10;
+               val2 = jvalue & 0x000003fc;
+               val2 = val2 <<6;
+               val3 = jvalue & 0x00000003;
+               val3 = val3 <<22;
+               jvalue = val1 + val2 + val3;
+               b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
+                   (u_int)jtype, reverse, (u_int)jvalue);
+               break;
+
+       case M_DPC:
+               if (off_dpc == (u_int)-1)
+                       bpf_error("'dpc' supported only on SS7");
+               /* dpc coded on 14 bits so max value 16383 */
+               if (jvalue > 16383)
+                       bpf_error("dpc value %u too big; max value = 16383",
+                           jvalue);
+               /* the following instructions are made to convert jvalue
+                * to the forme used to write dpc in an ss7 message*/
+               val1 = jvalue & 0x000000ff;
+               val1 = val1 << 24;
+               val2 = jvalue & 0x00003f00;
+               val2 = val2 << 8;
+               jvalue = val1 + val2;
+               b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
+                   (u_int)jtype, reverse, (u_int)jvalue);
+               break;
+
+       case M_SLS:
+               if (off_sls == (u_int)-1)
+                       bpf_error("'sls' supported only on SS7");
+               /* sls coded on 4 bits so max value 15 */
+               if (jvalue > 15)
+                        bpf_error("sls value %u too big; max value = 15",
+                            jvalue);
+               /* the following instruction is made to convert jvalue
+                * to the forme used to write sls in an ss7 message*/
+               jvalue = jvalue << 4;
+               b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0,
+                   (u_int)jtype,reverse, (u_int)jvalue);
+               break;
+
+       default:
+               abort();
+       }
+       return b0;
+}
+
+static struct block *
+gen_msg_abbrev(type)
+       int type;
+{
+       struct block *b1;
+
+       /*
+        * Q.2931 signalling protocol messages for handling virtual circuits
+        * establishment and teardown
+        */
+       switch (type) {
+
+       case A_SETUP:
+               b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
+               break;
+
+       case A_CALLPROCEED:
+               b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+               break;
+
+       case A_CONNECT:
+               b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
+               break;
+
+       case A_CONNECTACK:
+               b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+               break;
+
+       case A_RELEASE:
+               b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
+               break;
+
+       case A_RELEASE_DONE:
+               b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+               break;
+
+       default:
+               abort();
+       }
+       return b1;
+}
+
+struct block *
+gen_atmmulti_abbrev(type)
+       int type;
+{
+       struct block *b0, *b1;
+
+       switch (type) {
+
+       case A_OAM:
+               if (!is_atm)
+                       bpf_error("'oam' supported only on raw ATM");
+               b1 = gen_atmmulti_abbrev(A_OAMF4);
+               break;
+
+       case A_OAMF4:
+               if (!is_atm)
+                       bpf_error("'oamf4' supported only on raw ATM");
+               /* OAM F4 type */
+               b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+               b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+               gen_or(b0, b1);
+               b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+               gen_and(b0, b1);
+               break;
+
+       case A_CONNECTMSG:
+               /*
+                * Get Q.2931 signalling messages for switched
+                * virtual connection
+                */
+               if (!is_atm)
+                       bpf_error("'connectmsg' supported only on raw ATM");
+               b0 = gen_msg_abbrev(A_SETUP);
+               b1 = gen_msg_abbrev(A_CALLPROCEED);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_CONNECT);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_CONNECTACK);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_RELEASE);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_RELEASE_DONE);
+               gen_or(b0, b1);
+               b0 = gen_atmtype_abbrev(A_SC);
+               gen_and(b0, b1);
+               break;
+
+       case A_METACONNECT:
+               if (!is_atm)
+                       bpf_error("'metaconnect' supported only on raw ATM");
+               b0 = gen_msg_abbrev(A_SETUP);
+               b1 = gen_msg_abbrev(A_CALLPROCEED);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_CONNECT);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_RELEASE);
+               gen_or(b0, b1);
+               b0 = gen_msg_abbrev(A_RELEASE_DONE);
+               gen_or(b0, b1);
+               b0 = gen_atmtype_abbrev(A_METAC);
+               gen_and(b0, b1);
+               break;
+
+       default:
+               abort();
+       }
+       return b1;
+}
diff --git a/gencode.h b/gencode.h
new file mode 100644 (file)
index 0000000..29d2d10
--- /dev/null
+++ b/gencode.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.71 2007-11-18 02:03:52 guy Exp $ (LBL)
+ */
+
+/*
+ * ATM support:
+ *
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Yen Yen Lim and
+ *      North Dakota State University
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif /* HAVE___ATTRIBUTE__ */
+
+/* Address qualifiers. */
+
+#define Q_HOST         1
+#define Q_NET          2
+#define Q_PORT         3
+#define Q_GATEWAY      4
+#define Q_PROTO                5
+#define Q_PROTOCHAIN   6
+#define Q_PORTRANGE    7
+
+/* Protocol qualifiers. */
+
+#define Q_LINK         1
+#define Q_IP           2
+#define Q_ARP          3
+#define Q_RARP         4
+#define Q_SCTP         5
+#define Q_TCP          6
+#define Q_UDP          7
+#define Q_ICMP         8
+#define Q_IGMP         9
+#define Q_IGRP         10
+
+
+#define        Q_ATALK         11
+#define        Q_DECNET        12
+#define        Q_LAT           13
+#define Q_SCA          14
+#define        Q_MOPRC         15
+#define        Q_MOPDL         16
+
+
+#define Q_IPV6         17
+#define Q_ICMPV6       18
+#define Q_AH           19
+#define Q_ESP          20
+
+#define Q_PIM          21
+#define Q_VRRP         22
+
+#define Q_AARP         23
+
+#define Q_ISO          24
+#define Q_ESIS         25
+#define Q_ISIS         26
+#define Q_CLNP         27
+
+#define Q_STP          28
+
+#define Q_IPX          29
+
+#define Q_NETBEUI      30
+
+/* IS-IS Levels */
+#define Q_ISIS_L1       31
+#define Q_ISIS_L2       32
+/* PDU types */
+#define Q_ISIS_IIH      33
+#define Q_ISIS_LAN_IIH  34
+#define Q_ISIS_PTP_IIH  35
+#define Q_ISIS_SNP      36
+#define Q_ISIS_CSNP     37
+#define Q_ISIS_PSNP     38
+#define Q_ISIS_LSP      39
+
+#define Q_RADIO                40
+
+#define Q_CARP         41
+
+/* Directional qualifiers. */
+
+#define Q_SRC          1
+#define Q_DST          2
+#define Q_OR           3
+#define Q_AND          4
+#define Q_ADDR1                5
+#define Q_ADDR2                6
+#define Q_ADDR3                7
+#define Q_ADDR4                8
+#define Q_RA           9
+#define Q_TA           10
+
+#define Q_DEFAULT      0
+#define Q_UNDEF                255
+
+/* ATM types */
+#define A_METAC                22      /* Meta signalling Circuit */
+#define A_BCC          23      /* Broadcast Circuit */
+#define A_OAMF4SC      24      /* Segment OAM F4 Circuit */
+#define A_OAMF4EC      25      /* End-to-End OAM F4 Circuit */
+#define A_SC           26      /* Signalling Circuit*/
+#define A_ILMIC                27      /* ILMI Circuit */
+#define A_OAM          28      /* OAM cells : F4 only */
+#define A_OAMF4                29      /* OAM F4 cells: Segment + End-to-end */
+#define A_LANE         30      /* LANE traffic */
+#define A_LLC          31      /* LLC-encapsulated traffic */
+
+/* Based on Q.2931 signalling protocol */
+#define A_SETUP                41      /* Setup message */
+#define A_CALLPROCEED  42      /* Call proceeding message */
+#define A_CONNECT      43      /* Connect message */
+#define A_CONNECTACK   44      /* Connect Ack message */
+#define A_RELEASE      45      /* Release message */
+#define A_RELEASE_DONE 46      /* Release message */
+/* ATM field types */
+#define A_VPI          51
+#define A_VCI          52
+#define A_PROTOTYPE    53
+#define A_MSGTYPE      54
+#define A_CALLREFTYPE  55
+
+#define A_CONNECTMSG   70      /* returns Q.2931 signalling messages for
+                                  establishing and destroying switched
+                                  virtual connection */
+#define A_METACONNECT  71      /* returns Q.2931 signalling messages for
+                                  establishing and destroying predefined
+                                  virtual circuits, such as broadcast
+                                  circuit, oamf4 segment circuit, oamf4
+                                  end-to-end circuits, ILMI circuits or
+                                  connection signalling circuit. */
+
+/* MTP2 types */
+#define M_FISU         22      /* FISU */
+#define M_LSSU         23      /* LSSU */
+#define M_MSU          24      /* MSU */
+
+/* MTP3 field types */
+#define M_SIO          1
+#define M_OPC          2
+#define M_DPC          3
+#define M_SLS          4
+
+
+struct slist;
+
+struct stmt {
+       int code;
+       struct slist *jt;       /*only for relative jump in block*/
+       struct slist *jf;       /*only for relative jump in block*/
+       bpf_int32 k;
+};
+
+struct slist {
+       struct stmt s;
+       struct slist *next;
+};
+
+/*
+ * A bit vector to represent definition sets.  We assume TOT_REGISTERS
+ * is smaller than 8*sizeof(atomset).
+ */
+typedef bpf_u_int32 atomset;
+#define ATOMMASK(n) (1 << (n))
+#define ATOMELEM(d, n) (d & ATOMMASK(n))
+
+/*
+ * An unbounded set.
+ */
+typedef bpf_u_int32 *uset;
+
+/*
+ * Total number of atomic entities, including accumulator (A) and index (X).
+ * We treat all these guys similarly during flow analysis.
+ */
+#define N_ATOMS (BPF_MEMWORDS+2)
+
+struct edge {
+       int id;
+       int code;
+       uset edom;
+       struct block *succ;
+       struct block *pred;
+       struct edge *next;      /* link list of incoming edges for a node */
+};
+
+struct block {
+       int id;
+       struct slist *stmts;    /* side effect stmts */
+       struct stmt s;          /* branch stmt */
+       int mark;
+       u_int longjt;           /* jt branch requires long jump */
+       u_int longjf;           /* jf branch requires long jump */
+       int level;
+       int offset;
+       int sense;
+       struct edge et;
+       struct edge ef;
+       struct block *head;
+       struct block *link;     /* link field used by optimizer */
+       uset dom;
+       uset closure;
+       struct edge *in_edges;
+       atomset def, kill;
+       atomset in_use;
+       atomset out_use;
+       int oval;
+       int val[N_ATOMS];
+};
+
+struct arth {
+       struct block *b;        /* protocol checks */
+       struct slist *s;        /* stmt list */
+       int regno;              /* virtual register number of result */
+};
+
+struct qual {
+       unsigned char addr;
+       unsigned char proto;
+       unsigned char dir;
+       unsigned char pad;
+};
+
+struct arth *gen_loadi(int);
+struct arth *gen_load(int, struct arth *, int);
+struct arth *gen_loadlen(void);
+struct arth *gen_neg(struct arth *);
+struct arth *gen_arth(int, struct arth *, struct arth *);
+
+void gen_and(struct block *, struct block *);
+void gen_or(struct block *, struct block *);
+void gen_not(struct block *);
+
+struct block *gen_scode(const char *, struct qual);
+struct block *gen_ecode(const u_char *, struct qual);
+struct block *gen_acode(const u_char *, struct qual);
+struct block *gen_mcode(const char *, const char *, int, struct qual);
+#ifdef INET6
+struct block *gen_mcode6(const char *, const char *, int, struct qual);
+#endif
+struct block *gen_ncode(const char *, bpf_u_int32, struct qual);
+struct block *gen_proto_abbrev(int);
+struct block *gen_relation(int, struct arth *, struct arth *, int);
+struct block *gen_less(int);
+struct block *gen_greater(int);
+struct block *gen_byteop(int, int, int);
+struct block *gen_broadcast(int);
+struct block *gen_multicast(int);
+struct block *gen_inbound(int);
+
+struct block *gen_vlan(int);
+struct block *gen_mpls(int);
+
+struct block *gen_pppoed(void);
+struct block *gen_pppoes(void);
+
+struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse);
+struct block *gen_atmtype_abbrev(int type);
+struct block *gen_atmmulti_abbrev(int type);
+
+struct block *gen_mtp2type_abbrev(int type);
+struct block *gen_mtp3field_code(int mtp3field, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse);
+
+struct block *gen_pf_ifname(const char *);
+struct block *gen_pf_rnr(int);
+struct block *gen_pf_srnr(int);
+struct block *gen_pf_ruleset(char *);
+struct block *gen_pf_reason(int);
+struct block *gen_pf_action(int);
+struct block *gen_pf_dir(int);
+
+struct block *gen_p80211_type(int, int);
+struct block *gen_p80211_fcdir(int);
+
+void bpf_optimize(struct block **);
+void bpf_error(const char *, ...)
+    __attribute__((noreturn, format (printf, 1, 2)));
+
+void finish_parse(struct block *);
+char *sdup(const char *);
+
+struct bpf_insn *icode_to_fcode(struct block *, u_int *);
+int pcap_parse(void);
+void lex_init(const char *);
+void lex_cleanup(void);
+void sappend(struct slist *, struct slist *);
+
+/* XXX */
+#define JT(b)  ((b)->et.succ)
+#define JF(b)  ((b)->ef.succ)
+
+extern int no_optimize;
diff --git a/grammar.y b/grammar.y
new file mode 100644 (file)
index 0000000..f2ba28b
--- /dev/null
+++ b/grammar.y
@@ -0,0 +1,697 @@
+%{
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.101 2007-11-18 02:03:52 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* WIN32 */
+
+#include <stdlib.h>
+
+#ifndef WIN32
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* WIN32 */
+
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#ifdef HAVE_NET_PFVAR_H
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <net/if_pflog.h>
+#endif
+#include "ieee80211.h"
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#define QSET(q, p, d, a) (q).proto = (p),\
+                        (q).dir = (d),\
+                        (q).addr = (a)
+
+struct tok {
+       int v;                  /* value */
+       const char *s;          /* string */
+};
+
+static const struct tok ieee80211_types[] = {
+       { IEEE80211_FC0_TYPE_DATA, "data" },
+       { IEEE80211_FC0_TYPE_MGT, "mgt" },
+       { IEEE80211_FC0_TYPE_MGT, "management" },
+       { IEEE80211_FC0_TYPE_CTL, "ctl" },
+       { IEEE80211_FC0_TYPE_CTL, "control" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_mgt_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
+       { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
+       { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
+       { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
+       { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
+       { IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
+       { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
+       { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
+       { IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
+       { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
+       { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
+       { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_ctl_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
+       { IEEE80211_FC0_SUBTYPE_RTS, "rts" },
+       { IEEE80211_FC0_SUBTYPE_CTS, "cts" },
+       { IEEE80211_FC0_SUBTYPE_ACK, "ack" },
+       { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
+       { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
+       { 0, NULL }
+};
+static const struct tok ieee80211_data_subtypes[] = {
+       { IEEE80211_FC0_SUBTYPE_DATA, "data" },
+       { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_NODATA, "null" },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll"  },
+       { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
+       { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
+       { 0, NULL }
+};
+struct type2tok {
+       int type;
+       const struct tok *tok;
+};
+static const struct type2tok ieee80211_type_subtypes[] = {
+       { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
+       { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
+       { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
+       { 0, NULL }
+};
+
+static int
+str2tok(const char *str, const struct tok *toks)
+{
+       int i;
+
+       for (i = 0; toks[i].s != NULL; i++) {
+               if (pcap_strcasecmp(toks[i].s, str) == 0)
+                       return (toks[i].v);
+       }
+       return (-1);
+}
+
+int n_errors = 0;
+
+static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror(const char *msg)
+{
+       ++n_errors;
+       bpf_error("%s", msg);
+       /* NOTREACHED */
+}
+
+#ifndef YYBISON
+int yyparse(void);
+
+int
+pcap_parse()
+{
+       return (yyparse());
+}
+#endif
+
+#ifdef HAVE_NET_PFVAR_H
+static int
+pfreason_to_num(const char *reason)
+{
+       const char *reasons[] = PFRES_NAMES;
+       int i;
+
+       for (i = 0; reasons[i]; i++) {
+               if (pcap_strcasecmp(reason, reasons[i]) == 0)
+                       return (i);
+       }
+       bpf_error("unknown PF reason");
+       /*NOTREACHED*/
+}
+
+static int
+pfaction_to_num(const char *action)
+{
+       if (pcap_strcasecmp(action, "pass") == 0 ||
+           pcap_strcasecmp(action, "accept") == 0)
+               return (PF_PASS);
+       else if (pcap_strcasecmp(action, "drop") == 0 ||
+               pcap_strcasecmp(action, "block") == 0)
+               return (PF_DROP);
+#if HAVE_PF_NAT_THROUGH_PF_NORDR
+       else if (pcap_strcasecmp(action, "rdr") == 0)
+               return (PF_RDR);
+       else if (pcap_strcasecmp(action, "nat") == 0)
+               return (PF_NAT);
+       else if (pcap_strcasecmp(action, "binat") == 0)
+               return (PF_BINAT);
+       else if (pcap_strcasecmp(action, "nordr") == 0)
+               return (PF_NORDR);
+#endif
+       else {
+               bpf_error("unknown PF action");
+               /*NOTREACHED*/
+       }
+}
+#else /* !HAVE_NET_PFVAR_H */
+static int
+pfreason_to_num(const char *reason)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
+
+       /* this is to make the VC compiler happy */
+       return -1;
+}
+
+static int
+pfaction_to_num(const char *action)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
+
+       /* this is to make the VC compiler happy */
+       return -1;
+}
+#endif /* HAVE_NET_PFVAR_H */
+%}
+
+%union {
+       int i;
+       bpf_u_int32 h;
+       u_char *e;
+       char *s;
+       struct stmt *stmt;
+       struct arth *a;
+       struct {
+               struct qual q;
+               int atmfieldtype;
+               int mtp3fieldtype;
+               struct block *b;
+       } blk;
+       struct block *rblk;
+}
+
+%type  <blk>   expr id nid pid term rterm qid
+%type  <blk>   head
+%type  <i>     pqual dqual aqual ndaqual
+%type  <a>     arth narth
+%type  <i>     byteop pname pnum relop irelop
+%type  <blk>   and or paren not null prog
+%type  <rblk>  other pfvar p80211
+%type  <i>     atmtype atmmultitype
+%type  <blk>   atmfield
+%type  <blk>   atmfieldvalue atmvalue atmlistvalue
+%type  <i>     mtp2type
+%type  <blk>   mtp3field
+%type  <blk>   mtp3fieldvalue mtp3value mtp3listvalue
+
+
+%token  DST SRC HOST GATEWAY
+%token  NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE
+%token  ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP
+%token  ATALK AARP DECNET LAT SCA MOPRC MOPDL
+%token  TK_BROADCAST TK_MULTICAST
+%token  NUM INBOUND OUTBOUND
+%token  PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
+%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
+%token  LINK
+%token GEQ LEQ NEQ
+%token ID EID HID HID6 AID
+%token LSH RSH
+%token  LEN
+%token  IPV6 ICMPV6 AH ESP
+%token VLAN MPLS
+%token PPPOED PPPOES
+%token  ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP 
+%token  STP
+%token  IPX
+%token  NETBEUI
+%token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC
+%token OAM OAMF4 CONNECTMSG METACONNECT
+%token VPI VCI
+%token RADIO
+%token FISU LSSU MSU
+%token SIO OPC DPC SLS
+
+%type  <s> ID
+%type  <e> EID
+%type  <e> AID
+%type  <s> HID HID6
+%type  <i> NUM action reason type subtype type_subtype dir
+
+%left OR AND
+%nonassoc  '!'
+%left '|'
+%left '&'
+%left LSH RSH
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+%%
+prog:    null expr
+{
+       finish_parse($2.b);
+}
+       | null
+       ;
+null:    /* null */            { $$.q = qerr; }
+       ;
+expr:    term
+       | expr and term         { gen_and($1.b, $3.b); $$ = $3; }
+       | expr and id           { gen_and($1.b, $3.b); $$ = $3; }
+       | expr or term          { gen_or($1.b, $3.b); $$ = $3; }
+       | expr or id            { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+and:     AND                   { $$ = $<blk>0; }
+       ;
+or:      OR                    { $$ = $<blk>0; }
+       ;
+id:      nid
+       | pnum                  { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+                                                  $$.q = $<blk>0.q); }
+       | paren pid ')'         { $$ = $2; }
+       ;
+nid:     ID                    { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
+       | HID '/' NUM           { $$.b = gen_mcode($1, NULL, $3,
+                                   $$.q = $<blk>0.q); }
+       | HID NETMASK HID       { $$.b = gen_mcode($1, $3, 0,
+                                   $$.q = $<blk>0.q); }
+       | HID                   {
+                                 /* Decide how to parse HID based on proto */
+                                 $$.q = $<blk>0.q;
+                                 if ($$.q.addr == Q_PORT)
+                                       bpf_error("'port' modifier applied to ip host");
+                                 else if ($$.q.addr == Q_PORTRANGE)
+                                       bpf_error("'portrange' modifier applied to ip host");
+                                 else if ($$.q.addr == Q_PROTO)
+                                       bpf_error("'proto' modifier applied to ip host");
+                                 else if ($$.q.addr == Q_PROTOCHAIN)
+                                       bpf_error("'protochain' modifier applied to ip host");
+                                 $$.b = gen_ncode($1, 0, $$.q);
+                               }
+       | HID6 '/' NUM          {
+#ifdef INET6
+                                 $$.b = gen_mcode6($1, NULL, $3,
+                                   $$.q = $<blk>0.q);
+#else
+                                 bpf_error("'ip6addr/prefixlen' not supported "
+                                       "in this configuration");
+#endif /*INET6*/
+                               }
+       | HID6                  {
+#ifdef INET6
+                                 $$.b = gen_mcode6($1, 0, 128,
+                                   $$.q = $<blk>0.q);
+#else
+                                 bpf_error("'ip6addr' not supported "
+                                       "in this configuration");
+#endif /*INET6*/
+                               }
+       | EID                   { 
+                                 $$.b = gen_ecode($1, $$.q = $<blk>0.q);
+                                 /*
+                                  * $1 was allocated by "pcap_ether_aton()",
+                                  * so we must free it now that we're done
+                                  * with it.
+                                  */
+                                 free($1);
+                               }
+       | AID                   {
+                                 $$.b = gen_acode($1, $$.q = $<blk>0.q);
+                                 /*
+                                  * $1 was allocated by "pcap_ether_aton()",
+                                  * so we must free it now that we're done
+                                  * with it.
+                                  */
+                                 free($1);
+                               }
+       | not id                { gen_not($2.b); $$ = $2; }
+       ;
+not:     '!'                   { $$ = $<blk>0; }
+       ;
+paren:   '('                   { $$ = $<blk>0; }
+       ;
+pid:     nid
+       | qid and id            { gen_and($1.b, $3.b); $$ = $3; }
+       | qid or id             { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+qid:     pnum                  { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+                                                  $$.q = $<blk>0.q); }
+       | pid
+       ;
+term:    rterm
+       | not term              { gen_not($2.b); $$ = $2; }
+       ;
+head:    pqual dqual aqual     { QSET($$.q, $1, $2, $3); }
+       | pqual dqual           { QSET($$.q, $1, $2, Q_DEFAULT); }
+       | pqual aqual           { QSET($$.q, $1, Q_DEFAULT, $2); }
+       | pqual PROTO           { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
+       | pqual PROTOCHAIN      { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); }
+       | pqual ndaqual         { QSET($$.q, $1, Q_DEFAULT, $2); }
+       ;
+rterm:   head id               { $$ = $2; }
+       | paren expr ')'        { $$.b = $2.b; $$.q = $1.q; }
+       | pname                 { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
+       | arth relop arth       { $$.b = gen_relation($2, $1, $3, 0);
+                                 $$.q = qerr; }
+       | arth irelop arth      { $$.b = gen_relation($2, $1, $3, 1);
+                                 $$.q = qerr; }
+       | other                 { $$.b = $1; $$.q = qerr; }
+       | atmtype               { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; }
+       | atmmultitype          { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; }
+       | atmfield atmvalue     { $$.b = $2.b; $$.q = qerr; }
+       | mtp2type              { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; }
+       | mtp3field mtp3value   { $$.b = $2.b; $$.q = qerr; }
+       ;
+/* protocol level qualifiers */
+pqual:   pname
+       |                       { $$ = Q_DEFAULT; }
+       ;
+/* 'direction' qualifiers */
+dqual:   SRC                   { $$ = Q_SRC; }
+       | DST                   { $$ = Q_DST; }
+       | SRC OR DST            { $$ = Q_OR; }
+       | DST OR SRC            { $$ = Q_OR; }
+       | SRC AND DST           { $$ = Q_AND; }
+       | DST AND SRC           { $$ = Q_AND; }
+       | ADDR1                 { $$ = Q_ADDR1; }
+       | ADDR2                 { $$ = Q_ADDR2; }
+       | ADDR3                 { $$ = Q_ADDR3; }
+       | ADDR4                 { $$ = Q_ADDR4; }
+       | RA                    { $$ = Q_RA; }
+       | TA                    { $$ = Q_TA; }
+       ;
+/* address type qualifiers */
+aqual:   HOST                  { $$ = Q_HOST; }
+       | NET                   { $$ = Q_NET; }
+       | PORT                  { $$ = Q_PORT; }
+       | PORTRANGE             { $$ = Q_PORTRANGE; }
+       ;
+/* non-directional address type qualifiers */
+ndaqual:  GATEWAY              { $$ = Q_GATEWAY; }
+       ;
+pname:   LINK                  { $$ = Q_LINK; }
+       | IP                    { $$ = Q_IP; }
+       | ARP                   { $$ = Q_ARP; }
+       | RARP                  { $$ = Q_RARP; }
+       | SCTP                  { $$ = Q_SCTP; }
+       | TCP                   { $$ = Q_TCP; }
+       | UDP                   { $$ = Q_UDP; }
+       | ICMP                  { $$ = Q_ICMP; }
+       | IGMP                  { $$ = Q_IGMP; }
+       | IGRP                  { $$ = Q_IGRP; }
+       | PIM                   { $$ = Q_PIM; }
+       | VRRP                  { $$ = Q_VRRP; }
+       | CARP                  { $$ = Q_CARP; }
+       | ATALK                 { $$ = Q_ATALK; }
+       | AARP                  { $$ = Q_AARP; }
+       | DECNET                { $$ = Q_DECNET; }
+       | LAT                   { $$ = Q_LAT; }
+       | SCA                   { $$ = Q_SCA; }
+       | MOPDL                 { $$ = Q_MOPDL; }
+       | MOPRC                 { $$ = Q_MOPRC; }
+       | IPV6                  { $$ = Q_IPV6; }
+       | ICMPV6                { $$ = Q_ICMPV6; }
+       | AH                    { $$ = Q_AH; }
+       | ESP                   { $$ = Q_ESP; }
+       | ISO                   { $$ = Q_ISO; }
+       | ESIS                  { $$ = Q_ESIS; }
+       | ISIS                  { $$ = Q_ISIS; }
+       | L1                    { $$ = Q_ISIS_L1; }
+       | L2                    { $$ = Q_ISIS_L2; }
+       | IIH                   { $$ = Q_ISIS_IIH; }
+       | LSP                   { $$ = Q_ISIS_LSP; }
+       | SNP                   { $$ = Q_ISIS_SNP; }
+       | PSNP                  { $$ = Q_ISIS_PSNP; }
+       | CSNP                  { $$ = Q_ISIS_CSNP; }
+       | CLNP                  { $$ = Q_CLNP; }
+       | STP                   { $$ = Q_STP; }
+       | IPX                   { $$ = Q_IPX; }
+       | NETBEUI               { $$ = Q_NETBEUI; }
+       | RADIO                 { $$ = Q_RADIO; }
+       ;
+other:   pqual TK_BROADCAST    { $$ = gen_broadcast($1); }
+       | pqual TK_MULTICAST    { $$ = gen_multicast($1); }
+       | LESS NUM              { $$ = gen_less($2); }
+       | GREATER NUM           { $$ = gen_greater($2); }
+       | CBYTE NUM byteop NUM  { $$ = gen_byteop($3, $2, $4); }
+       | INBOUND               { $$ = gen_inbound(0); }
+       | OUTBOUND              { $$ = gen_inbound(1); }
+       | VLAN pnum             { $$ = gen_vlan($2); }
+       | VLAN                  { $$ = gen_vlan(-1); }
+       | MPLS pnum             { $$ = gen_mpls($2); }
+       | MPLS                  { $$ = gen_mpls(-1); }
+       | PPPOED                { $$ = gen_pppoed(); }
+       | PPPOES                { $$ = gen_pppoes(); }
+       | pfvar                 { $$ = $1; }
+       | pqual p80211          { $$ = $2; }
+       ;
+
+pfvar:   PF_IFNAME ID          { $$ = gen_pf_ifname($2); }
+       | PF_RSET ID            { $$ = gen_pf_ruleset($2); }
+       | PF_RNR NUM            { $$ = gen_pf_rnr($2); }
+       | PF_SRNR NUM           { $$ = gen_pf_srnr($2); }
+       | PF_REASON reason      { $$ = gen_pf_reason($2); }
+       | PF_ACTION action      { $$ = gen_pf_action($2); }
+       ;
+
+p80211:   TYPE type SUBTYPE subtype
+                               { $$ = gen_p80211_type($2 | $4,
+                                       IEEE80211_FC0_TYPE_MASK |
+                                       IEEE80211_FC0_SUBTYPE_MASK);
+                               }
+       | TYPE type             { $$ = gen_p80211_type($2,
+                                       IEEE80211_FC0_TYPE_MASK);
+                               }
+       | SUBTYPE type_subtype  { $$ = gen_p80211_type($2,
+                                       IEEE80211_FC0_TYPE_MASK |
+                                       IEEE80211_FC0_SUBTYPE_MASK);
+                               }
+       | DIR dir               { $$ = gen_p80211_fcdir($2); }
+       ;
+
+type:    NUM
+       | ID                    { $$ = str2tok($1, ieee80211_types);
+                                 if ($$ == -1)
+                                       bpf_error("unknown 802.11 type name");
+                               }
+       ;
+
+subtype:  NUM
+       | ID                    { const struct tok *types = NULL;
+                                 int i;
+                                 for (i = 0;; i++) {
+                                       if (ieee80211_type_subtypes[i].tok == NULL) {
+                                               /* Ran out of types */
+                                               bpf_error("unknown 802.11 type");
+                                               break;
+                                       }
+                                       if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+                                               types = ieee80211_type_subtypes[i].tok;
+                                               break;
+                                       }
+                                 }
+
+                                 $$ = str2tok($1, types);
+                                 if ($$ == -1)
+                                       bpf_error("unknown 802.11 subtype name");
+                               }
+       ;
+
+type_subtype:  ID              { int i;
+                                 for (i = 0;; i++) {
+                                       if (ieee80211_type_subtypes[i].tok == NULL) {
+                                               /* Ran out of types */
+                                               bpf_error("unknown 802.11 type name");
+                                               break;
+                                       }
+                                       $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
+                                       if ($$ != -1) {
+                                               $$ |= ieee80211_type_subtypes[i].type;
+                                               break;
+                                       }
+                                 }
+                               }
+               ;
+
+dir:     NUM
+       | ID                    { if (pcap_strcasecmp($1, "nods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_NODS;
+                                 else if (pcap_strcasecmp($1, "tods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_TODS;
+                                 else if (pcap_strcasecmp($1, "fromds") == 0)
+                                       $$ = IEEE80211_FC1_DIR_FROMDS;
+                                 else if (pcap_strcasecmp($1, "dstods") == 0)
+                                       $$ = IEEE80211_FC1_DIR_DSTODS;
+                                 else
+                                       bpf_error("unknown 802.11 direction");
+                               }
+       ;
+
+reason:          NUM                   { $$ = $1; }
+       | ID                    { $$ = pfreason_to_num($1); }
+       ;
+
+action:          ID                    { $$ = pfaction_to_num($1); }
+       ;
+
+relop:   '>'                   { $$ = BPF_JGT; }
+       | GEQ                   { $$ = BPF_JGE; }
+       | '='                   { $$ = BPF_JEQ; }
+       ;
+irelop:          LEQ                   { $$ = BPF_JGT; }
+       | '<'                   { $$ = BPF_JGE; }
+       | NEQ                   { $$ = BPF_JEQ; }
+       ;
+arth:    pnum                  { $$ = gen_loadi($1); }
+       | narth
+       ;
+narth:   pname '[' arth ']'            { $$ = gen_load($1, $3, 1); }
+       | pname '[' arth ':' NUM ']'    { $$ = gen_load($1, $3, $5); }
+       | arth '+' arth                 { $$ = gen_arth(BPF_ADD, $1, $3); }
+       | arth '-' arth                 { $$ = gen_arth(BPF_SUB, $1, $3); }
+       | arth '*' arth                 { $$ = gen_arth(BPF_MUL, $1, $3); }
+       | arth '/' arth                 { $$ = gen_arth(BPF_DIV, $1, $3); }
+       | arth '&' arth                 { $$ = gen_arth(BPF_AND, $1, $3); }
+       | arth '|' arth                 { $$ = gen_arth(BPF_OR, $1, $3); }
+       | arth LSH arth                 { $$ = gen_arth(BPF_LSH, $1, $3); }
+       | arth RSH arth                 { $$ = gen_arth(BPF_RSH, $1, $3); }
+       | '-' arth %prec UMINUS         { $$ = gen_neg($2); }
+       | paren narth ')'               { $$ = $2; }
+       | LEN                           { $$ = gen_loadlen(); }
+       ;
+byteop:          '&'                   { $$ = '&'; }
+       | '|'                   { $$ = '|'; }
+       | '<'                   { $$ = '<'; }
+       | '>'                   { $$ = '>'; }
+       | '='                   { $$ = '='; }
+       ;
+pnum:    NUM
+       | paren pnum ')'        { $$ = $2; }
+       ;
+atmtype: LANE                  { $$ = A_LANE; }
+       | LLC                   { $$ = A_LLC; }
+       | METAC                 { $$ = A_METAC; }
+       | BCC                   { $$ = A_BCC; }
+       | OAMF4EC               { $$ = A_OAMF4EC; }
+       | OAMF4SC               { $$ = A_OAMF4SC; }
+       | SC                    { $$ = A_SC; }
+       | ILMIC                 { $$ = A_ILMIC; }
+       ;
+atmmultitype: OAM              { $$ = A_OAM; }
+       | OAMF4                 { $$ = A_OAMF4; }
+       | CONNECTMSG            { $$ = A_CONNECTMSG; }
+       | METACONNECT           { $$ = A_METACONNECT; }
+       ;
+       /* ATM field types quantifier */
+atmfield: VPI                  { $$.atmfieldtype = A_VPI; }
+       | VCI                   { $$.atmfieldtype = A_VCI; }
+       ;
+atmvalue: atmfieldvalue
+       | relop NUM             { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
+       | irelop NUM            { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
+       | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
+       ;
+atmfieldvalue: NUM {
+       $$.atmfieldtype = $<blk>0.atmfieldtype;
+       if ($$.atmfieldtype == A_VPI ||
+           $$.atmfieldtype == A_VCI)
+               $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
+       }
+       ;
+atmlistvalue: atmfieldvalue
+       | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+       /* MTP2 types quantifier */
+mtp2type: FISU                 { $$ = M_FISU; }
+       | LSSU                  { $$ = M_LSSU; }
+       | MSU                   { $$ = M_MSU; }
+       ;
+       /* MTP3 field types quantifier */
+mtp3field: SIO                 { $$.mtp3fieldtype = M_SIO; }
+       | OPC                   { $$.mtp3fieldtype = M_OPC; }
+       | DPC                   { $$.mtp3fieldtype = M_DPC; }
+       | SLS                   { $$.mtp3fieldtype = M_SLS; }
+       ;
+mtp3value: mtp3fieldvalue
+       | relop NUM             { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
+       | irelop NUM            { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
+       | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
+       ;
+mtp3fieldvalue: NUM {
+       $$.mtp3fieldtype = $<blk>0.mtp3fieldtype;
+       if ($$.mtp3fieldtype == M_SIO ||
+           $$.mtp3fieldtype == M_OPC ||
+           $$.mtp3fieldtype == M_DPC ||
+           $$.mtp3fieldtype == M_SLS )
+               $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+       }
+       ;
+mtp3listvalue: mtp3fieldvalue
+       | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+%%
diff --git a/ieee80211.h b/ieee80211.h
new file mode 100644 (file)
index 0000000..473803d
--- /dev/null
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/net80211/ieee80211.h,v 1.10 2005/07/22 16:55:27 sam Exp $
+ */
+#ifndef _NET80211_IEEE80211_H_
+#define _NET80211_IEEE80211_H_
+
+/*
+ * 802.11 protocol definitions.
+ */
+
+#define        IEEE80211_FC0_VERSION_MASK              0x03
+#define        IEEE80211_FC0_VERSION_SHIFT             0
+#define        IEEE80211_FC0_VERSION_0                 0x00
+#define        IEEE80211_FC0_TYPE_MASK                 0x0c
+#define        IEEE80211_FC0_TYPE_SHIFT                2
+#define        IEEE80211_FC0_TYPE_MGT                  0x00
+#define        IEEE80211_FC0_TYPE_CTL                  0x04
+#define        IEEE80211_FC0_TYPE_DATA                 0x08
+
+#define        IEEE80211_FC0_SUBTYPE_MASK              0xf0
+#define        IEEE80211_FC0_SUBTYPE_SHIFT             4
+/* for TYPE_MGT */
+#define        IEEE80211_FC0_SUBTYPE_ASSOC_REQ         0x00
+#define        IEEE80211_FC0_SUBTYPE_ASSOC_RESP        0x10
+#define        IEEE80211_FC0_SUBTYPE_REASSOC_REQ       0x20
+#define        IEEE80211_FC0_SUBTYPE_REASSOC_RESP      0x30
+#define        IEEE80211_FC0_SUBTYPE_PROBE_REQ         0x40
+#define        IEEE80211_FC0_SUBTYPE_PROBE_RESP        0x50
+#define        IEEE80211_FC0_SUBTYPE_BEACON            0x80
+#define        IEEE80211_FC0_SUBTYPE_ATIM              0x90
+#define        IEEE80211_FC0_SUBTYPE_DISASSOC          0xa0
+#define        IEEE80211_FC0_SUBTYPE_AUTH              0xb0
+#define        IEEE80211_FC0_SUBTYPE_DEAUTH            0xc0
+/* for TYPE_CTL */
+#define        IEEE80211_FC0_SUBTYPE_PS_POLL           0xa0
+#define        IEEE80211_FC0_SUBTYPE_RTS               0xb0
+#define        IEEE80211_FC0_SUBTYPE_CTS               0xc0
+#define        IEEE80211_FC0_SUBTYPE_ACK               0xd0
+#define        IEEE80211_FC0_SUBTYPE_CF_END            0xe0
+#define        IEEE80211_FC0_SUBTYPE_CF_END_ACK        0xf0
+/* for TYPE_DATA (bit combination) */
+#define        IEEE80211_FC0_SUBTYPE_DATA              0x00
+#define        IEEE80211_FC0_SUBTYPE_CF_ACK            0x10
+#define        IEEE80211_FC0_SUBTYPE_CF_POLL           0x20
+#define        IEEE80211_FC0_SUBTYPE_CF_ACPL           0x30
+#define        IEEE80211_FC0_SUBTYPE_NODATA            0x40
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK     0x50
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL    0x60
+#define        IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL    0x70
+#define        IEEE80211_FC0_SUBTYPE_QOS               0x80
+#define        IEEE80211_FC0_SUBTYPE_QOS_NULL          0xc0
+
+#define        IEEE80211_FC1_DIR_MASK                  0x03
+#define        IEEE80211_FC1_DIR_NODS                  0x00    /* STA->STA */
+#define        IEEE80211_FC1_DIR_TODS                  0x01    /* STA->AP  */
+#define        IEEE80211_FC1_DIR_FROMDS                0x02    /* AP ->STA */
+#define        IEEE80211_FC1_DIR_DSTODS                0x03    /* AP ->AP  */
+
+#define        IEEE80211_FC1_MORE_FRAG                 0x04
+#define        IEEE80211_FC1_RETRY                     0x08
+#define        IEEE80211_FC1_PWR_MGT                   0x10
+#define        IEEE80211_FC1_MORE_DATA                 0x20
+#define        IEEE80211_FC1_WEP                       0x40
+#define        IEEE80211_FC1_ORDER                     0x80
+
+#define        IEEE80211_SEQ_FRAG_MASK                 0x000f
+#define        IEEE80211_SEQ_FRAG_SHIFT                0
+#define        IEEE80211_SEQ_SEQ_MASK                  0xfff0
+#define        IEEE80211_SEQ_SEQ_SHIFT                 4
+
+#define        IEEE80211_NWID_LEN                      32
+
+#define        IEEE80211_QOS_TXOP                      0x00ff
+/* bit 8 is reserved */
+#define        IEEE80211_QOS_ACKPOLICY                 0x60
+#define        IEEE80211_QOS_ACKPOLICY_S               5
+#define        IEEE80211_QOS_ESOP                      0x10
+#define        IEEE80211_QOS_ESOP_S                    4
+#define        IEEE80211_QOS_TID                       0x0f
+
+#define IEEE80211_MGT_SUBTYPE_NAMES {                  \
+       "assoc-req",            "assoc-resp",           \
+       "reassoc-req",          "reassoc-resp",         \
+       "probe-req",            "probe-resp",           \
+       "reserved#6",           "reserved#7",           \
+       "beacon",               "atim",                 \
+       "disassoc",             "auth",                 \
+       "deauth",               "reserved#13",          \
+       "reserved#14",          "reserved#15"           \
+}
+
+#define IEEE80211_CTL_SUBTYPE_NAMES {                  \
+       "reserved#0",           "reserved#1",           \
+       "reserved#2",           "reserved#3",           \
+       "reserved#3",           "reserved#5",           \
+       "reserved#6",           "reserved#7",           \
+       "reserved#8",           "reserved#9",           \
+       "ps-poll",              "rts",                  \
+       "cts",                  "ack",                  \
+       "cf-end",               "cf-end-ack"            \
+}
+
+#define IEEE80211_DATA_SUBTYPE_NAMES {                 \
+       "data",                 "data-cf-ack",          \
+       "data-cf-poll",         "data-cf-ack-poll",     \
+       "null",                 "cf-ack",               \
+       "cf-poll",              "cf-ack-poll",          \
+       "qos-data",             "qos-data-cf-ack",      \
+       "qos-data-cf-poll",     "qos-data-cf-ack-poll", \
+       "qos",                  "reserved#13",          \
+       "qos-cf-poll",          "qos-cf-ack-poll"       \
+}
+
+#define IEEE80211_TYPE_NAMES   { "mgt", "ctl", "data", "reserved#4" }
+
+#endif /* _NET80211_IEEE80211_H_ */
diff --git a/inet.c b/inet.c
new file mode 100644 (file)
index 0000000..6ae46ef
--- /dev/null
+++ b/inet.c
@@ -0,0 +1,933 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#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
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+
+#include <sys/param.h>
+#ifndef MSDOS
+#include <sys/file.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+#endif /* WIN32 */
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(WIN32) && !defined(__BORLANDC__)
+#include <unistd.h>
+#endif /* !WIN32 && !__BORLANDC__ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX                2147483647
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
+    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
+#endif
+
+struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+       struct sockaddr *newsa;
+
+       if ((newsa = malloc(sa_length)) == NULL)
+               return (NULL);
+       return (memcpy(newsa, sa, sa_length));
+}
+
+static int
+get_instance(const char *name)
+{
+       const char *cp, *endcp;
+       int n;
+
+       if (strcmp(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;
+       }
+
+       endcp = name + strlen(name);
+       for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
+               continue;
+
+       if (isdigit((unsigned char)*cp))
+               n = atoi(cp);
+       else
+               n = 0;
+       return (n);
+}
+
+int
+add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
+    u_int flags, const char *description, char *errbuf)
+{
+       pcap_t *p;
+       pcap_if_t *curdev, *prevdev, *nextdev;
+       int this_instance;
+       char open_errbuf[PCAP_ERRBUF_SIZE];
+
+       /*
+        * Is there already an entry in the list for this interface?
+        */
+       for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
+               if (strcmp(name, curdev->name) == 0)
+                       break;  /* yes, we found it */
+       }
+
+       if (curdev == NULL) {
+               /*
+                * No, we didn't find it.
+                *
+                * Can we open this interface for live capture?
+                *
+                * We do this check so that interfaces that are
+                * supplied by the interface enumeration mechanism
+                * we're using but that don't support packet capture
+                * aren't included in the list.  Loopback interfaces
+                * on Solaris are an example of this; we don't just
+                * omit loopback interfaces on all platforms because
+                * you *can* capture on loopback interfaces on some
+                * OSes.
+                *
+                * On OS X, we don't do this check if the device
+                * name begins with "wlt"; at least some versions
+                * of OS X offer monitor mode capturing by having
+                * a separate "monitor mode" device for each wireless
+                * adapter, rather than by implementing the ioctls
+                * that {Free,Net,Open,DragonFly}BSD provide.
+                * Opening that device puts the adapter into monitor
+                * mode, which, at least for some adapters, causes
+                * them to deassociate from the network with which
+                * they're associated.
+                *
+                * Instead, we try to open the corresponding "en"
+                * device (so that we don't end up with, for users
+                * without sufficient privilege to open capture
+                * devices, a list of adapters that only includes
+                * the wlt devices).
+                */
+#ifdef __APPLE__
+               if (strncmp(name, "wlt", 3) == 0) {
+                       char *en_name;
+                       size_t en_name_len;
+
+                       /*
+                        * Try to allocate a buffer for the "en"
+                        * device's name.
+                        */
+                       en_name_len = strlen(name) - 1;
+                       en_name = malloc(en_name_len + 1);
+                       if (en_name == NULL) {
+                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "malloc: %s", pcap_strerror(errno));
+                               return (-1);
+                       }
+                       strcpy(en_name, "en");
+                       strcat(en_name, name + 3);
+                       p = pcap_open_live(en_name, 68, 0, 0, open_errbuf);
+                       free(en_name);
+               } else
+#endif /* __APPLE */
+               p = pcap_open_live(name, 68, 0, 0, open_errbuf);
+               if (p == NULL) {
+                       /*
+                        * No.  Don't bother including it.
+                        * Don't treat this as an error, though.
+                        */
+                       *curdev_ret = NULL;
+                       return (0);
+               }
+               pcap_close(p);
+
+               /*
+                * Yes, we can open it.
+                * Allocate a new entry.
+                */
+               curdev = malloc(sizeof(pcap_if_t));
+               if (curdev == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+
+               /*
+                * Fill in the entry.
+                */
+               curdev->next = NULL;
+               curdev->name = strdup(name);
+               if (curdev->name == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curdev);
+                       return (-1);
+               }
+               if (description != NULL) {
+                       /*
+                        * We have a description for this interface.
+                        */
+                       curdev->description = strdup(description);
+                       if (curdev->description == NULL) {
+                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "malloc: %s", pcap_strerror(errno));
+                               free(curdev->name);
+                               free(curdev);
+                               return (-1);
+                       }
+               } else {
+                       /*
+                        * We don't.
+                        */
+                       curdev->description = NULL;
+               }
+               curdev->addresses = NULL;       /* list starts out as empty */
+               curdev->flags = 0;
+               if (ISLOOPBACK(name, flags))
+                       curdev->flags |= PCAP_IF_LOOPBACK;
+
+               /*
+                * Add it to the list, in the appropriate location.
+                * First, get the instance number of this interface.
+                */
+               this_instance = get_instance(name);
+
+               /*
+                * 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.
+                *
+                * We start with "prevdev" being NULL, meaning we're before
+                * the first element in the list.
+                */
+               prevdev = NULL;
+               for (;;) {
+                       /*
+                        * Get the interface after this one.
+                        */
+                       if (prevdev == NULL) {
+                               /*
+                                * The next element is the first element.
+                                */
+                               nextdev = *alldevs;
+                       } else
+                               nextdev = prevdev->next;
+
+                       /*
+                        * Are we at the end of the list?
+                        */
+                       if (nextdev == NULL) {
+                               /*
+                                * Yes - we have to put the new entry
+                                * after "prevdev".
+                                */
+                               break;
+                       }
+
+                       /*
+                        * Is the new interface a non-loopback interface
+                        * and the next interface a loopback 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))) {
+                               /*
+                                * Yes - we should put the new entry
+                                * before "nextdev", i.e. after "prevdev".
+                                */
+                               break;
+                       }
+
+                       prevdev = nextdev;
+               }
+
+               /*
+                * Insert before "nextdev".
+                */
+               curdev->next = nextdev;
+
+               /*
+                * Insert after "prevdev" - unless "prevdev" is null,
+                * in which case this is the first interface.
+                */
+               if (prevdev == NULL) {
+                       /*
+                        * This is the first interface.  Pass back a
+                        * pointer to it, and put "curdev" before
+                        * "nextdev".
+                        */
+                       *alldevs = curdev;
+               } else
+                       prevdev->next = curdev;
+       }
+
+       *curdev_ret = curdev;
+       return (0);
+}
+
+/*
+ * 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?
+ */
+int
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
+    struct sockaddr *addr, size_t addr_size,
+    struct sockaddr *netmask, size_t netmask_size,
+    struct sockaddr *broadaddr, size_t broadaddr_size,
+    struct sockaddr *dstaddr, size_t dstaddr_size,
+    char *errbuf)
+{
+       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);
+               /*
+                * Error - give up.
+                */
+               return (-1);
+       }
+       free(description);
+       if (curdev == NULL) {
+               /*
+                * Device wasn't added because it can't be opened.
+                * Not a fatal error.
+                */
+               return (0);
+       }
+
+       /*
+        * "curdev" is an entry for this interface; add an entry for this
+        * address to its list of addresses.
+        *
+        * Allocate the new entry and fill it in.
+        */
+       curaddr = malloc(sizeof(pcap_addr_t));
+       if (curaddr == NULL) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "malloc: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       curaddr->next = NULL;
+       if (addr != NULL) {
+               curaddr->addr = dup_sockaddr(addr, addr_size);
+               if (curaddr->addr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->addr = NULL;
+
+       if (netmask != NULL) {
+               curaddr->netmask = dup_sockaddr(netmask, netmask_size);
+               if (curaddr->netmask == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       if (curaddr->addr != NULL)
+                               free(curaddr->addr);
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->netmask = NULL;
+
+       if (broadaddr != NULL) {
+               curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
+               if (curaddr->broadaddr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       if (curaddr->netmask != NULL)
+                               free(curaddr->netmask);
+                       if (curaddr->addr != NULL)
+                               free(curaddr->addr);
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->broadaddr = NULL;
+
+       if (dstaddr != NULL) {
+               curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
+               if (curaddr->dstaddr == NULL) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       if (curaddr->broadaddr != NULL)
+                               free(curaddr->broadaddr);
+                       if (curaddr->netmask != NULL)
+                               free(curaddr->netmask);
+                       if (curaddr->addr != NULL)
+                               free(curaddr->addr);
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->dstaddr = NULL;
+
+       /*
+        * Find the end of the list of addresses.
+        */
+       for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
+               nextaddr = prevaddr->next;
+               if (nextaddr == NULL) {
+                       /*
+                        * This is the end of the list.
+                        */
+                       break;
+               }
+       }
+
+       if (prevaddr == NULL) {
+               /*
+                * The list was empty; this is the first member.
+                */
+               curdev->addresses = curaddr;
+       } else {
+               /*
+                * "prevaddr" is the last member of the list; append
+                * this member to it.
+                */
+               prevaddr->next = curaddr;
+       }
+
+       return (0);
+}
+
+int
+pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
+    const char *description, char *errbuf)
+{
+       pcap_if_t *curdev;
+
+       return (add_or_find_if(&curdev, devlist, name, flags, description,
+           errbuf));
+}
+
+
+/*
+ * Free a list of interfaces.
+ */
+void
+pcap_freealldevs(pcap_if_t *alldevs)
+{
+       pcap_if_t *curdev, *nextdev;
+       pcap_addr_t *curaddr, *nextaddr;
+
+       for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
+               nextdev = curdev->next;
+
+               /*
+                * Free all addresses.
+                */
+               for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
+                       nextaddr = curaddr->next;
+                       if (curaddr->addr)
+                               free(curaddr->addr);
+                       if (curaddr->netmask)
+                               free(curaddr->netmask);
+                       if (curaddr->broadaddr)
+                               free(curaddr->broadaddr);
+                       if (curaddr->dstaddr)
+                               free(curaddr->dstaddr);
+                       free(curaddr);
+               }
+
+               /*
+                * Free the name string.
+                */
+               free(curdev->name);
+
+               /*
+                * Free the description string, if any.
+                */
+               if (curdev->description != NULL)
+                       free(curdev->description);
+
+               /*
+                * Free the interface.
+                */
+               free(curdev);
+       }
+}
+
+#if !defined(WIN32) && !defined(MSDOS)
+
+/*
+ * 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 */
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/lbl/os-aix4.h b/lbl/os-aix4.h
new file mode 100644 (file)
index 0000000..c5dfce2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-aix4.h,v 1.1 2002-06-01 09:37:40 guy Exp $
+ */
+
+/* Prototypes missing in AIX 4.x */
+int    ffs(int i);
diff --git a/lbl/os-hpux11.h b/lbl/os-hpux11.h
new file mode 100644 (file)
index 0000000..5e325a9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-hpux11.h,v 1.1 2002-06-01 09:37:41 guy Exp $
+ */
+
+/* Prototypes missing in HP-UX 11.x */
+int    ffs(int i);
diff --git a/lbl/os-osf4.h b/lbl/os-osf4.h
new file mode 100644 (file)
index 0000000..60abcd9
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-osf4.h,v 1.2 2000-12-22 11:51:33 guy Exp $ (LBL)
+ */
+
+/* Prototypes missing in Digital UNIX 4.x */
+int    snprintf(char *, size_t, const char *, ...);
+int    vsnprintf(char *, size_t, const char *, va_list);
+int    pfopen(char *, int);
+   
diff --git a/lbl/os-osf5.h b/lbl/os-osf5.h
new file mode 100644 (file)
index 0000000..1ebcac6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-osf5.h,v 1.2 2002-08-02 03:24:15 guy Exp $ (LBL)
+ */
+
+/*
+ * Prototypes missing in Tru64 UNIX 5.x
+ * XXX - "snprintf()" and "vsnprintf()" aren't missing, but you have to
+ * #define the right value to get them defined by <stdio.h>.
+ */
+int    snprintf(char *, size_t, const char *, ...);
+int    vsnprintf(char *, size_t, const char *, va_list);
+int    pfopen(char *, int);
+   
diff --git a/lbl/os-solaris2.h b/lbl/os-solaris2.h
new file mode 100644 (file)
index 0000000..fae2aa3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-solaris2.h,v 1.19 2000-10-11 04:02:52 guy Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 5 */
+char    *strerror(int);
+int    snprintf(char *, size_t, const char *, ...);
diff --git a/lbl/os-sunos4.h b/lbl/os-sunos4.h
new file mode 100644 (file)
index 0000000..cfd4b04
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1989, 1990, 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-sunos4.h,v 1.32 1999-10-07 23:46:41 mcr Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 4 */
+#ifdef FILE
+int    _filbuf(FILE *);
+int    _flsbuf(u_char, FILE *);
+int    fclose(FILE *);
+int    fflush(FILE *);
+int    fgetc(FILE *);
+int    fprintf(FILE *, const char *, ...);
+int    fputc(int, FILE *);
+int    fputs(const char *, FILE *);
+u_int  fread(void *, u_int, u_int, FILE *);
+int    fseek(FILE *, long, int);
+u_int  fwrite(const void *, u_int, u_int, FILE *);
+int    pclose(FILE *);
+void   rewind(FILE *);
+void   setbuf(FILE *, char *);
+int    setlinebuf(FILE *);
+int    ungetc(int, FILE *);
+int    vfprintf(FILE *, const char *, ...);
+int    vprintf(const char *, ...);
+#endif
+
+#if __GNUC__ <= 1
+int    read(int, char *, u_int);
+int    write(int, char *, u_int);
+#endif
+
+long   a64l(const char *);
+#ifdef __STDC__
+struct sockaddr;
+#endif
+int    accept(int, struct sockaddr *, int *);
+int    bind(int, struct sockaddr *, int);
+int    bcmp(const void *, const void *, u_int);
+void   bcopy(const void *, void *, u_int);
+void   bzero(void *, int);
+int    chroot(const char *);
+int    close(int);
+void   closelog(void);
+int    connect(int, struct sockaddr *, int);
+char   *crypt(const char *, const char *);
+int    daemon(int, int);
+int    fchmod(int, int);
+int    fchown(int, int, int);
+void   endgrent(void);
+void   endpwent(void);
+void   endservent(void);
+#ifdef __STDC__
+struct ether_addr;
+#endif
+struct ether_addr *ether_aton(const char *);
+int    flock(int, int);
+#ifdef __STDC__
+struct stat;
+#endif
+int    fstat(int, struct stat *);
+#ifdef __STDC__
+struct statfs;
+#endif
+int    fstatfs(int, struct statfs *);
+int    fsync(int);
+#ifdef __STDC__
+struct timeb;
+#endif
+int    ftime(struct timeb *);
+int    ftruncate(int, off_t);
+int    getdtablesize(void);
+long   gethostid(void);
+int    gethostname(char *, int);
+int    getopt(int, char * const *, const char *);
+int    getpagesize(void);
+char   *getpass(char *);
+int    getpeername(int, struct sockaddr *, int *);
+int    getpriority(int, int);
+#ifdef __STDC__
+struct rlimit;
+#endif
+int    getrlimit(int, struct rlimit *);
+int    getsockname(int, struct sockaddr *, int *);
+int    getsockopt(int, int, int, char *, int *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int    gettimeofday(struct timeval *, struct timezone *);
+char   *getusershell(void);
+char   *getwd(char *);
+int    initgroups(const char *, int);
+int    ioctl(int, int, caddr_t);
+int    iruserok(u_long, int, char *, char *);
+int    isatty(int);
+int    killpg(int, int);
+int    listen(int, int);
+#ifdef __STDC__
+struct utmp;
+#endif
+void   login(struct utmp *);
+int    logout(const char *);
+off_t  lseek(int, off_t, int);
+int    lstat(const char *, struct stat *);
+int    mkstemp(char *);
+char   *mktemp(char *);
+int    munmap(caddr_t, int);
+void   openlog(const char *, int, int);
+void   perror(const char *);
+int    printf(const char *, ...);
+int    puts(const char *);
+long   random(void);
+int    readlink(const char *, char *, int);
+#ifdef __STDC__
+struct iovec;
+#endif
+int    readv(int, struct iovec *, int);
+int    recv(int, char *, u_int, int);
+int    recvfrom(int, char *, u_int, int, struct sockaddr *, int *);
+int    rename(const char *, const char *);
+int    rcmd(char **, u_short, char *, char *, char *, int *);
+int    rresvport(int *);
+int    send(int, char *, u_int, int);
+int    sendto(int, char *, u_int, int, struct sockaddr *, int);
+int    setenv(const char *, const char *, int);
+int    seteuid(int);
+int    setpriority(int, int, int);
+int    select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int    setpgrp(int, int);
+void   setpwent(void);
+int    setrlimit(int, struct rlimit *);
+void   setservent(int);
+int    setsockopt(int, int, int, char *, int);
+int    shutdown(int, int);
+int    sigblock(int);
+void   (*signal (int, void (*) (int))) (int);
+int    sigpause(int);
+int    sigsetmask(int);
+#ifdef __STDC__
+struct sigvec;
+#endif
+int    sigvec(int, struct sigvec *, struct sigvec*);
+int    snprintf(char *, size_t, const char *, ...);
+int    socket(int, int, int);
+int    socketpair(int, int, int, int *);
+int    symlink(const char *, const char *);
+void   srandom(int);
+int    sscanf(char *, const char *, ...);
+int    stat(const char *, struct stat *);
+int    statfs(char *, struct statfs *);
+char   *strerror(int);
+int    strcasecmp(const char *, const char *);
+#ifdef __STDC__
+struct tm;
+#endif
+int    strftime(char *, int, char *, struct tm *);
+int    strncasecmp(const char *, const char *, int);
+long   strtol(const char *, char **, int);
+void   sync(void);
+void   syslog(int, const char *, ...);
+int    system(const char *);
+long   tell(int);
+time_t time(time_t *);
+char   *timezone(int, int);
+int    tolower(int);
+int    toupper(int);
+int    truncate(char *, off_t);
+void   unsetenv(const char *);
+int    vfork(void);
+int    vsprintf(char *, const char *, ...);
+int    writev(int, struct iovec *, int);
+#ifdef __STDC__
+struct rusage;
+#endif
+int    utimes(const char *, struct timeval *);
+#if __GNUC__ <= 1
+int    wait(int *);
+pid_t  wait3(int *, int, struct rusage *);
+#endif
+
+/* Ugly signal hacking */
+#ifdef SIG_ERR
+#undef SIG_ERR
+#define SIG_ERR                (void (*)(int))-1
+#undef SIG_DFL
+#define SIG_DFL                (void (*)(int))0
+#undef SIG_IGN
+#define SIG_IGN                (void (*)(int))1
+
+#ifdef KERNEL
+#undef SIG_CATCH
+#define SIG_CATCH      (void (*)(int))2
+#endif
+#undef SIG_HOLD
+#define SIG_HOLD       (void (*)(int))3
+#endif
diff --git a/lbl/os-ultrix4.h b/lbl/os-ultrix4.h
new file mode 100644 (file)
index 0000000..9f2a155
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1990, 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/lbl/os-ultrix4.h,v 1.19 1999-10-07 23:46:41 mcr Exp $ (LBL)
+ */
+
+/* Prototypes missing in Ultrix 4 */
+int    bcmp(const char *, const char *, u_int);
+void   bcopy(const void *, void *, u_int);
+void   bzero(void *, u_int);
+void   endservent(void);
+int    getopt(int, char * const *, const char *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int    gettimeofday(struct timeval *, struct timezone *);
+int    ioctl(int, int, caddr_t);
+int    pfopen(char *, int);
+int    setlinebuf(FILE *);
+int    socket(int, int, int);
+int    strcasecmp(const char *, const char *);
diff --git a/llc.h b/llc.h
new file mode 100644 (file)
index 0000000..b8c221f
--- /dev/null
+++ b/llc.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1993, 1994, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/llc.h,v 1.2 2001-01-28 09:44:50 guy Exp $ (LBL)
+ */
+
+/*
+ * 802.2 LLC SAP values.
+ */
+
+#ifndef LLCSAP_NULL
+#define        LLCSAP_NULL             0x00
+#endif
+#ifndef LLCSAP_GLOBAL
+#define        LLCSAP_GLOBAL           0xff
+#endif
+#ifndef LLCSAP_8021B
+#define        LLCSAP_8021B_I          0x02
+#endif
+#ifndef LLCSAP_8021B
+#define        LLCSAP_8021B_G          0x03
+#endif
+#ifndef LLCSAP_IP
+#define        LLCSAP_IP               0x06
+#endif
+#ifndef LLCSAP_PROWAYNM
+#define        LLCSAP_PROWAYNM         0x0e
+#endif
+#ifndef LLCSAP_8021D
+#define        LLCSAP_8021D            0x42
+#endif
+#ifndef LLCSAP_RS511
+#define        LLCSAP_RS511            0x4e
+#endif
+#ifndef LLCSAP_ISO8208
+#define        LLCSAP_ISO8208          0x7e
+#endif
+#ifndef LLCSAP_PROWAY
+#define        LLCSAP_PROWAY           0x8e
+#endif
+#ifndef LLCSAP_SNAP
+#define        LLCSAP_SNAP             0xaa
+#endif
+#ifndef LLCSAP_IPX
+#define LLCSAP_IPX             0xe0
+#endif
+#ifndef LLCSAP_NETBEUI
+#define LLCSAP_NETBEUI         0xf0
+#endif
+#ifndef LLCSAP_ISONS
+#define        LLCSAP_ISONS            0xfe
+#endif
diff --git a/missing/snprintf.c b/missing/snprintf.c
new file mode 100644 (file)
index 0000000..8991f24
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: snprintf.c,v 1.1 2004-04-05 22:43:51 guy Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef lint
+static const char rcsid[] _U_ =
+     "@(#) $Header: /tcpdump/master/libpcap/missing/snprintf.c,v 1.1 2004-04-05 22:43:51 guy Exp $";
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include <pcap-int.h>
+
+enum format_flags {
+    minus_flag     =  1,
+    plus_flag      =  2,
+    space_flag     =  4,
+    alternate_flag =  8,
+    zero_flag      = 16
+};
+
+/*
+ * Common state
+ */
+
+struct state {
+  unsigned char *str;
+  unsigned char *s;
+  unsigned char *theend;
+  size_t sz;
+  size_t max_sz;
+  int (*append_char)(struct state *, unsigned char);
+  int (*reserve)(struct state *, size_t);
+  /* XXX - methods */
+};
+
+#ifndef HAVE_VSNPRINTF
+static int
+sn_reserve (struct state *state, size_t n)
+{
+  return state->s + n > state->theend;
+}
+
+static int
+sn_append_char (struct state *state, unsigned char c)
+{
+  if (sn_reserve (state, 1)) {
+    return 1;
+  } else {
+    *state->s++ = c;
+    return 0;
+  }
+}
+#endif
+
+#if 0
+static int
+as_reserve (struct state *state, size_t n)
+{
+  if (state->s + n > state->theend) {
+    int off = state->s - state->str;
+    unsigned char *tmp;
+
+    if (state->max_sz && state->sz >= state->max_sz)
+      return 1;
+
+    state->sz = max(state->sz * 2, state->sz + n);
+    if (state->max_sz)
+      state->sz = min(state->sz, state->max_sz);
+    tmp = realloc (state->str, state->sz);
+    if (tmp == NULL)
+      return 1;
+    state->str = tmp;
+    state->s = state->str + off;
+    state->theend = state->str + state->sz - 1;
+  }
+  return 0;
+}
+
+static int
+as_append_char (struct state *state, unsigned char c)
+{
+  if(as_reserve (state, 1))
+    return 1;
+  else {
+    *state->s++ = c;
+    return 0;
+  }
+}
+#endif
+
+static int
+append_number(struct state *state,
+             unsigned long num, unsigned base, char *rep,
+             int width, int prec, int flags, int minusp)
+{
+  int len = 0;
+  int i;
+
+  /* given precision, ignore zero flag */
+  if(prec != -1)
+    flags &= ~zero_flag;
+  else
+    prec = 1;
+  /* zero value with zero precision -> "" */
+  if(prec == 0 && num == 0)
+    return 0;
+  do{
+    if((*state->append_char)(state, rep[num % base]))
+      return 1;
+    len++;
+    num /= base;
+  }while(num);
+  prec -= len;
+  /* pad with prec zeros */
+  while(prec-- > 0){
+    if((*state->append_char)(state, '0'))
+      return 1;
+    len++;
+  }
+  /* add length of alternate prefix (added later) to len */
+  if(flags & alternate_flag && (base == 16 || base == 8))
+    len += base / 8;
+  /* pad with zeros */
+  if(flags & zero_flag){
+    width -= len;
+    if(minusp || (flags & space_flag) || (flags & plus_flag))
+      width--;
+    while(width-- > 0){
+      if((*state->append_char)(state, '0'))
+       return 1;
+      len++;
+    }
+  }
+  /* add alternate prefix */
+  if(flags & alternate_flag && (base == 16 || base == 8)){
+    if(base == 16)
+      if((*state->append_char)(state, rep[10] + 23)) /* XXX */
+       return 1;
+    if((*state->append_char)(state, '0'))
+      return 1;
+  }
+  /* add sign */
+  if(minusp){
+    if((*state->append_char)(state, '-'))
+      return 1;
+    len++;
+  } else if(flags & plus_flag) {
+    if((*state->append_char)(state, '+'))
+      return 1;
+    len++;
+  } else if(flags & space_flag) {
+    if((*state->append_char)(state, ' '))
+      return 1;
+    len++;
+  }
+  if(flags & minus_flag)
+    /* swap before padding with spaces */
+    for(i = 0; i < len / 2; i++){
+      char c = state->s[-i-1];
+      state->s[-i-1] = state->s[-len+i];
+      state->s[-len+i] = c;
+    }
+  width -= len;
+  while(width-- > 0){
+    if((*state->append_char)(state,  ' '))
+      return 1;
+    len++;
+  }
+  if(!(flags & minus_flag))
+    /* swap after padding with spaces */
+    for(i = 0; i < len / 2; i++){
+      char c = state->s[-i-1];
+      state->s[-i-1] = state->s[-len+i];
+      state->s[-len+i] = c;
+    }
+
+  return 0;
+}
+
+static int
+append_string (struct state *state,
+              unsigned char *arg,
+              int width,
+              int prec,
+              int flags)
+{
+  if(prec != -1)
+    width -= prec;
+  else
+    width -= strlen((char *)arg);
+  if(!(flags & minus_flag))
+    while(width-- > 0)
+      if((*state->append_char) (state, ' '))
+       return 1;
+  if (prec != -1) {
+    while (*arg && prec--)
+      if ((*state->append_char) (state, *arg++))
+       return 1;
+  } else {
+    while (*arg)
+      if ((*state->append_char) (state, *arg++))
+       return 1;
+  }
+  if(flags & minus_flag)
+    while(width-- > 0)
+      if((*state->append_char) (state, ' '))
+       return 1;
+  return 0;
+}
+
+static int
+append_char(struct state *state,
+           unsigned char arg,
+           int width,
+           int flags)
+{
+  while(!(flags & minus_flag) && --width > 0)
+    if((*state->append_char) (state, ' '))
+      return 1;
+
+  if((*state->append_char) (state, arg))
+    return 1;
+  while((flags & minus_flag) && --width > 0)
+    if((*state->append_char) (state, ' '))
+      return 1;
+
+  return 0;
+}
+
+/*
+ * This can't be made into a function...
+ */
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_flag) \
+     res = (unsig long)va_arg(arg, unsig long); \
+else if (short_flag) \
+     res = (unsig short)va_arg(arg, unsig int); \
+else \
+     res = (unsig int)va_arg(arg, unsig int)
+
+/*
+ * zyxprintf - return 0 or -1
+ */
+
+static int
+xyzprintf (struct state *state, const char *char_format, va_list ap)
+{
+  const unsigned char *format = (const unsigned char *)char_format;
+  unsigned char c;
+
+  while((c = *format++)) {
+    if (c == '%') {
+      int flags      = 0;
+      int width      = 0;
+      int prec       = -1;
+      int long_flag  = 0;
+      int short_flag = 0;
+
+      /* flags */
+      while((c = *format++)){
+       if(c == '-')
+         flags |= minus_flag;
+       else if(c == '+')
+         flags |= plus_flag;
+       else if(c == ' ')
+         flags |= space_flag;
+       else if(c == '#')
+         flags |= alternate_flag;
+       else if(c == '0')
+         flags |= zero_flag;
+       else
+         break;
+      }
+
+      if((flags & space_flag) && (flags & plus_flag))
+       flags ^= space_flag;
+
+      if((flags & minus_flag) && (flags & zero_flag))
+       flags ^= zero_flag;
+
+      /* width */
+      if (isdigit(c))
+       do {
+         width = width * 10 + c - '0';
+         c = *format++;
+       } while(isdigit(c));
+      else if(c == '*') {
+       width = va_arg(ap, int);
+       c = *format++;
+      }
+
+      /* precision */
+      if (c == '.') {
+       prec = 0;
+       c = *format++;
+       if (isdigit(c))
+         do {
+           prec = prec * 10 + c - '0';
+           c = *format++;
+         } while(isdigit(c));
+       else if (c == '*') {
+         prec = va_arg(ap, int);
+         c = *format++;
+       }
+      }
+
+      /* size */
+
+      if (c == 'h') {
+       short_flag = 1;
+       c = *format++;
+      } else if (c == 'l') {
+       long_flag = 1;
+       c = *format++;
+      }
+
+      switch (c) {
+      case 'c' :
+       if(append_char(state, va_arg(ap, int), width, flags))
+         return -1;
+       break;
+      case 's' :
+       if (append_string(state,
+                         va_arg(ap, unsigned char*),
+                         width,
+                         prec,
+                         flags))
+         return -1;
+       break;
+      case 'd' :
+      case 'i' : {
+       long arg;
+       unsigned long num;
+       int minusp = 0;
+
+       PARSE_INT_FORMAT(arg, ap, signed);
+
+       if (arg < 0) {
+         minusp = 1;
+         num = -arg;
+       } else
+         num = arg;
+
+       if (append_number (state, num, 10, "0123456789",
+                          width, prec, flags, minusp))
+         return -1;
+       break;
+      }
+      case 'u' : {
+       unsigned long arg;
+
+       PARSE_INT_FORMAT(arg, ap, unsigned);
+
+       if (append_number (state, arg, 10, "0123456789",
+                          width, prec, flags, 0))
+         return -1;
+       break;
+      }
+      case 'o' : {
+       unsigned long arg;
+
+       PARSE_INT_FORMAT(arg, ap, unsigned);
+
+       if (append_number (state, arg, 010, "01234567",
+                          width, prec, flags, 0))
+         return -1;
+       break;
+      }
+      case 'x' : {
+       unsigned long arg;
+
+       PARSE_INT_FORMAT(arg, ap, unsigned);
+
+       if (append_number (state, arg, 0x10, "0123456789abcdef",
+                          width, prec, flags, 0))
+         return -1;
+       break;
+      }
+      case 'X' :{
+       unsigned long arg;
+
+       PARSE_INT_FORMAT(arg, ap, unsigned);
+
+       if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+                          width, prec, flags, 0))
+         return -1;
+       break;
+      }
+      case 'p' : {
+       unsigned long arg = (unsigned long)va_arg(ap, void*);
+
+       if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+                          width, prec, flags, 0))
+         return -1;
+       break;
+      }
+      case 'n' : {
+       int *arg = va_arg(ap, int*);
+       *arg = state->s - state->str;
+       break;
+      }
+      case '\0' :
+         --format;
+         /* FALLTHROUGH */
+      case '%' :
+       if ((*state->append_char)(state, c))
+         return -1;
+       break;
+      default :
+       if (   (*state->append_char)(state, '%')
+           || (*state->append_char)(state, c))
+         return -1;
+       break;
+      }
+    } else
+      if ((*state->append_char) (state, c))
+       return -1;
+  }
+  return 0;
+}
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf (char *str, size_t sz, const char *format, ...)
+{
+  va_list args;
+  int ret;
+
+  va_start(args, format);
+  ret = vsnprintf (str, sz, format, args);
+
+#ifdef PARANOIA
+  {
+    int ret2;
+    char *tmp;
+
+    tmp = malloc (sz);
+    if (tmp == NULL)
+      abort ();
+
+    ret2 = vsprintf (tmp, format, args);
+    if (ret != ret2 || strcmp(str, tmp))
+      abort ();
+    free (tmp);
+  }
+#endif
+
+  va_end(args);
+  return ret;
+}
+#endif
+
+#if 0
+#ifndef HAVE_ASPRINTF
+int
+asprintf (char **ret, const char *format, ...)
+{
+  va_list args;
+  int val;
+
+  va_start(args, format);
+  val = vasprintf (ret, format, args);
+
+#ifdef PARANOIA
+  {
+    int ret2;
+    char *tmp;
+    tmp = malloc (val + 1);
+    if (tmp == NULL)
+      abort ();
+
+    ret2 = vsprintf (tmp, format, args);
+    if (val != ret2 || strcmp(*ret, tmp))
+      abort ();
+    free (tmp);
+  }
+#endif
+
+  va_end(args);
+  return val;
+}
+#endif
+
+#ifndef HAVE_ASNPRINTF
+int
+asnprintf (char **ret, size_t max_sz, const char *format, ...)
+{
+  va_list args;
+  int val;
+
+  va_start(args, format);
+  val = vasnprintf (ret, max_sz, format, args);
+
+#ifdef PARANOIA
+  {
+    int ret2;
+    char *tmp;
+    tmp = malloc (val + 1);
+    if (tmp == NULL)
+      abort ();
+
+    ret2 = vsprintf (tmp, format, args);
+    if (val != ret2 || strcmp(*ret, tmp))
+      abort ();
+    free (tmp);
+  }
+#endif
+
+  va_end(args);
+  return val;
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int
+vasprintf (char **ret, const char *format, va_list args)
+{
+  return vasnprintf (ret, 0, format, args);
+}
+#endif
+
+
+#ifndef HAVE_VASNPRINTF
+int
+vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+{
+  int st;
+  size_t len;
+  struct state state;
+
+  state.max_sz = max_sz;
+  state.sz     = 1;
+  state.str    = malloc(state.sz);
+  if (state.str == NULL) {
+    *ret = NULL;
+    return -1;
+  }
+  state.s = state.str;
+  state.theend = state.s + state.sz - 1;
+  state.append_char = as_append_char;
+  state.reserve     = as_reserve;
+
+  st = xyzprintf (&state, format, args);
+  if (st) {
+    free (state.str);
+    *ret = NULL;
+    return -1;
+  } else {
+    char *tmp;
+
+    *state.s = '\0';
+    len = state.s - state.str;
+    tmp = realloc (state.str, len+1);
+    if (tmp == NULL) {
+      free (state.str);
+      *ret = NULL;
+      return -1;
+    }
+    *ret = tmp;
+    return len;
+  }
+}
+#endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf (char *str, size_t sz, const char *format, va_list args)
+{
+  struct state state;
+  int ret;
+  unsigned char *ustr = (unsigned char *)str;
+
+  state.max_sz = 0;
+  state.sz     = sz;
+  state.str    = ustr;
+  state.s      = ustr;
+  state.theend = ustr + sz - 1;
+  state.append_char = sn_append_char;
+  state.reserve     = sn_reserve;
+
+  ret = xyzprintf (&state, format, args);
+  *state.s = '\0';
+  if (ret)
+    return sz;
+  else
+    return state.s - state.str;
+}
+#endif
+
diff --git a/mkdep b/mkdep
new file mode 100755 (executable)
index 0000000..b41a00e
--- /dev/null
+++ b/mkdep
@@ -0,0 +1,109 @@
+#!/bin/sh -
+#
+# Copyright (c) 1994, 1996
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted
+# provided that this notice is preserved and that due credit is given
+# to the University of California at Berkeley. The name of the University
+# may not be used to endorse or promote products derived from this
+# software without specific prior written permission. This software
+# is provided ``as is'' without express or implied warranty.
+#
+#      @(#)mkdep.sh    5.11 (Berkeley) 5/5/88
+#
+
+PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin:/usr/sfw/bin
+export PATH
+
+MAKE=Makefile                  # default makefile name is "Makefile"
+CC=cc                          # default C compiler is "cc"
+
+while :
+       do case "$1" in
+               # -c allows you to specify the C compiler
+               -c)
+                       CC=$2
+                       shift; shift ;;
+
+               # -f allows you to select a makefile name
+               -f)
+                       MAKE=$2
+                       shift; shift ;;
+
+               # the -p flag produces "program: program.c" style dependencies
+               # so .o's don't get produced
+               -p)
+                       SED='s;\.o;;'
+                       shift ;;
+               *)
+                       break ;;
+       esac
+done
+
+if [ $# = 0 ] ; then
+       echo 'usage: mkdep [-p] [-c cc] [-f makefile] [flags] file ...'
+       exit 1
+fi
+
+if [ ! -w $MAKE ]; then
+       echo "mkdep: no writeable file \"$MAKE\""
+       exit 1
+fi
+
+TMP=/tmp/mkdep$$
+
+trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
+
+cp $MAKE ${MAKE}.bak
+
+sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
+
+cat << _EOF_ >> $TMP
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+_EOF_
+
+# If your compiler doesn't have -M, add it.  If you can't, the next two
+# lines will try and replace the "cc -M".  The real problem is that this
+# hack can't deal with anything that requires a search path, and doesn't
+# even try for anything using bracket (<>) syntax.
+#
+# egrep '^#include[    ]*".*"' /dev/null $* |
+# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
+
+# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
+$CC -M $* |
+sed "
+       s; \./; ;g
+       $SED" |
+awk '{
+       if ($1 != prev) {
+               if (rec != "")
+                       print rec;
+               rec = $0;
+               prev = $1;
+       }
+       else {
+               if (length(rec $2) > 78) {
+                       print rec;
+                       rec = $0;
+               }
+               else
+                       rec = rec " " $2
+       }
+}
+END {
+       print rec
+}' >> $TMP
+
+cat << _EOF_ >> $TMP
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+_EOF_
+
+# copy to preserve permissions
+cp $TMP $MAKE
+rm -f ${MAKE}.bak $TMP
+exit 0
diff --git a/msdos/bin2c.c b/msdos/bin2c.c
new file mode 100644 (file)
index 0000000..d82056e
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+\r
+static void Abort (char *fmt,...)\r
+{\r
+  va_list args;\r
+  va_start (args, fmt);\r
+  vfprintf (stderr, fmt, args);\r
+  va_end (args);\r
+  exit (1);\r
+}\r
+\r
+int main (int argc, char **argv)\r
+{\r
+  FILE  *inFile;\r
+  FILE  *outFile = stdout;\r
+  time_t now     = time (NULL);\r
+  int    ch, i;\r
+\r
+  if (argc != 2)\r
+     Abort ("Usage: %s bin-file [> result]", argv[0]);\r
+\r
+  if ((inFile = fopen(argv[1],"rb")) == NULL)\r
+     Abort ("Cannot open %s\n", argv[1]);\r
+\r
+  fprintf (outFile,\r
+           "/* data statements for file %s at %.24s */\n"\r
+           "/* Generated by BIN2C, G.Vanem 1995 */\n",\r
+           argv[1], ctime(&now));\r
+\r
+  i = 0;\r
+  while ((ch = fgetc(inFile)) != EOF)\r
+  {\r
+    if (i++ % 12 == 0)\r
+       fputs ("\n  ", outFile);\r
+    fprintf (outFile, "0x%02X,", ch);\r
+  }\r
+  fputc ('\n', outFile);\r
+  fclose (inFile);\r
+  return (0);\r
+}\r
diff --git a/msdos/common.dj b/msdos/common.dj
new file mode 100644 (file)
index 0000000..3f64d14
--- /dev/null
@@ -0,0 +1,80 @@
+#
+# Common defines for libpcap and 16/32-bit network drivers (djgpp)
+#
+# @(#) $Header: /tcpdump/master/libpcap/msdos/common.dj,v 1.2 2004-12-19 19:36:33 guy Exp $ (LBL)
+
+.SUFFIXES: .exe .wlm .dxe .l .y
+.PHONY:    check_gcclib
+
+default: check_gcclib all
+
+GCCLIB   = /djgpp/lib/gcc-lib/djgpp/3.31
+MAKEFILE = Makefile.dj
+
+#
+# DLX 2.91+ lib. Change path to suite.
+# Not used anymore. Uses DXE3 now.
+#
+# DLX_LIB  = $(DJDIR)/contrib/dlx.291/libdlx.a
+# DLX_LINK = $(DJDIR)/bin/dlxgen.exe
+
+WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
+
+
+ifeq ($(wildcard $(GCCLIB)/libgcc.a),)
+check_gcclib:
+       @echo libgcc.a not found. Set \"$(GCCLIB)\" to \"/djgpp/lib/gcc-lib/djgpp/3.X\"
+endif
+
+
+#
+# Include 32-bit driver support
+#
+USE_32BIT_DRIVERS = 0
+
+#
+# Use loadable driver modules instead of statically linking
+# all drivers.
+#
+USE_32BIT_MODULES = 0
+
+#
+# Put interrupt sensitive code/data in locked sections
+# Do `make clean' in all affected directories after changing this.
+#
+USE_SECTION_LOCKING = 0
+
+#
+# Set to 1 to use exception handler lib (only for me)
+#
+USE_EXCEPT = 0
+
+CC   = gcc.exe
+LD   = ld.exe
+ASM  = nasm.exe -fbin -dDEBUG
+YACC = bison.exe
+LEX  = flex.exe
+
+CFLAGS = -g -gcoff -O2 -Wall -I. -I$(WATT32_ROOT)/inc
+
+ifeq ($(USE_EXCEPT),1)
+  CFLAGS += -DUSE_EXCEPT
+  EXC_LIB = d:/prog/mw/except/lib/libexc.a
+endif
+
+ifeq ($(USE_SECTION_LOCKING),1)
+  CFLAGS += -DUSE_SECTION_LOCKING
+endif
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+  CFLAGS += -DUSE_32BIT_DRIVERS
+endif
+
+%.o: %.c
+       $(CC) -c $(CFLAGS) $<
+       @echo
+
+%.o: %.s
+       $(CC) -c $(CFLAGS) -x assembler-with-cpp -o $@ $<
+       @echo
+
diff --git a/msdos/makefile b/msdos/makefile
new file mode 100644 (file)
index 0000000..cdb4e7c
--- /dev/null
@@ -0,0 +1,184 @@
+#\r
+#  Makefile for dos-libpcap. NB. This makefile requires a Borland\r
+#  compatible make tool.\r
+#\r
+#  Targets:\r
+#    Borland C 4.0+      (DOS large model)\r
+#    Metaware HighC 3.3+ (PharLap 386|DosX)\r
+#\r
+\r
+.AUTODEPEND\r
+.SWAP\r
+\r
+!if "$(WATT_ROOT)" == ""\r
+!error Environment variable "WATT_ROOT" not set.\r
+!endif\r
+\r
+WATT_INC = $(WATT_ROOT)\inc\r
+\r
+DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \\r
+         -DHAVE_STRERROR -DHAVE_LIMITS_H\r
+\r
+ASM    = tasm.exe -t -l -mx -m2 -DDEBUG\r
+\r
+SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \\r
+         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \\r
+         savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \\r
+         missing\snprintf.c\r
+\r
+BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj\r
+\r
+HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32\r
+\r
+all:\r
+            @echo Usage: make pcap_bc.lib or pcap_hc.lib\r
+\r
+\r
+pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc\r
+\r
+\r
+pcap_hc.lib: hc386.arg $(HIGHC_OBJ)\r
+            386lib $< @&&|\r
+               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)\r
+|\r
+\r
+pcap_bc:    $(BORLAND_OBJ)\r
+            @tlib pcap_bc.lib /C @&&|\r
+               -+$(**:.obj=-+)\r
+|\r
+\r
+.c.obj:\r
+            bcc.exe @bcc.arg -o$*.obj $*.c\r
+\r
+.c.o32:\r
+            hc386.exe @hc386.arg -o $*.o32 $*.c\r
+\r
+.asm.obj:\r
+            $(ASM) $*.asm, $*.obj\r
+\r
+.asm.o32:\r
+            $(ASM) -DDOSX=1 $*.asm, $*.o32\r
+\r
+scanner.c: scanner.l\r
+            flex -Ppcap_ -7 -oscanner.c scanner.l\r
+\r
+grammar.c tokdefs.h: grammar.y\r
+            bison --name-prefix=pcap_ --yacc --defines grammar.y\r
+            - @del grammar.c\r
+            - @del tokdefs.h\r
+            ren y_tab.c grammar.c\r
+            ren y_tab.h tokdefs.h\r
+\r
+bcc.arg:    msdos\Makefile\r
+            @copy &&|\r
+              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-\r
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym\r
+| $<\r
+\r
+hc386.arg:  msdos\Makefile\r
+            @copy &&|\r
+            # -DUSE_32BIT_DRIVERS\r
+              $(DEFS) -DDOSX=1 -w3 -c -g -O5\r
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr\r
+              -Hsuffix=.o32\r
+              -Hnocopyr\r
+              -Hpragma=Offwarn(491,553,572)\r
+              -Hon=Recognize_library  # make memcpy/strlen etc. inline\r
+              -Hoff=Behaved           # turn off some optimiser warnings\r
+| $<\r
+\r
+clean:\r
+            @del *.obj\r
+            @del *.o32\r
+            @del *.lst\r
+            @del *.map\r
+            @del bcc.arg\r
+            @del hc386.arg\r
+            @del grammar.c\r
+            @del tokdefs.h\r
+            @del scanner.c\r
+            @echo Cleaned\r
+\r
+#\r
+# dependencies\r
+#             \r
+pkt_rx0.obj:  msdos\pkt_rx0.asm\r
+\r
+bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
+\r
+bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h\r
+\r
+etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h\r
+\r
+optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
+\r
+savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
+\r
+inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pf.h pcap-namedb.h\r
+\r
+scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pcap-namedb.h tokdefs.h\r
+\r
+gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \\r
+  arcnet.h pf.h pcap-namedb.h\r
+\r
+nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pcap-namedb.h ethertype.h\r
+\r
+pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \\r
+  msdos\pktdrvr.h\r
+\r
+pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \\r
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
+\r
+ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
+  msdos\ndis2.h\r
+\r
+pkt_rx0.o32:  msdos\pkt_rx0.asm\r
+\r
+bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
+\r
+bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h\r
+\r
+etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h\r
+\r
+optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
+\r
+savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
+\r
+inet.o32: inet.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pf.h pcap-namedb.h\r
+\r
+scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pcap-namedb.h tokdefs.h\r
+\r
+gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \\r
+  arcnet.h pf.h pcap-namedb.h\r
+\r
+nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
+  pcap-namedb.h ethertype.h\r
+\r
+pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \\r
+  msdos\pktdrvr.h\r
+\r
+pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \\r
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
+\r
+ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
+  msdos\ndis2.h\r
+\r
diff --git a/msdos/makefile.dj b/msdos/makefile.dj
new file mode 100644 (file)
index 0000000..7ce58b4
--- /dev/null
@@ -0,0 +1,152 @@
+#
+# GNU Makefile for DOS-libpcap. djgpp version.
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+#  c:\net\pcap> make -f msdos/makefile.dj
+#
+# @(#) $Header: /tcpdump/master/libpcap/msdos/makefile.dj,v 1.2 2004-12-19 19:41:06 guy Exp $ (LBL)
+
+VPATH = missing msdos
+
+PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc
+
+include msdos/common.dj
+
+DRIVER_DIR = ./msdos/pm_drvr
+
+CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR \
+          -D_U_='__attribute__((unused))' -DHAVE_VERSION_H
+
+# CFLAGS += -Dyylval=pcap_lval -DBDEBUG -DNDEBUG
+
+SOURCES = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c   \
+          etherent.c gencode.c nametoad.c pcap-dos.c optimize.c  \
+          savefile.c pcap.c inet.c msdos\pktdrvr.c msdos/ndis2.c \
+          missing/snprintf.c
+
+OBJECTS = $(notdir $(SOURCES:.c=.o))
+TEMPBIN = tmp.bin
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+  PM_OBJECTS = $(addprefix $(DRIVER_DIR)/, \
+                 printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \
+                 lock.o kmalloc.o quirks.o timer.o net_init.o)
+  #
+  # Static link of drivers
+  #
+  ifeq ($(USE_32BIT_MODULES),0)
+    PM_OBJECTS += $(addprefix $(DRIVER_DIR)/, \
+                    accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \
+                    3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o)
+  endif
+endif
+
+all: libpcap.a
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+$(PM_OBJECTS):
+       $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) $(notdir $@)
+endif
+
+libpcap.a: version.h $(OBJECTS) $(PM_OBJECTS)
+       rm -f $@
+       ar rs $@ $^
+
+msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
+       $(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S
+       ./msdos/bin2c $(TEMPBIN) > $@
+       rm -f $(TEMPBIN)
+
+grammar.c tokdefs.h: grammar.y
+       rm -f grammar.c tokdefs.h
+       $(YACC) --name-prefix=pcap_ --yacc --defines grammar.y
+       mv -f y_tab.c grammar.c
+       mv -f y_tab.h tokdefs.h
+
+version.h: ./VERSION
+       @echo '/* Generated from VERSION. Do not edit */' > $@
+       sed -e 's/.*/static char pcap_version_string[] = "libpcap (&)";/' ./VERSION >> $@
+
+scanner.c: scanner.l
+       $(LEX) -Ppcap_ -7 -t $^ > $@
+       @echo
+
+msdos/bin2c.exe: msdos/bin2c.c
+       $(CC) $*.c -o $*.exe
+
+clean:
+       $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
+       $(MAKE) -f Makefile.dj -C libcpcap clean
+       rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak $(PREREQUISITES)
+
+vclean: clean
+       rm -f libpcap.a msdos/bin2c.exe
+
+#
+# Generated dependencies; Due to some hacks in gcc 2.95 and djgpp 2.03
+# we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing
+# included in dependency output (or else this makefile cannot be used on
+# another machine). We therefore use a special 'specs' file during
+# pre-processing.
+#
+MM_SPECS = specs.tmp
+MAKEFILE = msdos/Makefile.dj
+
+depend: $(PREREQUISITES)
+       @echo Generating dependencies..
+       @cp $(MAKEFILE) Makefile.bak
+       @echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS)
+       sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE)
+       echo "# DO NOT DELETE THIS LINE"                        >> $(MAKEFILE)
+       $(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES)       >> $(MAKEFILE)
+       rm -f $(MM_SPECS)
+
+#
+# Manually generated dependencies
+#             
+msdos/pktdrvr.c: msdos/pkt_stub.inc
+scanner.c: scanner.l
+grammar.c tokdefs.h: grammar.y
+grammar.h: grammar.y
+scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h gnuc.h
+grammar.y: pcap-int.h gencode.h pcap-namedb.h gnuc.h
+
+#
+# Automatically generated dependencies
+#
+# DO NOT DELETE THIS LINE
+grammar.o: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h pf.h \
+  pcap-namedb.h
+scanner.o: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h pcap-namedb.h \
+  tokdefs.h
+bpf_filt.o: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+bpf_imag.o: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+bpf_dump.o: bpf_dump.c pcap.h pcap-bpf.h
+etherent.o: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+gencode.o: gencode.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h \
+  ppp.h sll.h arcnet.h pf.h pcap-namedb.h
+nametoad.o: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+pcap-dos.o: pcap-dos.c msdos/pm_drvr/pmdrvr.h msdos/pm_drvr/iface.h \
+  msdos/pm_drvr/lock.h msdos/pm_drvr/ioport.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos/pm_drvr/kmalloc.h msdos/pm_drvr/bitops.h \
+  msdos/pm_drvr/timer.h msdos/pm_drvr/dma.h msdos/pm_drvr/irq.h \
+  msdos/pm_drvr/printk.h msdos/pm_drvr/pci.h msdos/pm_drvr/bios32.h \
+  msdos/pm_drvr/module.h msdos/pm_drvr/3c501.h msdos/pm_drvr/3c503.h \
+  msdos/pm_drvr/3c509.h msdos/pm_drvr/3c59x.h msdos/pm_drvr/3c515.h \
+  msdos/pm_drvr/3c90x.h msdos/pm_drvr/3c575_cb.h msdos/pm_drvr/ne.h \
+  msdos/pm_drvr/wd.h msdos/pm_drvr/accton.h msdos/pm_drvr/cs89x0.h \
+  msdos/pm_drvr/rtl8139.h msdos/pm_drvr/ne2k-pci.h msdos/pktdrvr.h
+optimize.o: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+savefile.o: savefile.c pcap-int.h pcap.h pcap-bpf.h
+pcap.o: pcap.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h
+inet.o: inet.c pcap-int.h pcap.h pcap-bpf.h
+pktdrvr.o: msdos/pktdrvr.c gnuc.h pcap-dos.h msdos/pm_drvr/lock.h \
+  pcap-int.h pcap.h pcap-bpf.h msdos/pktdrvr.h msdos/pkt_stub.inc
+ndis2.o: msdos/ndis2.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
+  pcap-bpf.h msdos/ndis2.h
+snprintf.o: missing/snprintf.c pcap-int.h pcap.h pcap-bpf.h
diff --git a/msdos/makefile.wc b/msdos/makefile.wc
new file mode 100644 (file)
index 0000000..e0d5672
--- /dev/null
@@ -0,0 +1,131 @@
+#\r
+#  Watcom Makefile for dos-libpcap.\r
+#\r
+# Specify MODEL = `3r' or `3s'\r
+# Specify TARGET = `pharlap' or `dos4g'\r
+#\r
+# Use this makefile from the libpcap root directory.\r
+# E.g. like this:\r
+#\r
+#  c:\net\pcap> wmake -f msdos\makefile.wc\r
+#\r
+\r
+MODEL  = 3s\r
+TARGET = dos4g\r
+\r
+OBJDIR = msdos\$(TARGET).w$(MODEL)\r
+LIB    = $(OBJDIR)\pcap.lib\r
+\r
+.EXTENSIONS: .l .y\r
+\r
+DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &\r
+       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF\r
+\r
+CC  = wcc386.exe\r
+ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s\r
+\r
+OBJS = $(OBJDIR)\grammar.obj  $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &\r
+       $(OBJDIR)\bpf_filt.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &\r
+       $(OBJDIR)\etherent.obj $(OBJDIR)\gencode.obj  $(OBJDIR)\nametoad.obj &\r
+       $(OBJDIR)\pcap-dos.obj $(OBJDIR)\pktdrvr.obj  $(OBJDIR)\optimize.obj &\r
+       $(OBJDIR)\savefile.obj $(OBJDIR)\inet.obj     $(OBJDIR)\ndis2.obj\r
+\r
+CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &\r
+         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &\r
+         -oilrtf -zm\r
+\r
+TEMPBIN = tmp.bin\r
+\r
+all: $(OBJDIR) $(OBJDIR)\pcap.lib\r
+\r
+$(OBJDIR):\r
+          - mkdir $(OBJDIR)\r
+\r
+$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg\r
+          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg\r
+\r
+wlib.arg: msdos\makefile.wc\r
+          %create $^@\r
+          for %f in ($(OBJS)) do %append $^@ +- %f\r
+\r
+$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c gnuc.h &\r
+  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h\r
+          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@\r
+\r
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c\r
+          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@\r
+\r
+.ERASE\r
+.c{$(OBJDIR)}.obj:\r
+          *$(CC) $(CFLAGS) $[@ -fo=$@\r
+\r
+grammar.c tokdefs.h: grammar.y \r
+          bison --name-prefix=pcap_ --yacc --defines $[@\r
+          - @del grammar.c\r
+          - @del tokdefs.h\r
+          ren y_tab.c grammar.c\r
+          ren y_tab.h tokdefs.h\r
+\r
+scanner.c: scanner.l\r
+          flex -Ppcap_ -7 -o$@ $[@\r
+\r
+msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S\r
+          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S\r
+          bin2c.exe  $(TEMPBIN) > $@\r
+          @del $(TEMPBIN)\r
+\r
+bin2c.exe: msdos\bin2c.c\r
+          wcl $[@\r
+\r
+clean realclean vclean: .SYMBOLIC\r
+          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &\r
+            @del %f\*.obj\r
+          @del grammar.c\r
+          @del tokdefs.h\r
+          @del scanner.c\r
+          @del bin2c.exe\r
+          @del bin2c.obj\r
+          @del msdos\pkt_stub.inc\r
+          @echo Cleaned\r
+\r
+#\r
+# dependencies\r
+#                     \r
+$(OBJDIR)\bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
+\r
+$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h\r
+\r
+$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-nam.h\r
+\r
+$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
+\r
+$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
+\r
+$(OBJDIR)\inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h\r
+\r
+$(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
+  pf.h pcap-nam.h\r
+\r
+$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
+  pcap-nam.h tokdefs.h\r
+\r
+$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &\r
+  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &\r
+  arcnet.h pf.h pcap-nam.h\r
+\r
+$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
+  pcap-nam.h ethertyp.h\r
+\r
+$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &\r
+  msdos\pktdrvr.h\r
+\r
+$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h &\r
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
+\r
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &\r
+  msdos\ndis2.h\r
+\r
diff --git a/msdos/ndis2.c b/msdos/ndis2.c
new file mode 100644 (file)
index 0000000..0a5ea2a
--- /dev/null
@@ -0,0 +1,860 @@
+/* \r
+ * Copyright (c) 1993,1994\r
+ *      Texas A&M University.  All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ * 3. All advertising materials mentioning features or use of this software\r
+ *    must display the following acknowledgement:\r
+ *      This product includes software developed by Texas A&M University\r
+ *      and its contributors.\r
+ * 4. Neither the name of the University nor the names of its contributors\r
+ *    may be used to endorse or promote products derived from this software\r
+ *    without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ * SUCH DAMAGE.\r
+ *\r
+ * Developers:\r
+ *             David K. Hess, Douglas Lee Schales, David R. Safford\r
+ *\r
+ * Heavily modified for Metaware HighC + GNU C 2.8+\r
+ *             Gisle Vanem 1998\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <dos.h>\r
+#include <io.h>\r
+#include <fcntl.h>\r
+#include <malloc.h>\r
+#include <string.h>\r
+\r
+#include "pcap-dos.h"\r
+#include "pcap-int.h"\r
+#include "msdos/ndis2.h"\r
+\r
+#if defined(USE_NDIS2)\r
+\r
+/*\r
+ *  Packet buffer handling\r
+ */\r
+extern int     FreePktBuf  (PktBuf *buf);\r
+extern int     EnquePktBuf (PktBuf *buf);\r
+extern PktBuf* AllocPktBuf (void);\r
+\r
+/*\r
+ *  Various defines\r
+ */\r
+#define MAX_NUM_DEBUG_STRINGS 90\r
+#define DEBUG_STRING_LENGTH   80\r
+#define STACK_POOL_SIZE       6\r
+#define STACK_SIZE            256\r
+\r
+#define MEDIA_FDDI            1\r
+#define MEDIA_ETHERNET        2\r
+#define MEDIA_TOKEN           3\r
+\r
+static int     startDebug     = 0;\r
+static int     stopDebug      = 0;\r
+\r
+static DWORD   droppedPackets = 0L;\r
+static WORD    frameSize      = 0;\r
+static WORD    headerSize     = 0;\r
+static int     mediaType      = 0;\r
+static char   *lastErr        = NULL;\r
+\r
+static BYTE    debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH];\r
+static BYTE   *freeStacks   [STACK_POOL_SIZE];\r
+static int     freeStackPtr = STACK_POOL_SIZE - 1;\r
+\r
+static ProtMan protManEntry = NULL;\r
+static WORD    protManDS    = 0;\r
+static volatile int xmitPending;\r
+\r
+static struct _PktBuf        *txBufPending;\r
+static struct _CardHandle    *handle;\r
+static struct _CommonChars    common;\r
+static struct _ProtocolChars  protChars;\r
+static struct _ProtDispatch   lowerTable;\r
+\r
+static struct _FailingModules failingModules;\r
+static struct _BindingsList   bindings;\r
+\r
+static struct {\r
+         WORD  err_num;\r
+         char *err_text;\r
+       } ndis_errlist[] = {\r
+\r
+  { ERR_SUCCESS,\r
+    "The function completed successfully.\n"  },\r
+\r
+  { ERR_WAIT_FOR_RELEASE,\r
+    "The ReceiveChain completed successfully but the protocol has\n"\r
+    "retained control of the buffer.\n"  },\r
+\r
+  { ERR_REQUEST_QUEUED,\r
+    "The current request has been queued.\n"  },\r
+\r
+  { ERR_FRAME_NOT_RECOGNIZED,\r
+    "Frame not recognized.\n"  },\r
+\r
+  { ERR_FRAME_REJECTED,\r
+    "Frame was discarded.\n"  },\r
+\r
+  { ERR_FORWARD_FRAME,\r
+    "Protocol wishes to forward frame to another protocol.\n"  },\r
+\r
+  { ERR_OUT_OF_RESOURCE,\r
+    "Out of resource.\n"  },\r
+\r
+  { ERR_INVALID_PARAMETER,\r
+    "Invalid parameter.\n"  },\r
+\r
+  { ERR_INVALID_FUNCTION,\r
+    "Invalid function.\n"  },\r
+\r
+  { ERR_NOT_SUPPORTED,\r
+    "Not supported.\n"  },\r
+\r
+  { ERR_HARDWARE_ERROR,\r
+    "Hardware error.\n"  },\r
+\r
+  { ERR_TRANSMIT_ERROR,\r
+    "The packet was not transmitted due to an error.\n"  },\r
+\r
+  { ERR_NO_SUCH_DESTINATION,\r
+    "Token ring packet was not recognized when transmitted.\n"  },\r
+\r
+  { ERR_BUFFER_TOO_SMALL,\r
+    "Provided buffer was too small.\n"  },\r
+\r
+  { ERR_ALREADY_STARTED,\r
+    "Network drivers already started.\n"  },\r
+\r
+  { ERR_INCOMPLETE_BINDING,\r
+    "Protocol driver could not complete its bindings.\n"  },\r
+\r
+  { ERR_DRIVER_NOT_INITIALIZED,\r
+    "MAC did not initialize properly.\n"  },\r
+\r
+  { ERR_HARDWARE_NOT_FOUND,\r
+    "Hardware not found.\n"  },\r
+\r
+  { ERR_HARDWARE_FAILURE,\r
+    "Hardware failure.\n"  },\r
+\r
+  { ERR_CONFIGURATION_FAILURE,\r
+    "Configuration failure.\n"  },\r
+\r
+  { ERR_INTERRUPT_CONFLICT,\r
+    "Interrupt conflict.\n"  },\r
+\r
+  { ERR_INCOMPATIBLE_MAC,\r
+    "The MAC is not compatible with the protocol.\n"  },\r
+\r
+  { ERR_INITIALIZATION_FAILED,\r
+    "Initialization failed.\n"  },\r
+\r
+  { ERR_NO_BINDING,\r
+    "Binding did not occur.\n"  },\r
+\r
+  { ERR_NETWORK_MAY_NOT_BE_CONNECTED,\r
+    "The network may not be connected to the adapter.\n"  },\r
+\r
+  { ERR_INCOMPATIBLE_OS_VERSION,\r
+    "The version of the operating system is incompatible with the protocol.\n"  },\r
+\r
+  { ERR_ALREADY_REGISTERED,\r
+    "The protocol is already registered.\n"  },\r
+\r
+  { ERR_PATH_NOT_FOUND,\r
+    "PROTMAN.EXE could not be found.\n"  },\r
+\r
+  { ERR_INSUFFICIENT_MEMORY,\r
+    "Insufficient memory.\n"  },\r
+\r
+  { ERR_INFO_NOT_FOUND,\r
+    "Protocol Mananger info structure is lost or corrupted.\n"  },\r
+\r
+  { ERR_GENERAL_FAILURE,\r
+    "General failure.\n"  }\r
+};\r
+\r
+/*\r
+ *  Some handy macros\r
+ */       \r
+#define PERROR(str)    printf("%s (%d): %s\n", __FILE__,__LINE__,str)\r
+#define DEBUG_RING()   (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \\r
+                        stopDebug = 0 : ++stopDebug])\r
+\r
+/*\r
+ * needs rewrite for DOSX\r
+ */\r
+#define MAC_DISPATCH(hnd)  ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable)\r
+#define MAC_STATUS(hnd)    ((struct _MacStatusTable*)  (hnd)->common->serviceStatus)\r
+#define MAC_CHAR(hnd)      ((struct _MacChars*)        (hnd)->common->serviceChars)\r
+\r
+#ifdef NDIS_DEBUG\r
+  #define DEBUG0(str)      printf (str)\r
+  #define DEBUG1(fmt,a)    printf (fmt,a)\r
+  #define DEBUG2(fmt,a,b)  printf (fmt,a,b)\r
+  #define TRACE0(str)      sprintf (DEBUG_RING(),str)\r
+  #define TRACE1(fmt,a)    sprintf (DEBUG_RING(),fmt,a)\r
+#else\r
+  #define DEBUG0(str)      ((void)0)\r
+  #define DEBUG1(fmt,a)    ((void)0)\r
+  #define DEBUG2(fmt,a,b)  ((void)0)\r
+  #define TRACE0(str)      ((void)0)\r
+  #define TRACE1(fmt,a)    ((void)0)\r
+#endif\r
+\r
+/*\r
+ * This routine is called from both threads\r
+ */\r
+void NdisFreeStack (BYTE *aStack)\r
+{\r
+  GUARD();\r
+\r
+  if (freeStackPtr == STACK_POOL_SIZE - 1)\r
+     PERROR ("tried to free too many stacks");\r
+\r
+  freeStacks[++freeStackPtr] = aStack;\r
+\r
+  if (freeStackPtr == 0)\r
+     TRACE0 ("freeStackPtr went positive\n");\r
+\r
+  UNGUARD();\r
+}\r
+\r
+/*\r
+ * This routine is called from callbacks to allocate local data\r
+ */\r
+BYTE *NdisAllocStack (void)\r
+{\r
+  BYTE *stack;\r
+\r
+  GUARD();\r
+\r
+  if (freeStackPtr < 0)\r
+  {\r
+    /* Ran out of stack buffers. Return NULL which will start\r
+     * dropping packets\r
+     */\r
+    TRACE0 ("freeStackPtr went negative\n");\r
+    stack = 0;\r
+  }\r
+  else\r
+    stack = freeStacks[freeStackPtr--];\r
+\r
+  UNGUARD();\r
+  return (stack);\r
+}\r
+\r
+CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3,\r
+                             WORD opcode, WORD targetDS))\r
+{\r
+  static int            bindEntry = 0;\r
+  struct _CommonChars  *macCommon;\r
+  volatile WORD result;\r
+\r
+  switch (opcode)\r
+  {\r
+    case REQ_INITIATE_BIND:\r
+         macCommon = (struct _CommonChars*) param2;\r
+         if (macCommon == NULL)\r
+        {\r
+           printf ("There is an NDIS misconfiguration.\n");\r
+           result = ERR_GENERAL_FAILURE;\r
+          break;\r
+        }\r
+         DEBUG2 ("module name %s\n"\r
+                 "module type %s\n",\r
+                 macCommon->moduleName,\r
+                 ((MacChars*) macCommon->serviceChars)->macName);\r
+\r
+         /* Binding to the MAC */\r
+         result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon,\r
+                                            0, REQ_BIND,\r
+                                            macCommon->moduleDS);\r
+\r
+         if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName))\r
+              handle->common = macCommon;\r
+         else PERROR ("unknown module");\r
+         ++bindEntry;\r
+        break;\r
+\r
+    case REQ_INITIATE_UNBIND:\r
+         macCommon = (struct _CommonChars*) param2;\r
+         result = macCommon->systemRequest ((DWORD)&common, 0,\r
+                                            0, REQ_UNBIND,\r
+                                            macCommon->moduleDS);\r
+         break;\r
+\r
+    default:\r
+         result = ERR_GENERAL_FAILURE;\r
+        break;\r
+  }\r
+  ARGSUSED (param1);\r
+  ARGSUSED (param3);\r
+  ARGSUSED (targetDS);\r
+  return (result);\r
+}\r
+\r
+CALLBACK (NdisRequestConfirm (WORD protId, WORD macId,   WORD reqHandle,\r
+                              WORD status, WORD request, WORD protDS))\r
+{\r
+  ARGSUSED (protId);    ARGSUSED (macId);\r
+  ARGSUSED (reqHandle); ARGSUSED (status);\r
+  ARGSUSED (request);   ARGSUSED (protDS);\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle,\r
+                               WORD status, WORD protDS))\r
+{\r
+  xmitPending--;\r
+  FreePktBuf (txBufPending);  /* Add passed ECB back to the free list */\r
+\r
+  ARGSUSED (reqHandle);\r
+  ARGSUSED (status);\r
+  ARGSUSED (protDS);\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * The primary function for receiving packets\r
+ */\r
+CALLBACK (NdisReceiveLookahead (WORD  macId,      WORD  frameSize,\r
+                                WORD  bytesAvail, BYTE *buffer,\r
+                                BYTE *indicate,   WORD  protDS))\r
+{\r
+  int     result;\r
+  PktBuf *pktBuf;\r
+  WORD    bytesCopied;\r
+  struct _TDBufDescr tDBufDescr;\r
+\r
+#if 0\r
+  TRACE1 ("lookahead length = %d, ", bytesAvail);\r
+  TRACE1 ("ecb = %08lX, ",          *ecb);\r
+  TRACE1 ("count = %08lX\n",         count);\r
+  TRACE1 ("offset = %08lX, ",        offset);\r
+  TRACE1 ("timesAllowed = %d, ",     timesAllowed);\r
+  TRACE1 ("packet size = %d\n",      look->dataLookAheadLen);\r
+#endif\r
+\r
+  /* Allocate a buffer for the packet\r
+   */\r
+  if ((pktBuf = AllocPktBuf()) == NULL)\r
+  {\r
+    droppedPackets++;\r
+    return (ERR_FRAME_REJECTED);\r
+  }\r
+\r
+  /*\r
+   * Now kludge things. Note we will have to undo this later. This will\r
+   * make the packet contiguous after the MLID has done the requested copy.\r
+   */\r
+\r
+  tDBufDescr.tDDataCount = 1;\r
+  tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL;\r
+  tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer;\r
+  tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length;\r
+  tDBufDescr.tDBufDescrRec[0].dummy     = 0;\r
+\r
+  result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr,\r
+                                               handle->common->moduleDS);\r
+  pktBuf->packetLength = bytesCopied;\r
+\r
+  if (result == ERR_SUCCESS)\r
+       EnquePktBuf(pktBuf);\r
+  else FreePktBuf (pktBuf);\r
+\r
+  ARGSUSED (frameSize);\r
+  ARGSUSED (bytesAvail);\r
+  ARGSUSED (indicate);\r
+  ARGSUSED (protDS);\r
+\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS))\r
+{\r
+  ARGSUSED (macId);\r
+  ARGSUSED (protDS);\r
+\r
+  /* We don't give a hoot about these. Just return\r
+   */\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+/*\r
+ * This is the OTHER way we may receive packets\r
+ */\r
+CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle,\r
+                            struct _RxBufDescr *rxBufDescr,\r
+                            BYTE *indicate, WORD protDS))\r
+{\r
+  struct _PktBuf *pktBuf;\r
+  int     i;\r
+\r
+  /*\r
+   * For now we copy the entire packet over to a PktBuf structure. This may be\r
+   * a performance hit but this routine probably isn't called very much, and\r
+   * it is a lot of work to do it otherwise. Also if it is a filter protocol\r
+   * packet we could end up sucking up MAC buffes.\r
+   */\r
+\r
+  if ((pktBuf = AllocPktBuf()) == NULL)\r
+  {\r
+    droppedPackets++;\r
+    return (ERR_FRAME_REJECTED);\r
+  }\r
+  pktBuf->packetLength = 0;\r
+\r
+  /* Copy the packet to the buffer\r
+   */\r
+  for (i = 0; i < rxBufDescr->rxDataCount; ++i)\r
+  {\r
+    struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i];\r
+\r
+    memcpy (pktBuf->buffer + pktBuf->packetLength,\r
+            rxDescr->rxDataPtr, rxDescr->rxDataLen);\r
+    pktBuf->packetLength += rxDescr->rxDataLen;\r
+  }\r
+\r
+  EnquePktBuf (pktBuf);\r
+\r
+  ARGSUSED (frameSize);\r
+  ARGSUSED (reqHandle);\r
+  ARGSUSED (indicate);\r
+  ARGSUSED (protDS);   \r
+\r
+  /* This frees up the buffer for the MAC to use\r
+   */\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+CALLBACK (NdisStatusProc (WORD macId,  WORD param1, BYTE *indicate,\r
+                          WORD opcode, WORD protDS))\r
+{\r
+  switch (opcode)\r
+  {\r
+    case STATUS_RING_STATUS:\r
+        break;\r
+    case STATUS_ADAPTER_CHECK:\r
+        break;\r
+    case STATUS_START_RESET:\r
+        break;\r
+    case STATUS_INTERRUPT:\r
+        break;\r
+    case STATUS_END_RESET:\r
+        break;\r
+    default:\r
+        break;\r
+  }\r
+  ARGSUSED (macId);\r
+  ARGSUSED (param1);\r
+  ARGSUSED (indicate);\r
+  ARGSUSED (opcode);\r
+  ARGSUSED (protDS);\r
+\r
+  /* We don't need to do anything about this stuff yet\r
+   */\r
+  return (ERR_SUCCESS);\r
+}\r
+\r
+/*\r
+ * Tell the NDIS driver to start the delivery of the packet\r
+ */\r
+int NdisSendPacket (struct _PktBuf *pktBuf, int macId)\r
+{ \r
+  struct _TxBufDescr txBufDescr;\r
+  int     result;\r
+\r
+  xmitPending++;\r
+  txBufPending = pktBuf;    /* we only have 1 pending Tx at a time */\r
+\r
+  txBufDescr.txImmedLen  = 0;\r
+  txBufDescr.txImmedPtr  = NULL;\r
+  txBufDescr.txDataCount = 1;\r
+  txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL;\r
+  txBufDescr.txBufDescrRec[0].dummy     = 0;\r
+  txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength;\r
+  txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer;\r
+\r
+  result = MAC_DISPATCH(handle)->transmitChain (common.moduleId,\r
+                                                pktBuf->handle,\r
+                                                &txBufDescr,\r
+                                                handle->common->moduleDS);\r
+  switch (result)\r
+  {\r
+    case ERR_OUT_OF_RESOURCE:\r
+         /* Note that this should not happen but if it does there is not\r
+          * much we can do about it\r
+          */\r
+         printf ("ERROR: transmit queue overflowed\n");\r
+         return (0);\r
+\r
+    case ERR_SUCCESS:\r
+         /* Everything was hunky dory and synchronous. Free up the \r
+          * packet buffer\r
+          */\r
+         xmitPending--;\r
+         FreePktBuf (pktBuf);\r
+         return (1);\r
+\r
+    case ERR_REQUEST_QUEUED:\r
+         /* Everything was hunky dory and asynchronous. Do nothing\r
+          */\r
+         return (1);\r
+\r
+    default:\r
+         printf ("Tx fail, code = %04X\n", result);\r
+         return (0);\r
+  }\r
+}\r
+\r
+\r
+\r
+static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]);\r
+\r
+static char *Ndis_strerror (WORD errorCode)\r
+{\r
+  static char buf[30];\r
+  int    i;\r
+\r
+  for (i = 0; i < ndis_nerr; i++)\r
+      if (errorCode == ndis_errlist[i].err_num)\r
+         return (ndis_errlist[i].err_text);\r
+\r
+  sprintf (buf,"unknown error %d",errorCode);\r
+  return (buf);\r
+}\r
+\r
+\r
+char *NdisLastError (void)\r
+{\r
+  char *errStr = lastErr;\r
+  lastErr = NULL;\r
+  return (errStr);\r
+}\r
+\r
+int NdisOpen (void)\r
+{\r
+  struct _ReqBlock reqBlock;\r
+  int     result;\r
+  int     ndisFd = open (NDIS_PATH, O_RDONLY);\r
+\r
+  if (ndisFd < 0)\r
+  {\r
+    printf ("Could not open NDIS Protocol Manager device.\n");\r
+    return (0);\r
+  }\r
+\r
+  memset (&reqBlock, 0, sizeof(ReqBlock));\r
+\r
+  reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE;\r
+\r
+  result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock));\r
+  if (result != 0)\r
+  {\r
+    printf ("Could not get Protocol Manager linkage.\n");\r
+    close (ndisFd);\r
+    return (0);\r
+  }\r
+\r
+  close (ndisFd);\r
+  protManEntry = (ProtMan) reqBlock.pointer1;\r
+  protManDS    = reqBlock.word1;\r
+\r
+  DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry));\r
+  DEBUG1 ("ProtMan DS  = %04X\n", protManDS);\r
+  return (1);\r
+}\r
+\r
+\r
+int NdisRegisterAndBind (int promis)\r
+{\r
+  struct _ReqBlock reqBlock;\r
+  WORD    result;\r
+\r
+  memset (&common,0,sizeof(common));\r
+\r
+  common.tableSize = sizeof (common);\r
+\r
+  common.majorNdisVersion   = 2;\r
+  common.minorNdisVersion   = 0;\r
+  common.majorModuleVersion = 2;\r
+  common.minorModuleVersion = 0;\r
+\r
+  /* Indicates binding from below and dynamically loaded\r
+   */\r
+  common.moduleFlags = 0x00000006L;\r
+\r
+  strcpy (common.moduleName, "PCAP");\r
+\r
+  common.protocolLevelUpper = 0xFF;\r
+  common.protocolLevelLower = 1;\r
+  common.interfaceLower     = 1;\r
+#ifdef __DJGPP__\r
+  common.moduleDS           = _dos_ds; /* the callback data segment */\r
+#else\r
+  common.moduleDS           = _DS;\r
+#endif\r
+\r
+  common.systemRequest      = (SystemRequest) systemRequestGlue;\r
+  common.serviceChars       = (BYTE*) &protChars;\r
+  common.serviceStatus      = NULL;\r
+  common.upperDispatchTable = NULL;\r
+  common.lowerDispatchTable = (BYTE*) &lowerTable;\r
+\r
+  protChars.length  = sizeof (protChars);\r
+  protChars.name[0] = 0;\r
+  protChars.type    = 0;\r
+\r
+  lowerTable.backPointer        = &common;\r
+  lowerTable.requestConfirm     = requestConfirmGlue;\r
+  lowerTable.transmitConfirm    = transmitConfirmGlue;\r
+  lowerTable.receiveLookahead   = receiveLookaheadGlue;\r
+  lowerTable.indicationComplete = indicationCompleteGlue;\r
+  lowerTable.receiveChain       = receiveChainGlue;\r
+  lowerTable.status             = statusGlue;\r
+  lowerTable.flags              = 3;\r
+  if (promis)\r
+     lowerTable.flags |= 4;   /* promiscous mode (receive everything) */\r
+\r
+  bindings.numBindings = 1;\r
+  strcpy (bindings.moduleName[0], handle->moduleName);\r
+\r
+  /* Register ourselves with NDIS\r
+   */\r
+  reqBlock.opcode   = PM_REGISTER_MODULE;\r
+  reqBlock.pointer1 = (BYTE FAR*) &common;\r
+  reqBlock.pointer2 = (BYTE FAR*) &bindings;\r
+\r
+  result = (*protManEntry) (&reqBlock, protManDS);\r
+  if (result)\r
+  {\r
+    printf ("Protman registering failed: %s\n", Ndis_strerror(result));\r
+    return (0);\r
+  }\r
+\r
+  /* Start the binding process\r
+   */\r
+  reqBlock.opcode   = PM_BIND_AND_START;\r
+  reqBlock.pointer1 = (BYTE FAR*) &failingModules;\r
+\r
+  result = (*protManEntry) (&reqBlock, protManDS);\r
+  if (result)\r
+  {\r
+    printf ("Start binding failed: %s\n", Ndis_strerror(result));\r
+    return (0);\r
+  }\r
+  return (1);\r
+}\r
+\r
+static int CheckMacFeatures (CardHandle *card)\r
+{\r
+  DWORD      serviceFlags;\r
+  BYTE _far *mediaString;\r
+  BYTE _far *mac_addr;\r
+\r
+  DEBUG2 ("checking card features\n"\r
+          "common table address = %08lX, macId = %d\n",\r
+          card->common, card->common->moduleId);\r
+\r
+  serviceFlags = MAC_CHAR (handle)->serviceFlags;\r
+\r
+  if ((serviceFlags & SF_PROMISCUOUS) == 0)\r
+  {\r
+    printf ("The MAC %s does not support promiscuous mode.\n",\r
+            card->moduleName);\r
+    return (0);\r
+  }\r
+\r
+  mediaString = MAC_CHAR (handle)->macName;\r
+\r
+  DEBUG1 ("media type = %s\n",mediaString);\r
+\r
+  /* Get the media type. And set the header size\r
+   */\r
+  if (!strncmp(mediaString,"802.3",5) ||\r
+      !strncmp(mediaString,"DIX",3)   ||\r
+      !strncmp(mediaString,"DIX+802.3",9))\r
+       headerSize = sizeof (EthernetIIHeader);\r
+\r
+  else if (!strncmp(mediaString,"FDDI",4))\r
+       headerSize = sizeof (FddiHeader) +\r
+                    sizeof (Ieee802Dot2SnapHeader);\r
+  else\r
+  {\r
+    printf ("Unsupported MAC type: `%s'\n", mediaString);\r
+    return (0);\r
+  }\r
+\r
+  frameSize = MAC_CHAR (handle)->maxFrameSize;\r
+  mac_addr  = MAC_CHAR (handle)->currentAddress;\r
+\r
+  printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n",\r
+          mac_addr[0], mac_addr[1], mac_addr[2],\r
+          mac_addr[3], mac_addr[4], mac_addr[5]);\r
+  return (1);\r
+}\r
+\r
+static int NdisStartMac (CardHandle *card)\r
+{\r
+  WORD result;\r
+\r
+  /* Set the lookahead length\r
+   */\r
+  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,\r
+                                          headerSize, 0,\r
+                                          REQ_SET_LOOKAHEAD,\r
+                                          card->common->moduleDS);\r
+\r
+  /* We assume that if we got INVALID PARAMETER then either this\r
+   * is not supported or will work anyway. NE2000 does this.\r
+   */\r
+  if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER)\r
+  {\r
+    DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result));\r
+    return (0);\r
+  }\r
+\r
+  /* Set the packet filter. Note that for some medias and drivers we\r
+   * must specify all three flags or the card(s) will not operate correctly.\r
+   */\r
+  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,\r
+                      /* all packets */   FILTER_PROMISCUOUS |\r
+                      /* packets to us */ FILTER_DIRECTED    |\r
+                      /* broadcasts */    FILTER_BROADCAST,\r
+                                          0, REQ_SET_PACKET_FILTER,\r
+                                          card->common->moduleDS);\r
+  if (result != ERR_SUCCESS)\r
+  {\r
+    DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result));\r
+    return (0);\r
+  }\r
+\r
+  /* If OPEN/CLOSE supported then open the adapter\r
+   */\r
+  if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE)\r
+  {\r
+    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL,\r
+                                            REQ_OPEN_ADAPTER,\r
+                                            card->common->moduleDS);\r
+    if (result != ERR_SUCCESS)\r
+    {\r
+      DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result));\r
+      return (0);\r
+    }\r
+  }\r
+  return (1);\r
+}\r
+\r
+void NdisShutdown (void)\r
+{\r
+  struct _ReqBlock reqBlock;\r
+  int     result, i;\r
+\r
+  if (!handle)\r
+     return;\r
+\r
+  /* If the adapters support open and are open then close them\r
+   */\r
+  if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) &&\r
+      (MAC_STATUS(handle)->macStatus & MAC_OPEN))\r
+  {\r
+    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0,\r
+                                            REQ_CLOSE_ADAPTER,\r
+                                            handle->common->moduleDS);\r
+    if (result != ERR_SUCCESS)\r
+    {\r
+      printf ("Closing the MAC failed: %s\n", Ndis_strerror(result));\r
+      return;\r
+    }\r
+  }\r
+\r
+  /* Tell the Protocol Manager to unbind and stop\r
+   */\r
+  reqBlock.opcode   = PM_UNBIND_AND_STOP;\r
+  reqBlock.pointer1 = (BYTE FAR*) &failingModules;\r
+  reqBlock.pointer2 = NULL;\r
+\r
+  result = (*protManEntry) (&reqBlock, protManDS);\r
+  if (result)\r
+     printf ("Unbind failed: %s\n",  Ndis_strerror(result));\r
+\r
+  for (i = 0; i < STACK_POOL_SIZE; ++i)\r
+     free (freeStacks[i] - STACK_SIZE);\r
+\r
+  handle = NULL;\r
+}\r
+\r
+int NdisInit (int promis)\r
+{\r
+  int i, result;\r
+\r
+  /* Allocate the real mode stacks used for NDIS callbacks\r
+   */\r
+  for (i = 0; i < STACK_POOL_SIZE; ++i)\r
+  {\r
+    freeStacks[i] = malloc (STACK_SIZE);\r
+    if (!freeStacks[i])\r
+       return (0);\r
+    freeStacks[i] += STACK_SIZE;\r
+  }\r
+\r
+  if (!NdisOpen())\r
+     return (0);\r
+\r
+  if (!NdisRegisterAndBind(promis))\r
+     return (0);\r
+\r
+  DEBUG1 ("My module id: %d\n", common.moduleId);\r
+  DEBUG1 ("Handle id;    %d\n", handle->common->moduleId);\r
+  DEBUG1 ("MAC card:     %-16s - ", handle->moduleName);\r
+\r
+  atexit (NdisShutdown);\r
+\r
+  if (!CheckMacFeatures(&handle))\r
+     return (0);\r
+\r
+  switch (mediaType)\r
+  {\r
+    case MEDIA_FDDI:\r
+         DEBUG0 ("Media type: FDDI");\r
+        break;\r
+    case MEDIA_ETHERNET:\r
+         DEBUG0 ("Media type: ETHERNET");\r
+        break;\r
+    default:\r
+         DEBUG0 ("Unsupported media.\n");\r
+         return (0);\r
+  }\r
+\r
+  DEBUG1 (" - Frame size: %d\n", frameSize);\r
+\r
+  if (!NdisStartMac(&handle))\r
+     return (0);\r
+  return (1);\r
+}\r
+#endif  /* USE_NDIS2 */\r
+\r
diff --git a/msdos/ndis2.h b/msdos/ndis2.h
new file mode 100644 (file)
index 0000000..dc72f4c
--- /dev/null
@@ -0,0 +1,559 @@
+/* \r
+ * Copyright (c) 1993,1994\r
+ *      Texas A&M University.  All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ * 3. All advertising materials mentioning features or use of this software\r
+ *    must display the following acknowledgement:\r
+ *      This product includes software developed by Texas A&M University\r
+ *      and its contributors.\r
+ * 4. Neither the name of the University nor the names of its contributors\r
+ *    may be used to endorse or promote products derived from this software\r
+ *    without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ * SUCH DAMAGE.\r
+ *\r
+ * Developers:\r
+ *             David K. Hess, Douglas Lee Schales, David R. Safford\r
+ *\r
+ * Heavily modified for Metaware HighC + GNU C 2.8+\r
+ *             Gisle Vanem 1998\r
+ */\r
+\r
+#ifndef __PCAP_NDIS_H\r
+#define __PCAP_NDIS_H\r
+\r
+#if defined (__HIGHC__)\r
+  #define pascal          _CC(_CALLEE_POPS_STACK & ~_REVERSE_PARMS) /* calling convention */\r
+  #define CALLBACK(foo)   pascal WORD foo\r
+  #define PAS_PTR(x,arg)  typedef FAR WORD pascal (*x) arg\r
+  #define GUARD()         _inline (0x9C,0xFA)   /* pushfd, cli */\r
+  #define UNGUARD()       _inline (0x9D)        /* popfd */\r
+  #define FAR             _far\r
+\r
+#elif defined(__GNUC__)\r
+  #define CALLBACK(foo)   WORD foo __attribute__((stdcall))\r
+  #define PAS_PTR(x,arg)  typedef WORD (*x) arg __attribute__((stdcall))\r
+  #define GUARD()         __asm__ __volatile__ ("pushfd; cli")\r
+  #define UNGUARD()       __asm__ __volatile__ ("popfd")\r
+  #define FAR\r
+\r
+#elif defined (__TURBOC__)\r
+  #define CALLBACK(foo)   WORD pascal foo\r
+  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg\r
+  #define GUARD()         _asm { pushf; cli }\r
+  #define UNGUARD()       _asm { popf }\r
+  #define FAR             _far\r
+\r
+#elif defined (__WATCOMC__)\r
+  #define CALLBACK(foo)   WORD pascal foo\r
+  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg\r
+  #define GUARD()         _disable()\r
+  #define UNGUARD()       _enable()\r
+  #define FAR             _far\r
+\r
+#else\r
+  #error Unsupported compiler\r
+#endif\r
+\r
+\r
+/*\r
+ *  Forwards\r
+ */\r
+struct _ReqBlock;\r
+struct _TxBufDescr;\r
+struct _TDBufDescr;\r
+\r
+/*\r
+ * Protocol Manager API\r
+ */\r
+PAS_PTR (ProtMan, (struct _ReqBlock FAR*, WORD));\r
+\r
+/*\r
+ * System request\r
+ */\r
+PAS_PTR (SystemRequest, (DWORD, DWORD, WORD, WORD, WORD));\r
+\r
+/*\r
+ * MAC API\r
+ */\r
+PAS_PTR (TransmitChain, (WORD, WORD, struct _TxBufDescr FAR*, WORD));\r
+PAS_PTR (TransferData,  (WORD*,WORD, struct _TDBufDescr FAR*, WORD));\r
+PAS_PTR (Request,       (WORD, WORD, WORD, DWORD, WORD, WORD));\r
+PAS_PTR (ReceiveRelease,(WORD, WORD));\r
+PAS_PTR (IndicationOn,  (WORD));\r
+PAS_PTR (IndicationOff, (WORD));\r
+\r
+\r
+typedef enum {\r
+        HARDWARE_NOT_INSTALLED  = 0,\r
+        HARDWARE_FAILED_DIAG    = 1,\r
+        HARDWARE_FAILED_CONFIG  = 2,\r
+        HARDWARE_HARD_FAULT     = 3,\r
+        HARDWARE_SOFT_FAULT     = 4,\r
+        HARDWARE_OK             = 7,\r
+        HARDWARE_MASK           = 0x0007,\r
+        MAC_BOUND               = 0x0008,\r
+        MAC_OPEN                = 0x0010,\r
+        DIAG_IN_PROGRESS        = 0x0020\r
+      } NdisMacStatus;\r
+\r
+typedef enum {\r
+        STATUS_RING_STATUS      = 1,\r
+        STATUS_ADAPTER_CHECK    = 2,\r
+        STATUS_START_RESET      = 3,\r
+        STATUS_INTERRUPT        = 4,\r
+        STATUS_END_RESET        = 5\r
+      } NdisStatus;\r
+\r
+typedef enum {\r
+        FILTER_DIRECTED         = 1,\r
+        FILTER_BROADCAST        = 2,\r
+        FILTER_PROMISCUOUS      = 4,\r
+        FILTER_SOURCE_ROUTE     = 8\r
+      } NdisPacketFilter;\r
+\r
+typedef enum {\r
+        REQ_INITIATE_DIAGNOSTICS     = 1,\r
+        REQ_READ_ERROR_LOG           = 2,\r
+        REQ_SET_STATION_ADDRESS      = 3,\r
+        REQ_OPEN_ADAPTER             = 4,\r
+        REQ_CLOSE_ADAPTER            = 5,\r
+        REQ_RESET_MAC                = 6,\r
+        REQ_SET_PACKET_FILTER        = 7,\r
+        REQ_ADD_MULTICAST_ADDRESS    = 8,\r
+        REQ_DELETE_MULTICAST_ADDRESS = 9,\r
+        REQ_UPDATE_STATISTICS        = 10,\r
+        REQ_CLEAR_STATISTICS         = 11,\r
+        REQ_INTERRUPT_REQUEST        = 12,\r
+        REQ_SET_FUNCTIONAL_ADDRESS   = 13,\r
+        REQ_SET_LOOKAHEAD            = 14\r
+      } NdisGeneralRequest;\r
+\r
+typedef enum {\r
+        SF_BROADCAST             = 0x00000001L,\r
+        SF_MULTICAST             = 0x00000002L,\r
+        SF_FUNCTIONAL            = 0x00000004L,\r
+        SF_PROMISCUOUS           = 0x00000008L,\r
+        SF_SOFT_ADDRESS          = 0x00000010L,\r
+        SF_STATS_CURRENT         = 0x00000020L,\r
+        SF_INITIATE_DIAGS        = 0x00000040L,\r
+        SF_LOOPBACK              = 0x00000080L,\r
+        SF_RECEIVE_CHAIN         = 0x00000100L,\r
+        SF_SOURCE_ROUTING        = 0x00000200L,\r
+        SF_RESET_MAC             = 0x00000400L,\r
+        SF_OPEN_CLOSE            = 0x00000800L,\r
+        SF_INTERRUPT_REQUEST     = 0x00001000L,\r
+        SF_SOURCE_ROUTING_BRIDGE = 0x00002000L,\r
+        SF_VIRTUAL_ADDRESSES     = 0x00004000L\r
+      } NdisMacServiceFlags;\r
+\r
+typedef enum {\r
+        REQ_INITIATE_BIND        = 1,\r
+        REQ_BIND                 = 2,\r
+        REQ_INITIATE_PREBIND     = 3,\r
+        REQ_INITIATE_UNBIND      = 4,\r
+        REQ_UNBIND               = 5\r
+      } NdisSysRequest;\r
+\r
+typedef enum  {\r
+        PM_GET_PROTOCOL_MANAGER_INFO      = 1,\r
+        PM_REGISTER_MODULE                = 2,\r
+        PM_BIND_AND_START                 = 3,\r
+        PM_GET_PROTOCOL_MANAGER_LINKAGE   = 4,\r
+        PM_GET_PROTOCOL_INI_PATH          = 5,\r
+        PM_REGISTER_PROTOCOL_MANAGER_INFO = 6,\r
+        PM_INIT_AND_REGISTER              = 7,\r
+        PM_UNBIND_AND_STOP                = 8,\r
+        PM_BIND_STATUS                    = 9,\r
+        PM_REGISTER_STATUS                = 10\r
+      } NdisProtManager;\r
+\r
+\r
+typedef enum {\r
+        ERR_SUCCESS                      = 0x00,\r
+        ERR_WAIT_FOR_RELEASE             = 0x01,\r
+        ERR_REQUEST_QUEUED               = 0x02,\r
+        ERR_FRAME_NOT_RECOGNIZED         = 0x03,\r
+        ERR_FRAME_REJECTED               = 0x04,\r
+        ERR_FORWARD_FRAME                = 0x05,\r
+        ERR_OUT_OF_RESOURCE              = 0x06,\r
+        ERR_INVALID_PARAMETER            = 0x07,\r
+        ERR_INVALID_FUNCTION             = 0x08,\r
+        ERR_NOT_SUPPORTED                = 0x09,\r
+        ERR_HARDWARE_ERROR               = 0x0A,\r
+        ERR_TRANSMIT_ERROR               = 0x0B,\r
+        ERR_NO_SUCH_DESTINATION          = 0x0C,\r
+        ERR_BUFFER_TOO_SMALL             = 0x0D,\r
+        ERR_ALREADY_STARTED              = 0x20,\r
+        ERR_INCOMPLETE_BINDING           = 0x21,\r
+        ERR_DRIVER_NOT_INITIALIZED       = 0x22,\r
+        ERR_HARDWARE_NOT_FOUND           = 0x23,\r
+        ERR_HARDWARE_FAILURE             = 0x24,\r
+        ERR_CONFIGURATION_FAILURE        = 0x25,\r
+        ERR_INTERRUPT_CONFLICT           = 0x26,\r
+        ERR_INCOMPATIBLE_MAC             = 0x27,\r
+        ERR_INITIALIZATION_FAILED        = 0x28,\r
+        ERR_NO_BINDING                   = 0x29,\r
+        ERR_NETWORK_MAY_NOT_BE_CONNECTED = 0x2A,\r
+        ERR_INCOMPATIBLE_OS_VERSION      = 0x2B,\r
+        ERR_ALREADY_REGISTERED           = 0x2C,\r
+        ERR_PATH_NOT_FOUND               = 0x2D,\r
+        ERR_INSUFFICIENT_MEMORY          = 0x2E,\r
+        ERR_INFO_NOT_FOUND               = 0x2F,\r
+        ERR_GENERAL_FAILURE              = 0xFF\r
+      } NdisError;\r
+\r
+#define NDIS_PARAM_INTEGER   0\r
+#define NDIS_PARAM_STRING    1\r
+\r
+#define NDIS_TX_BUF_LENGTH   8\r
+#define NDIS_TD_BUF_LENGTH   1\r
+#define NDIS_RX_BUF_LENGTH   8\r
+\r
+#define NDIS_PTR_PHYSICAL    0\r
+#define NDIS_PTR_VIRTUAL     2\r
+\r
+#define NDIS_PATH    "PROTMAN$"\r
+\r
+\r
+typedef struct _CommonChars {\r
+        WORD  tableSize;\r
+        BYTE  majorNdisVersion;        /* 2 - Latest version */\r
+        BYTE  minorNdisVersion;        /* 0                  */\r
+        WORD  reserved1;\r
+        BYTE  majorModuleVersion;\r
+        BYTE  minorModuleVersion;\r
+        DWORD moduleFlags;\r
+        /* 0 - Binding at upper boundary supported\r
+         * 1 - Binding at lower boundary supported\r
+         * 2 - Dynamically bound.\r
+         * 3-31 - Reserved, must be zero.\r
+         */\r
+        BYTE  moduleName[16];\r
+        BYTE  protocolLevelUpper;\r
+        /* 1 - MAC\r
+         * 2 - Data Link\r
+         * 3 - Network\r
+         * 4 - Transport\r
+         * 5 - Session\r
+         * -1 - Not specified\r
+         */\r
+        BYTE  interfaceUpper;\r
+        BYTE  protocolLevelLower;\r
+        /* 0 - Physical\r
+         * 1 - MAC\r
+         * 2 - Data Link\r
+         * 3 - Network\r
+         * 4 - Transport\r
+         * 5 - Session\r
+         * -1 - Not specified\r
+         */\r
+        BYTE  interfaceLower;\r
+        WORD  moduleId;\r
+        WORD  moduleDS;\r
+        SystemRequest systemRequest;\r
+        BYTE *serviceChars;\r
+        BYTE *serviceStatus;\r
+        BYTE *upperDispatchTable;\r
+        BYTE *lowerDispatchTable;\r
+        BYTE *reserved2;            /* Must be NULL */\r
+        BYTE *reserved3;            /* Must be NULL */\r
+      } CommonChars;\r
+\r
+\r
+typedef struct _MulticastList {\r
+        WORD   maxMulticastAddresses;\r
+        WORD   numberMulticastAddresses;\r
+        BYTE   multicastAddress[16][16];\r
+      } MulticastList;\r
+\r
+\r
+typedef struct _MacChars {\r
+        WORD   tableSize;\r
+        BYTE   macName[16];\r
+        WORD   addressLength;\r
+        BYTE   permanentAddress[16];\r
+        BYTE   currentAddress[16];\r
+        DWORD  currentFunctionalAddress;\r
+        MulticastList *multicastList;\r
+        DWORD  linkSpeed;\r
+        DWORD  serviceFlags;\r
+        WORD   maxFrameSize;\r
+        DWORD  txBufferSize;\r
+        WORD   txBufferAllocSize;\r
+        DWORD  rxBufferSize;\r
+        WORD   rxBufferAllocSize;\r
+        BYTE   ieeeVendor[3];\r
+        BYTE   vendorAdapter;\r
+        BYTE  *vendorAdapterDescription;\r
+        WORD   interruptLevel;\r
+        WORD   txQueueDepth;\r
+        WORD   maxDataBlocks;\r
+      } MacChars;\r
+\r
+\r
+typedef struct _ProtocolChars {\r
+        WORD   length;\r
+        BYTE   name[16];\r
+        WORD   type;\r
+      } ProtocolChars;\r
+\r
+\r
+typedef struct _MacUpperDispatch {\r
+        CommonChars      *backPointer;\r
+        Request           request;\r
+        TransmitChain     transmitChain;\r
+        TransferData      transferData;\r
+        ReceiveRelease    receiveRelease;\r
+        IndicationOn      indicationOn;\r
+        IndicationOff     indicationOff;\r
+      } MacUpperDispatch;\r
+\r
+\r
+typedef struct _MacStatusTable {\r
+        WORD   tableSize;\r
+        DWORD  lastDiag;\r
+        DWORD  macStatus;\r
+        WORD   packetFilter;\r
+        BYTE  *mediaSpecificStats;\r
+        DWORD  lastClear;\r
+        DWORD  totalFramesRx;\r
+        DWORD  totalFramesCrc;\r
+        DWORD  totalBytesRx;\r
+        DWORD  totalDiscardBufSpaceRx;\r
+        DWORD  totalMulticastRx;\r
+        DWORD  totalBroadcastRx;\r
+        DWORD  obsolete1[5];\r
+        DWORD  totalDiscardHwErrorRx;\r
+        DWORD  totalFramesTx;\r
+        DWORD  totalBytesTx;\r
+        DWORD  totalMulticastTx;\r
+        DWORD  totalBroadcastTx;\r
+        DWORD  obsolete2[2];\r
+        DWORD  totalDiscardTimeoutTx;\r
+        DWORD  totalDiscardHwErrorTx;\r
+      } MacStatusTable;\r
+\r
+\r
+typedef struct _ProtDispatch {\r
+        CommonChars *backPointer;\r
+        DWORD        flags;\r
+        /* 0 - handles non-LLC frames\r
+         * 1 - handles specific-LSAP LLC frames\r
+         * 2 - handles specific-LSAP LLC frames\r
+         * 3-31 - reserved must be 0\r
+         */\r
+        void  (*requestConfirm) (void);\r
+        void  (*transmitConfirm) (void);\r
+        void  (*receiveLookahead) (void);\r
+        void  (*indicationComplete) (void);\r
+        void  (*receiveChain) (void);\r
+        void  (*status) (void);\r
+      } ProtDispatch;\r
+\r
+\r
+typedef struct _ReqBlock {\r
+        WORD      opcode;\r
+        WORD      status;\r
+        BYTE FAR *pointer1;\r
+        BYTE FAR *pointer2;\r
+        WORD      word1;\r
+      } ReqBlock;\r
+\r
+\r
+typedef struct _TxBufDescrRec {\r
+        BYTE   txPtrType;\r
+        BYTE   dummy;\r
+        WORD   txDataLen;\r
+        BYTE  *txDataPtr;\r
+      } TxBufDescrRec;\r
+\r
+\r
+typedef struct _TxBufDescr {\r
+        WORD          txImmedLen;\r
+        BYTE         *txImmedPtr;\r
+        WORD          txDataCount;\r
+        TxBufDescrRec txBufDescrRec[NDIS_TX_BUF_LENGTH];\r
+      } TxBufDescr;\r
+\r
+\r
+typedef struct _TDBufDescrRec {\r
+        BYTE   tDPtrType;\r
+        BYTE   dummy;\r
+        WORD   tDDataLen;\r
+        BYTE  *tDDataPtr;\r
+      } TDBufDescrRec;\r
+\r
+\r
+typedef struct _TDBufDescr {\r
+        WORD          tDDataCount;\r
+        TDBufDescrRec tDBufDescrRec[NDIS_TD_BUF_LENGTH];\r
+      } TDBufDescr;\r
+\r
+\r
+typedef struct _RxBufDescrRec {\r
+        WORD   rxDataLen;\r
+        BYTE  *rxDataPtr;\r
+      } RxBufDescrRec;\r
+\r
+\r
+typedef struct _RxBufDescr {\r
+        WORD          rxDataCount;\r
+        RxBufDescrRec rxBufDescrRec[NDIS_RX_BUF_LENGTH];\r
+      } RxBufDescr;\r
+\r
+\r
+typedef struct _PktBuf {\r
+       struct _PktBuf *nextLink;\r
+       struct _PktBuf *prevLink;\r
+        int    handle;\r
+        int    length;\r
+        int    packetLength;\r
+        DWORD  sequence;\r
+        BYTE  *buffer;\r
+      } PktBuf;\r
+\r
+\r
+typedef struct _CardHandle {\r
+        BYTE         moduleName[16];\r
+        CommonChars *common;\r
+      } CardHandle;\r
+\r
+\r
+typedef struct _BindingsList {\r
+        WORD  numBindings;\r
+        BYTE  moduleName[2][16];\r
+      } BindingsList;\r
+\r
+\r
+typedef struct _FailingModules {\r
+        BYTE  upperModuleName[16];\r
+        BYTE  lowerModuleName[16];\r
+      } FailingModules;\r
+\r
+\r
+typedef union _HardwareAddress {\r
+        BYTE  bytes[6];\r
+        WORD  words[3];\r
+        struct {\r
+          BYTE bytes[6];\r
+        } addr;\r
+      } HardwareAddress;\r
+\r
+\r
+typedef struct _FddiHeader {\r
+        BYTE             frameControl;\r
+        HardwareAddress  etherDestHost;\r
+        HardwareAddress  etherSrcHost;\r
+      } FddiHeader;\r
+\r
+\r
+typedef struct _EthernetIIHeader {\r
+        HardwareAddress  etherDestHost;\r
+        HardwareAddress  etherSrcHost;\r
+        WORD             etherType;\r
+      } EthernetIIHeader;\r
+\r
+\r
+typedef struct _Ieee802Dot5Header {\r
+        HardwareAddress  etherDestHost;\r
+        HardwareAddress  etherSrcHost;\r
+        BYTE             routeInfo[30];\r
+      } Ieee802Dot5Header;\r
+\r
+\r
+typedef struct _Ieee802Dot2SnapHeader {\r
+        BYTE  dsap;                      /* 0xAA */\r
+        BYTE  ssap;                      /* 0xAA */\r
+        BYTE  control;                   /* 3    */\r
+        BYTE protocolId[5];\r
+      } Ieee802Dot2SnapHeader;\r
+\r
+\r
+/*\r
+ *  Prototypes\r
+ */\r
+extern char *NdisLastError        (void);\r
+extern int   NdisOpen             (void);\r
+extern int   NdisInit             (int promis);\r
+extern int   NdisRegisterAndBind  (int promis);\r
+extern void  NdisShutdown         (void);\r
+extern void  NdisCheckMacFeatures (struct _CardHandle *card);\r
+extern int   NdisSendPacket       (struct _PktBuf *pktBuf, int macId);\r
+\r
+/*\r
+ *  Assembly "glue" functions\r
+ */\r
+extern int systemRequestGlue();\r
+extern int requestConfirmGlue();\r
+extern int transmitConfirmGlue();\r
+extern int receiveLookaheadGlue();\r
+extern int indicationCompleteGlue();\r
+extern int receiveChainGlue();\r
+extern int statusGlue();\r
+\r
+/*\r
+ *  IOCTL function\r
+ */\r
+#ifdef __SMALL__\r
+extern int _far NdisGetLinkage (int handle, char *data, int size);\r
+#else\r
+extern int NdisGetLinkage (int handle, char *data, int size);\r
+#endif\r
+\r
+/*\r
+ *  NDIS callback handlers\r
+ */\r
+CALLBACK (NdisSystemRequest     (DWORD,DWORD, WORD, WORD, WORD));\r
+CALLBACK (NdisRequestConfirm    ( WORD, WORD, WORD, WORD, WORD,WORD));\r
+CALLBACK (NdisTransmitConfirm   ( WORD, WORD, WORD, WORD, WORD));\r
+CALLBACK (NdisReceiveLookahead  ( WORD, WORD, WORD, BYTE*, BYTE*, WORD));\r
+CALLBACK (NdisReceiveChain      ( WORD, WORD, WORD, struct _RxBufDescr*, BYTE*, WORD));\r
+CALLBACK (NdisStatusProc        ( WORD, WORD, BYTE*, WORD,WORD));\r
+CALLBACK (NdisIndicationComplete( WORD, WORD));\r
+\r
+BYTE *NdisAllocStack (void);\r
+void  NdisFreeStack  (BYTE*);\r
+\r
+#ifdef __HIGHC__\r
+  #define RENAME_ASM_SYM(x) pragma Alias(x,"@" #x "")  /* prepend `@' */\r
+  #define RENAME_C_SYM(x)   pragma Alias(x,"_" #x "")  /* prepend `_' */\r
+\r
+  RENAME_ASM_SYM (systemRequestGlue);\r
+  RENAME_ASM_SYM (requestConfirmGlue);\r
+  RENAME_ASM_SYM (transmitConfirmGlue);\r
+  RENAME_ASM_SYM (receiveLookaheadGlue);\r
+  RENAME_ASM_SYM (indicationCompleteGlue);\r
+  RENAME_ASM_SYM (receiveChainGlue);\r
+  RENAME_ASM_SYM (statusGlue);\r
+  RENAME_ASM_SYM (NdisGetLinkage);\r
+  RENAME_C_SYM   (NdisSystemRequest);\r
+  RENAME_C_SYM   (NdisRequestConfirm);\r
+  RENAME_C_SYM   (NdisTransmitConfirm);\r
+  RENAME_C_SYM   (NdisReceiveLookahead);\r
+  RENAME_C_SYM   (NdisIndicationComplete);\r
+  RENAME_C_SYM   (NdisReceiveChain);\r
+  RENAME_C_SYM   (NdisStatusProc);\r
+  RENAME_C_SYM   (NdisAllocStack);\r
+  RENAME_C_SYM   (NdisFreeStack);\r
+#endif\r
+\r
+#endif\r
diff --git a/msdos/ndis_0.asm b/msdos/ndis_0.asm
new file mode 100644 (file)
index 0000000..2990985
--- /dev/null
@@ -0,0 +1,188 @@
+PAGE 60,132\r
+NAME NDIS_0\r
+\r
+ifdef DOSX\r
+  .386\r
+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'\r
+  _TEXT   ENDS\r
+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'\r
+  _DATA   ENDS\r
+  _TEXT32 SEGMENT PUBLIC BYTE  USE32 'CODE'\r
+  _TEXT32 ENDS\r
+  CB_DSEG EQU <CS>                          ; DOSX is tiny-model\r
+  D_SEG   EQU <_TEXT SEGMENT>\r
+  D_END   EQU <_TEXT ENDS>\r
+  ASSUME  CS:_TEXT,DS:_TEXT\r
+\r
+  PUSHREGS equ <pushad>\r
+  POPREGS  equ <popad>\r
+\r
+  PUBPROC macro name\r
+          align 4\r
+          public @&name\r
+          @&name label near\r
+          endm\r
+else\r
+  .286\r
+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'\r
+  _TEXT   ENDS\r
+  _DATA   SEGMENT PUBLIC DWORD 'DATA'\r
+  _DATA   ENDS\r
+  CB_DSEG EQU <SEG _DATA>                   ; 16bit is small/large model\r
+  D_SEG   EQU <_DATA SEGMENT>\r
+  D_END   EQU <_DATA ENDS>\r
+  ASSUME  CS:_TEXT,DS:_DATA\r
+\r
+  PUSHREGS equ <pusha>\r
+  POPREGS  equ <popa>\r
+\r
+  PUBPROC  macro name\r
+           public _&name\r
+           _&name label far\r
+           endm\r
+endif\r
+\r
+;-------------------------------------------\r
+\r
+D_SEG\r
+\r
+D_END\r
+\r
+\r
+_TEXT SEGMENT\r
+\r
+EXTRN _NdisSystemRequest      : near\r
+EXTRN _NdisRequestConfirm     : near\r
+EXTRN _NdisTransmitConfirm    : near\r
+EXTRN _NdisReceiveLookahead   : near\r
+EXTRN _NdisIndicationComplete : near\r
+EXTRN _NdisReceiveChain       : near\r
+EXTRN _NdisStatusProc         : near\r
+EXTRN _NdisAllocStack         : near\r
+EXTRN _NdisFreeStack          : near\r
+\r
+;\r
+; *ALL* interrupt threads come through this macro.\r
+;\r
+CALLBACK macro callbackProc, argsSize\r
+\r
+     pushf\r
+     PUSHREGS                ;; Save the registers\r
+\r
+     push es\r
+     push ds\r
+     mov  ax,CB_DSEG         ;; Load DS\r
+     mov  ds,ax\r
+     call _NdisAllocStack    ;; Get and install a stack.\r
+\r
+     mov  bx,ss              ;; Save off the old stack in other regs\r
+     mov  cx,sp\r
+     mov  ss,dx              ;; Install the new one\r
+     mov  sp,ax\r
+     push bx                 ;; Save the old one on to the new stack\r
+     push cx\r
+     sub  sp,&argsSize       ;; Allocate space for arguments on the stack\r
+\r
+     mov  ax,ss              ;; Set up the destination for the move\r
+     mov  es,ax\r
+     mov  di,sp\r
+     mov  ds,bx              ;; Set up the source for the move.\r
+     mov  si,cx\r
+     add  si,4+6+32\r
+\r
+     mov  cx,&argsSize       ;; Move the arguments to the stack.\r
+     shr  cx,1\r
+     cld\r
+     rep  movsw\r
+\r
+     mov  ax,CB_DSEG         ;; Set my data segment again.\r
+     mov  ds,ax\r
+\r
+     call &callbackProc      ;; Call the real callback.\r
+     pop  di                 ;; Pop off the old stack\r
+     pop  si\r
+     mov  bx,ss              ;; Save off the current allocated stack.\r
+     mov  cx,sp\r
+     mov  ss,si              ;; Restore the old stack\r
+     mov  sp,di\r
+     push ax                 ;; Save the return code\r
+     push bx                 ;; Free the stack. Push the pointer to it\r
+     push cx\r
+     call _NdisFreeStack\r
+     add  sp,4\r
+     pop  ax                 ;; Get the return code back\r
+     add  di,32              ;; Get a pointer to ax on the stack\r
+     mov  word ptr ss:[di],ax\r
+     pop  ds\r
+     pop  es\r
+\r
+     POPREGS\r
+     popf\r
+endm\r
+\r
+;\r
+; Define all of the callbacks for the NDIS procs.\r
+;\r
+\r
+PUBPROC systemRequestGlue\r
+CALLBACK _NdisSystemRequest,14\r
+RETF\r
+\r
+PUBPROC requestConfirmGlue\r
+CALLBACK _NdisRequestConfirm,12\r
+RETF\r
+\r
+PUBPROC transmitConfirmGlue\r
+CALLBACK _NdisTransmitConfirm,10\r
+RETF\r
+\r
+PUBPROC receiveLookaheadGlue\r
+CALLBACK _NdisReceiveLookahead,16\r
+RETF\r
+\r
+PUBPROC indicationCompleteGlue\r
+CALLBACK _NdisIndicationComplete,4\r
+RETF\r
+\r
+PUBPROC receiveChainGlue\r
+CALLBACK _NdisReceiveChain,16\r
+RETF\r
+\r
+PUBPROC statusGlue\r
+CALLBACK _NdisStatusProc,12\r
+RETF\r
+\r
+;\r
+; int FAR NdisGetLinkage (int handle, char *data, int size);\r
+;\r
+\r
+ifdef DOSX\r
+  PUBPROC NdisGetLinkage\r
+          push ebx\r
+          mov ebx, [esp+8]              ; device handle\r
+          mov eax, 4402h                ; IOCTRL read function\r
+          mov edx, [esp+12]             ; DS:EDX -> result data\r
+          mov ecx, [esp+16]             ; ECX = length\r
+          int 21h\r
+          pop ebx\r
+          jc  @fail\r
+          xor eax, eax\r
+  @fail:  ret\r
+\r
+else\r
+  PUBPROC NdisGetLinkage\r
+          enter 0, 0\r
+          mov bx, [bp+6]\r
+          mov ax, 4402h\r
+          mov dx, [bp+8]\r
+          mov cx, [bp+12]\r
+          int 21h\r
+          jc  @fail\r
+          xor ax, ax\r
+  @fail:  leave\r
+          retf\r
+endif\r
+\r
+ENDS\r
+\r
+END\r
diff --git a/msdos/pkt_rx0.asm b/msdos/pkt_rx0.asm
new file mode 100644 (file)
index 0000000..94f3d09
--- /dev/null
@@ -0,0 +1,197 @@
+PAGE 60,132\r
+NAME PKT_RX\r
+\r
+ifdef ??version        ; using TASM\r
+  masm\r
+  jumps\r
+endif\r
+\r
+PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp\r
+PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd\r
+\r
+;\r
+; these sizes MUST be equal to the sizes in PKTDRVR.H\r
+;\r
+\r
+RX_BUF_SIZE = 1500      ; max message size on Ethernet\r
+TX_BUF_SIZE = 1500\r
+\r
+ifdef DOSX\r
+ .386\r
+  NUM_RX_BUF = 32       ; # of RX element buffers\r
+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'\r
+  _TEXT   ENDS\r
+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'\r
+  _DATA   ENDS\r
+  D_SEG   EQU <_TEXT SEGMENT>\r
+  D_END   EQU <_TEXT ENDS>\r
+  ASSUME  CS:_TEXT,DS:_TEXT\r
+else\r
+ .286\r
+  NUM_RX_BUF = 10\r
+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'\r
+  _TEXT   ENDS\r
+  _DATA   SEGMENT PUBLIC DWORD 'DATA'\r
+  _DATA   ENDS\r
+  D_SEG   EQU <_DATA SEGMENT>\r
+  D_END   EQU <_DATA ENDS>\r
+  ASSUME  CS:_TEXT,DS:_DATA\r
+endif\r
+\r
+;-------------------------------------------\r
+\r
+D_SEG\r
+\r
+RX_ELEMENT     STRUC\r
+   firstCount  dw  0                          ; # of bytes on 1st call\r
+   secondCount dw  0                          ; # of bytes on 2nd call\r
+   handle      dw  0                          ; handle for upcall\r
+   destinAdr   db  6           dup (0)        ; packet destination address\r
+   sourceAdr   db  6           dup (0)        ; packet source address\r
+   protocol    dw  0                          ; packet protocol number\r
+   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer\r
+ENDS\r
+               align 4\r
+_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets\r
+_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf\r
+_pktDrop       dw  0,0                        ; packet drop counter\r
+_pktTemp       db  20                dup (0)  ; temp work area\r
+_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer\r
+_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures\r
+ LAST_OFS      = offset $\r
+\r
+ screenSeg     dw  0B800h\r
+ newInOffset   dw  0\r
+\r
+ fanChars      db  '-\|/'\r
+ fanIndex      dw  0\r
+\r
+D_END\r
+\r
+_TEXT SEGMENT\r
+\r
+\r
+SHOW_RX  MACRO\r
+         push es\r
+         push bx\r
+         mov bx, screenSeg\r
+         mov es, bx                    ;; r-mode segment of colour screen\r
+         mov di, 158                   ;; upper right corner - 1\r
+         mov bx, fanIndex\r
+         mov al, fanChars[bx]          ;; get write char\r
+         mov ah, 15                    ;;  and white colour\r
+         stosw                         ;; write to screen at ES:EDI\r
+         inc fanIndex                  ;; update next index\r
+         and fanIndex, 3\r
+         pop bx\r
+         pop es\r
+ENDM\r
+\r
+;------------------------------------------------------------------------\r
+;\r
+; This macro return ES:DI to tail of Rx queue\r
+\r
+ENQUEUE  MACRO\r
+         LOCAL @noWrap\r
+         mov ax, _rxInOfs              ;; DI = current in-offset\r
+         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer\r
+         cmp ax, LAST_OFS              ;; pointing past last ?\r
+         jb  @noWrap                   ;; no - jump\r
+         lea ax, _pktRxBuf             ;; yes, point to 1st buffer\r
+         align 4\r
+@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?\r
+         je  @dump                     ;; yes, queue is full\r
+         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input\r
+         mov newInOffset, ax           ;; remember new input offset\r
+\r
+   ;; NOTE. rxInOfs is updated after the packet has been copied\r
+   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver\r
+\r
+ENDM\r
+\r
+;------------------------------------------------------------------------\r
+;\r
+; This routine gets called by the packet driver twice:\r
+;   1st time (AX=0) it requests an address where to put the packet\r
+;\r
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)\r
+;   BX has client handle (stored in RX_ELEMENT.handle).\r
+;   CX has # of bytes in packet on both call. They should be equal.\r
+;\r
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount\r
+; and _pktRxBuf[n].secondCount, and CL on first call in\r
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"\r
+; (PKTDRVR.C)\r
+;\r
+;---------------------------------------------------------------------\r
+\r
+_PktReceiver:\r
+         pushf\r
+         cli                         ; no distraction wanted !\r
+         push ds\r
+         push bx\r
+ifdef DOSX\r
+         mov bx, cs\r
+else\r
+         mov bx, SEG _DATA\r
+endif\r
+         mov ds, bx\r
+         mov es, bx                  ; ES = DS = CS or seg _DATA\r
+         pop bx                      ; restore handle\r
+\r
+         cmp ax, 0                   ; first call? (AX=0)\r
+         jne @post                   ; AX=1: second call, do post process\r
+\r
+ifdef DEBUG\r
+         SHOW_RX                     ; show that a packet is received\r
+endif\r
+         cmp cx, RX_BUF_SIZE+14      ; size OK ?\r
+         ja  @skip                   ; no, packet to large for us\r
+\r
+         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]\r
+\r
+         mov [di].firstCount, cx     ; remember the first count.\r
+         mov [di].handle, bx         ; remember the handle.\r
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr\r
+         pop ds\r
+         popf\r
+         retf                        ; far return to driver with ES:DI\r
+\r
+         align 4\r
+@dump:   inc _pktDrop[0]             ; discard the packet on 1st call\r
+         adc _pktDrop[2], 0          ; increment packets lost\r
+\r
+@skip:   xor di, di                  ; return ES:DI = NIL pointer\r
+         xor ax, ax\r
+         mov es, ax\r
+         pop ds\r
+         popf\r
+         retf\r
+\r
+         align 4\r
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr\r
+         jz @discard                 ; make sure we don't use NULL-pointer\r
+\r
+         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr\r
+       ;\r
+       ; push si\r
+       ; push [si].firstCount\r
+       ; call bpf_filter_match       ; run the filter here some day?\r
+       ; add sp, 4\r
+       ; cmp ax, 0\r
+       ; je  @discard\r
+\r
+         mov [si].secondCount, cx\r
+         mov ax, newInOffset\r
+         mov _rxInOfs, ax            ; update _pktRxBuf input offset\r
+\r
+         align 4\r
+@discard:pop ds\r
+         popf\r
+         retf\r
+\r
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data\r
+\r
+_TEXT ENDS\r
+\r
+END\r
diff --git a/msdos/pkt_rx1.s b/msdos/pkt_rx1.s
new file mode 100644 (file)
index 0000000..b294a36
--- /dev/null
@@ -0,0 +1,155 @@
+;\r
+; This file requires NASM 0.97+ to assemble\r
+;\r
+; Currently used only for djgpp + DOS4GW targets\r
+;\r
+; these sizes MUST be equal to the sizes in PKTDRVR.H\r
+;\r
+%define  ETH_MTU     1500                  ; max data size on Ethernet\r
+%define  ETH_MIN     60                    ; min/max total frame size\r
+%define  ETH_MAX     (ETH_MTU+2*6+2)\r
+%define  NUM_RX_BUF  32                    ; # of RX element buffers\r
+%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6\r
+%idefine offset\r
+\r
+struc RX_ELEMENT\r
+      .firstCount  resw 1                  ; # of bytes on 1st call\r
+      .secondCount resw 1                  ; # of bytes on 2nd call\r
+      .handle      resw 1                  ; handle for upcall\r
+    ; .timeStamp   resw 4                  ; 64-bit RDTSC value\r
+      .destinAdr   resb 6                  ; packet destination address\r
+      .sourceAdr   resb 6                  ; packet source address\r
+      .protocol    resw 1                  ; packet protocol number\r
+      .rxBuffer    resb ETH_MTU            ; RX buffer\r
+endstruc\r
+\r
+;-------------------------------------------\r
+\r
+[org 0]  ; assemble to .bin file\r
+\r
+_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets\r
+_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf\r
+_pktDrop    dw   0,0                       ; packet drop counter\r
+_pktTemp    resb 20                        ; temp work area\r
+_pktTxBuf   resb (ETH_MAX)                 ; TX buffer\r
+_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures\r
+ LAST_OFS   equ  $\r
+\r
+screenSeg   dw  0B800h\r
+newInOffset dw  0\r
+\r
+fanChars    db  '-\|/'\r
+fanIndex    dw  0\r
+\r
+%macro SHOW_RX 0\r
+       push es\r
+       push bx\r
+       mov bx, [screenSeg]\r
+       mov es, bx                    ;; r-mode segment of colour screen\r
+       mov di, 158                   ;; upper right corner - 1\r
+       mov bx, [fanIndex]\r
+       mov al, [fanChars+bx]         ;; get write char\r
+       mov ah, 15                    ;;  and white colour\r
+       cld                           ;; Needed?\r
+       stosw                         ;; write to screen at ES:EDI\r
+       inc word [fanIndex]           ;; update next index\r
+       and word [fanIndex], 3\r
+       pop bx\r
+       pop es\r
+%endmacro\r
+\r
+;PutTimeStamp\r
+;       rdtsc\r
+;       mov [si].timeStamp, eax\r
+;       mov [si+4].timeStamp, edx\r
+;       ret\r
+\r
+\r
+;------------------------------------------------------------------------\r
+;\r
+; This routine gets called by the packet driver twice:\r
+;   1st time (AX=0) it requests an address where to put the packet\r
+;\r
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)\r
+;   BX has client handle (stored in RX_ELEMENT.handle).\r
+;   CX has # of bytes in packet on both call. They should be equal.\r
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount\r
+; and _pktRxBuf[n].secondCount, and CL on first call in\r
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"\r
+; (PKTDRVR.C)\r
+;\r
+;---------------------------------------------------------------------\r
+\r
+_PktReceiver:\r
+         pushf\r
+         cli                         ; no distraction wanted !\r
+         push ds\r
+         push bx\r
+         mov bx, cs\r
+         mov ds, bx\r
+         mov es, bx                  ; ES = DS = CS or seg _DATA\r
+         pop bx                      ; restore handle\r
+\r
+         cmp ax, 0                   ; first call? (AX=0)\r
+         jne @post                   ; AX=1: second call, do post process\r
+\r
+%ifdef DEBUG\r
+         SHOW_RX                     ; show that a packet is received\r
+%endif\r
+\r
+         cmp cx, ETH_MAX             ; size OK ?\r
+         ja  @skip                   ; no, too big\r
+\r
+         mov ax, [_rxInOfs]\r
+         add ax, RX_SIZE\r
+         cmp ax, LAST_OFS\r
+         jb  @noWrap\r
+         mov ax, offset _pktRxBuf\r
+@noWrap:\r
+         cmp ax, [_rxOutOfs]\r
+         je  @dump\r
+         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]\r
+         mov [newInOffset], ax\r
+\r
+         mov [di], cx                ; remember firstCount.\r
+         mov [di+4], bx              ; remember handle.\r
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr\r
+         pop ds\r
+         popf\r
+         retf                        ; far return to driver with ES:DI\r
+\r
+@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call\r
+         adc word [_pktDrop+2], 0    ; increment packets lost\r
+\r
+@skip:   xor di, di                  ; return ES:DI = NIL pointer\r
+         xor ax, ax\r
+         mov es, ax\r
+         pop ds\r
+         popf\r
+         retf\r
+\r
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr\r
+         jz @discard                 ; make sure we don't use NULL-pointer\r
+\r
+       ;\r
+       ; push si\r
+       ; call bpf_filter_match       ; run the filter here some day\r
+       ; pop si\r
+       ; cmp ax, 0\r
+       ; je  @discard\r
+\r
+         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount\r
+         mov ax, [newInOffset]\r
+         mov [_rxInOfs], ax          ; update _pktRxBuf input offset\r
+\r
+       ; call PutTimeStamp\r
+\r
+@discard:\r
+         pop ds\r
+         popf\r
+         retf\r
+\r
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data\r
+\r
+END\r
+\r
diff --git a/msdos/pktdrvr.c b/msdos/pktdrvr.c
new file mode 100644 (file)
index 0000000..cd22ee6
--- /dev/null
@@ -0,0 +1,1436 @@
+/*\r
+ *  File.........: pktdrvr.c\r
+ *\r
+ *  Responsible..: Gisle Vanem,  giva@bgnett.no\r
+ *\r
+ *  Created......: 26.Sept 1995\r
+ *\r
+ *  Description..: Packet-driver interface for 16/32-bit C :\r
+ *                 Borland C/C++ 3.0+ small/large model\r
+ *                 Watcom C/C++ 11+, DOS4GW flat model\r
+ *                 Metaware HighC 3.1+ and PharLap 386|DosX\r
+ *                 GNU C/C++ 2.7+ and djgpp 2.x extender\r
+ *\r
+ *  References...: PC/TCP Packet driver Specification. rev 1.09\r
+ *                 FTP Software Inc.\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <dos.h>\r
+\r
+#include "pcap-dos.h"\r
+#include "pcap-int.h"\r
+#include "msdos/pktdrvr.h"\r
+\r
+#if (DOSX)\r
+#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */\r
+#else\r
+#define NUM_RX_BUF  10\r
+#endif\r
+\r
+#define DIM(x)   (sizeof((x)) / sizeof(x[0]))\r
+#define PUTS(s)  do {                                           \\r
+                   if (!pktInfo.quiet)                          \\r
+                      pktInfo.error ?                           \\r
+                        printf ("%s: %s\n", s, pktInfo.error) : \\r
+                        printf ("%s\n", pktInfo.error = s);     \\r
+                 } while (0)\r
+\r
+#if defined(__HIGHC__)\r
+  extern UINT _mwenv;\r
+\r
+#elif defined(__DJGPP__)\r
+  #include <stddef.h>\r
+  #include <dpmi.h>\r
+  #include <go32.h>\r
+  #include <pc.h>\r
+  #include <sys/farptr.h>\r
+\r
+#elif defined(__WATCOMC__)\r
+  #include <i86.h>\r
+  #include <stddef.h>\r
+  extern char _Extender;\r
+\r
+#else\r
+  extern void far PktReceiver (void);\r
+#endif\r
+\r
+\r
+#if (DOSX & (DJGPP|DOS4GW))\r
+  #include <sys/pack_on.h>\r
+\r
+  struct DPMI_regs {\r
+         DWORD  r_di;\r
+         DWORD  r_si;\r
+         DWORD  r_bp;\r
+         DWORD  reserved;\r
+         DWORD  r_bx;\r
+         DWORD  r_dx;\r
+         DWORD  r_cx;\r
+         DWORD  r_ax;\r
+         WORD   r_flags;\r
+         WORD   r_es, r_ds, r_fs, r_gs;\r
+         WORD   r_ip, r_cs, r_sp, r_ss;\r
+       };\r
+\r
+  /* Data located in a real-mode segment. This becomes far at runtime\r
+   */\r
+  typedef struct  {          /* must match data/code in pkt_rx1.s */\r
+          WORD       _rxOutOfs;\r
+          WORD       _rxInOfs;\r
+          DWORD      _pktDrop;\r
+          BYTE       _pktTemp [20];\r
+          TX_ELEMENT _pktTxBuf[1];\r
+          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];\r
+          WORD       _dummy[2];        /* screenSeg,newInOffset */\r
+          BYTE       _fanChars[4];\r
+          WORD       _fanIndex;\r
+          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */\r
+        } PktRealStub;\r
+  #include <sys/pack_off.h>\r
+\r
+  static BYTE real_stub_array [] = {\r
+         #include "pkt_stub.inc"       /* generated opcode array */\r
+       };\r
+\r
+  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)\r
+  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)\r
+  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])\r
+  #define pktDrop       offsetof (PktRealStub,_pktDrop)\r
+  #define pktTemp       offsetof (PktRealStub,_pktTemp)\r
+  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)\r
+  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])\r
+  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])\r
+\r
+#else\r
+  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */\r
+  extern WORD       rxInOfs;\r
+  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */\r
+  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */\r
+\r
+  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */\r
+  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */\r
+  extern char       pktTemp[20];                 /* PktDrvr temp area  */\r
+\r
+  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]\r
+  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]\r
+#endif\r
+\r
+\r
+#ifdef __BORLANDC__           /* Use Borland's inline functions */\r
+  #define memcpy  __memcpy__\r
+  #define memcmp  __memcmp__\r
+  #define memset  __memset__\r
+#endif\r
+\r
+\r
+#if (DOSX & PHARLAP)\r
+  extern void PktReceiver (void);     /* in pkt_rx0.asm */\r
+  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);\r
+\r
+  #undef  FP_SEG\r
+  #undef  FP_OFF\r
+  #define FP_OFF(x)     ((WORD)(x))\r
+  #define FP_SEG(x)     ((WORD)(realBase >> 16))\r
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))\r
+  #define r_ax          eax\r
+  #define r_bx          ebx\r
+  #define r_dx          edx\r
+  #define r_cx          ecx\r
+  #define r_si          esi\r
+  #define r_di          edi\r
+  #define r_ds          ds\r
+  #define r_es          es\r
+  LOCAL FARPTR          protBase;\r
+  LOCAL REALPTR         realBase;\r
+  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */\r
+  LOCAL SWI_REGS        reg;\r
+\r
+  static WORD _far *rxOutOfsFp, *rxInOfsFp;\r
+\r
+#elif (DOSX & DJGPP)\r
+  static _go32_dpmi_seginfo rm_mem;\r
+  static __dpmi_regs        reg;\r
+  static DWORD              realBase;\r
+  static int                para_skip = 0;\r
+\r
+  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))\r
+  #define r_ax              x.ax\r
+  #define r_bx              x.bx\r
+  #define r_dx              x.dx\r
+  #define r_cx              x.cx\r
+  #define r_si              x.si\r
+  #define r_di              x.di\r
+  #define r_ds              x.ds\r
+  #define r_es              x.es\r
+\r
+#elif (DOSX & DOS4GW)\r
+  LOCAL struct DPMI_regs    reg;\r
+  LOCAL WORD                rm_base_seg, rm_base_sel;\r
+  LOCAL DWORD               realBase;\r
+  LOCAL int                 para_skip = 0;\r
+\r
+  LOCAL DWORD dpmi_get_real_vector (int intr);\r
+  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);\r
+  LOCAL void  dpmi_real_free       (WORD selector);\r
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))\r
+\r
+#else              /* real-mode Borland etc. */\r
+  static struct  {\r
+         WORD r_ax, r_bx, r_cx, r_dx, r_bp;\r
+         WORD r_si, r_di, r_ds, r_es, r_flags;\r
+       } reg;\r
+#endif\r
+\r
+#ifdef __HIGHC__\r
+  #pragma Alias (pktDrop,    "_pktDrop")\r
+  #pragma Alias (pktRxBuf,   "_pktRxBuf")\r
+  #pragma Alias (pktTxBuf,   "_pktTxBuf")\r
+  #pragma Alias (pktTemp,    "_pktTemp")\r
+  #pragma Alias (rxOutOfs,   "_rxOutOfs")\r
+  #pragma Alias (rxInOfs,    "_rxInOfs")\r
+  #pragma Alias (pktRxEnd,   "_pktRxEnd")\r
+  #pragma Alias (PktReceiver,"_PktReceiver")\r
+#endif\r
+\r
+\r
+PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */\r
+PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */\r
+\r
+PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;\r
+PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };\r
+PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };\r
+\r
+LOCAL  struct {             /* internal statistics */\r
+       DWORD  tooSmall;     /* size < ETH_MIN */\r
+       DWORD  tooLarge;     /* size > ETH_MAX */\r
+       DWORD  badSync;      /* count_1 != count_2 */\r
+       DWORD  wrongHandle;  /* upcall to wrong handle */\r
+     } intStat;  \r
+\r
+/***************************************************************************/\r
+\r
+PUBLIC const char *PktGetErrorStr (int errNum)\r
+{\r
+  static const char *errStr[] = {\r
+                    "",\r
+                    "Invalid handle number",\r
+                    "No interfaces of specified class found",\r
+                    "No interfaces of specified type found",\r
+                    "No interfaces of specified number found",\r
+                    "Bad packet type specified",\r
+                    "Interface does not support multicast",\r
+                    "Packet driver cannot terminate",\r
+                    "Invalid receiver mode specified",\r
+                    "Insufficient memory space",\r
+                    "Type previously accessed, and not released",\r
+                    "Command out of range, or not implemented",\r
+                    "Cannot send packet (usually hardware error)",\r
+                    "Cannot change hardware address ( > 1 handle open)",\r
+                    "Hardware address has bad length or format",\r
+                    "Cannot reset interface (more than 1 handle open)",\r
+                    "Bad Check-sum",\r
+                    "Bad size",\r
+                    "Bad sync" ,\r
+                    "Source hit"\r
+                  };\r
+\r
+  if (errNum < 0 || errNum >= DIM(errStr))\r
+     return ("Unknown driver error.");\r
+  return (errStr [errNum]);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC const char *PktGetClassName (WORD class)\r
+{\r
+  switch (class)\r
+  { \r
+    case PD_ETHER:\r
+         return ("DIX-Ether");\r
+    case PD_PRONET10:\r
+         return ("ProNET-10");\r
+    case PD_IEEE8025:\r
+         return ("IEEE 802.5");\r
+    case PD_OMNINET:\r
+         return ("OmniNet");\r
+    case PD_APPLETALK:\r
+         return ("AppleTalk");\r
+    case PD_SLIP:\r
+         return ("SLIP");\r
+    case PD_STARTLAN:\r
+         return ("StartLAN");\r
+    case PD_ARCNET:\r
+         return ("ArcNet");\r
+    case PD_AX25:\r
+         return ("AX.25");\r
+    case PD_KISS:\r
+         return ("KISS");\r
+    case PD_IEEE8023_2:\r
+         return ("IEEE 802.3 w/802.2 hdr");\r
+    case PD_FDDI8022:\r
+         return ("FDDI w/802.2 hdr");\r
+    case PD_X25:\r
+         return ("X.25");\r
+    case PD_LANstar:\r
+         return ("LANstar");\r
+    case PD_PPP:\r
+         return ("PPP");\r
+    default:\r
+         return ("unknown");\r
+  }\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)\r
+{\r
+  static const char *modeStr [] = {\r
+                    "Receiver turned off",\r
+                    "Receive only directly addressed packets",\r
+                    "Receive direct & broadcast packets",\r
+                    "Receive direct,broadcast and limited multicast packets",\r
+                    "Receive direct,broadcast and all multicast packets",\r
+                    "Receive all packets (promiscuouos mode)"\r
+                  };\r
+\r
+  if (mode > DIM(modeStr))\r
+     return ("??");\r
+  return (modeStr [mode-1]);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+LOCAL __inline BOOL PktInterrupt (void)\r
+{\r
+  BOOL okay;\r
+\r
+#if (DOSX & PHARLAP)\r
+  _dx_real_int ((UINT)pktInfo.intr, &reg);\r
+  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */\r
+\r
+#elif (DOSX & DJGPP)\r
+  __dpmi_int ((int)pktInfo.intr, &reg);\r
+  okay = ((reg.x.flags & 1) == 0);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  union  REGS  r;\r
+  struct SREGS s;\r
+\r
+  memset (&r, 0, sizeof(r));\r
+  segread (&s);\r
+  r.w.ax  = 0x300;\r
+  r.x.ebx = pktInfo.intr;\r
+  r.w.cx  = 0;\r
+  s.es    = FP_SEG (&reg);\r
+  r.x.edi = FP_OFF (&reg);\r
+  reg.r_flags = 0;\r
+  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */\r
+\r
+  int386x (0x31, &r, &r, &s);\r
+  okay = (!r.w.cflag);\r
+\r
+#else\r
+  reg.r_flags = 0;\r
+  intr (pktInfo.intr, (struct REGPACK*)&reg);\r
+  okay = ((reg.r_flags & 1) == 0);\r
+#endif\r
+\r
+  if (okay)\r
+       pktInfo.error = NULL;\r
+  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);\r
+  return (okay);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+/*\r
+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ\r
+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return\r
+ * interrupt number, else return zero in pktInfo.intr\r
+ */\r
+PUBLIC BOOL PktSearchDriver (void)\r
+{\r
+  BYTE intr  = 0x20;\r
+  BOOL found = FALSE;\r
+\r
+  while (!found && intr < 0xFF)\r
+  {\r
+    static char str[12];                 /* 3 + strlen("PKT DRVR") */\r
+    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */\r
+    DWORD  rp;                           /* in interrupt  routine  */\r
+\r
+#if (DOSX & PHARLAP)\r
+    _dx_rmiv_get (intr, &rp);\r
+    ReadRealMem (&str, (REALPTR)rp, sizeof(str));\r
+\r
+#elif (DOSX & DJGPP)\r
+    __dpmi_raddr realAdr;\r
+    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);\r
+    rp = (realAdr.segment << 4) + realAdr.offset16;\r
+    dosmemget (rp, sizeof(str), &str);\r
+\r
+#elif (DOSX & DOS4GW)\r
+    rp = dpmi_get_real_vector (intr);\r
+    memcpy (&str, (void*)rp, sizeof(str));\r
+\r
+#else\r
+    _fmemcpy (&str, getvect(intr), sizeof(str));\r
+#endif\r
+\r
+    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;\r
+    intr++;\r
+  }\r
+  pktInfo.intr = (found ? intr-1 : 0);\r
+  return (found);\r
+}\r
+\r
+\r
+/**************************************************************************/\r
+\r
+static BOOL PktSetAccess (void)\r
+{\r
+  reg.r_ax = 0x0200 + pktInfo.class;\r
+  reg.r_bx = 0xFFFF;\r
+  reg.r_dx = 0;\r
+  reg.r_cx = 0;\r
+\r
+#if (DOSX & PHARLAP)\r
+  reg.ds  = 0;\r
+  reg.esi = 0;\r
+  reg.es  = RP_SEG (realBase);\r
+  reg.edi = (WORD) &PktReceiver;\r
+\r
+#elif (DOSX & DJGPP)\r
+  reg.x.ds = 0;\r
+  reg.x.si = 0;\r
+  reg.x.es = rm_mem.rm_segment;\r
+  reg.x.di = PktReceiver;\r
+\r
+#elif (DOSX & DOS4GW)\r
+  reg.r_ds = 0;\r
+  reg.r_si = 0;\r
+  reg.r_es = rm_base_seg;\r
+  reg.r_di = PktReceiver;\r
+\r
+#else\r
+  reg.r_ds = 0;\r
+  reg.r_si = 0;\r
+  reg.r_es = FP_SEG (&PktReceiver);\r
+  reg.r_di = FP_OFF (&PktReceiver);\r
+#endif\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+  pktInfo.handle = reg.r_ax;\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktReleaseHandle (WORD handle)\r
+{\r
+  reg.r_ax = 0x0300;\r
+  reg.r_bx = handle;\r
+  return PktInterrupt();\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktTransmit (const void *eth, int len)\r
+{\r
+  if (len > ETH_MTU)\r
+     return (FALSE);\r
+\r
+  reg.r_ax = 0x0400;             /* Function 4, send pkt */\r
+  reg.r_cx = len;                /* total size of frame  */\r
+\r
+#if (DOSX & DJGPP)\r
+  dosmemput (eth, len, realBase+pktTxBuf);\r
+  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */\r
+  reg.x.si = pktTxBuf;           /* DOS offset to buffer */\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy ((void*)(realBase+pktTxBuf), eth, len);\r
+  reg.r_ds = rm_base_seg;\r
+  reg.r_si = pktTxBuf;\r
+\r
+#elif (DOSX & PHARLAP)\r
+  memcpy (&pktTxBuf, eth, len);\r
+  reg.r_ds = FP_SEG (&pktTxBuf);\r
+  reg.r_si = FP_OFF (&pktTxBuf);\r
+\r
+#else\r
+  reg.r_ds = FP_SEG (eth);\r
+  reg.r_si = FP_OFF (eth);\r
+#endif\r
+\r
+  return PktInterrupt();\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+#if (DOSX & (DJGPP|DOS4GW))\r
+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)\r
+#else\r
+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)\r
+#endif\r
+{\r
+  WORD count_1, count_2;\r
+\r
+  /*\r
+   * We got an upcall to the same RMCB with wrong handle.\r
+   * This can happen if we failed to release handle at program exit\r
+   */\r
+  if (rx->handle != pktInfo.handle)\r
+  {\r
+    pktInfo.error = "Wrong handle";\r
+    intStat.wrongHandle++;\r
+    PktReleaseHandle (rx->handle);\r
+    return (FALSE);\r
+  }\r
+  count_1 = rx->firstCount;\r
+  count_2 = rx->secondCount;\r
+\r
+  if (count_1 != count_2)\r
+  {\r
+    pktInfo.error = "Bad sync";\r
+    intStat.badSync++;\r
+    return (FALSE);\r
+  }\r
+  if (count_1 > ETH_MAX)\r
+  {\r
+    pktInfo.error = "Large esize";\r
+    intStat.tooLarge++;\r
+    return (FALSE);\r
+  }\r
+#if 0\r
+  if (count_1 < ETH_MIN)\r
+  {\r
+    pktInfo.error = "Small esize";\r
+    intStat.tooSmall++;\r
+    return (FALSE);\r
+  }\r
+#endif\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktTerminHandle (WORD handle)\r
+{\r
+  reg.r_ax = 0x0500;\r
+  reg.r_bx = handle;\r
+  return PktInterrupt();\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktResetInterface (WORD handle)\r
+{\r
+  reg.r_ax = 0x0700;\r
+  reg.r_bx = handle;\r
+  return PktInterrupt();\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)\r
+{\r
+  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)\r
+     return (TRUE);\r
+\r
+  reg.r_ax = 0x1400;\r
+  reg.r_bx = pktInfo.handle;\r
+  reg.r_cx = (WORD)mode;\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+  receiveMode = mode;\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)\r
+{\r
+  reg.r_ax = 0x1500;\r
+  reg.r_bx = pktInfo.handle;\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+  *mode = reg.r_ax;\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+static PKT_STAT initialStat;         /* statistics at startup */\r
+static BOOL     resetStat = FALSE;   /* statistics reset ? */\r
+\r
+PUBLIC BOOL PktGetStatistics (WORD handle)\r
+{\r
+  reg.r_ax = 0x1800;\r
+  reg.r_bx = handle;\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+#if (DOSX & PHARLAP)\r
+  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));\r
+\r
+#elif (DOSX & DJGPP)\r
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));\r
+\r
+#else\r
+  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));\r
+#endif\r
+\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktSessStatistics (WORD handle)\r
+{\r
+  if (!PktGetStatistics(pktInfo.handle))\r
+     return (FALSE);\r
+\r
+  if (resetStat)\r
+  {\r
+    pktStat.inPackets  -= initialStat.inPackets;\r
+    pktStat.outPackets -= initialStat.outPackets;\r
+    pktStat.inBytes    -= initialStat.inBytes;\r
+    pktStat.outBytes   -= initialStat.outBytes;\r
+    pktStat.inErrors   -= initialStat.inErrors;\r
+    pktStat.outErrors  -= initialStat.outErrors;\r
+    pktStat.outErrors  -= initialStat.outErrors;\r
+    pktStat.lost       -= initialStat.lost;\r
+  }\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktResetStatistics (WORD handle)\r
+{\r
+  if (!PktGetStatistics(pktInfo.handle))\r
+     return (FALSE);\r
+\r
+  memcpy (&initialStat, &pktStat, sizeof(initialStat));\r
+  resetStat = TRUE;\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktGetAddress (ETHER *addr)\r
+{\r
+  reg.r_ax = 0x0600;\r
+  reg.r_bx = pktInfo.handle;\r
+  reg.r_cx = sizeof (*addr);\r
+\r
+#if (DOSX & DJGPP)\r
+  reg.x.es = rm_mem.rm_segment;\r
+  reg.x.di = pktTemp;\r
+#elif (DOSX & DOS4GW)\r
+  reg.r_es = rm_base_seg;\r
+  reg.r_di = pktTemp;\r
+#else\r
+  reg.r_es = FP_SEG (&pktTemp);\r
+  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */\r
+#endif\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+#if (DOSX & PHARLAP)\r
+  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));\r
+\r
+#elif (DOSX & DJGPP)\r
+  dosmemget (realBase+pktTemp, sizeof(*addr), addr);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));\r
+\r
+#else\r
+  memcpy ((void*)addr, &pktTemp, sizeof(*addr));\r
+#endif\r
+\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktSetAddress (const ETHER *addr)\r
+{\r
+  /* copy addr to real-mode scrath area */\r
+\r
+#if (DOSX & PHARLAP)\r
+  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));\r
+\r
+#elif (DOSX & DJGPP)\r
+  dosmemput (addr, sizeof(*addr), realBase+pktTemp);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));\r
+\r
+#else\r
+  memcpy (&pktTemp, (void*)addr, sizeof(*addr));\r
+#endif\r
+\r
+  reg.r_ax = 0x1900;\r
+  reg.r_cx = sizeof (*addr);      /* address length       */\r
+\r
+#if (DOSX & DJGPP)\r
+  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */\r
+  reg.x.di = pktTemp;             /* DOS segment to param */\r
+#elif (DOSX & DOS4GW)\r
+  reg.r_es = rm_base_seg;\r
+  reg.r_di = pktTemp;\r
+#else\r
+  reg.r_es = FP_SEG (&pktTemp);\r
+  reg.r_di = FP_OFF (&pktTemp);\r
+#endif\r
+\r
+  return PktInterrupt();\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktGetDriverInfo (void)\r
+{\r
+  pktInfo.majVer = 0;\r
+  pktInfo.minVer = 0;\r
+  memset (&pktInfo.name, 0, sizeof(pktInfo.name));\r
+  reg.r_ax = 0x01FF;\r
+  reg.r_bx = 0;\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+  pktInfo.number = reg.r_cx & 0xFF;\r
+  pktInfo.class  = reg.r_cx >> 8;\r
+#if 0\r
+  pktInfo.minVer = reg.r_bx % 10;\r
+  pktInfo.majVer = reg.r_bx / 10;\r
+#else\r
+  pktInfo.majVer = reg.r_bx;  // !!\r
+#endif\r
+  pktInfo.funcs  = reg.r_ax & 0xFF;\r
+  pktInfo.type   = reg.r_dx & 0xFF;\r
+\r
+#if (DOSX & PHARLAP)\r
+  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));\r
+\r
+#elif (DOSX & DJGPP)\r
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
+\r
+#else\r
+  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
+#endif\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktGetDriverParam (void)\r
+{\r
+  reg.r_ax = 0x0A00;\r
+\r
+  if (!PktInterrupt())\r
+     return (FALSE);\r
+\r
+#if (DOSX & PHARLAP)\r
+  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);\r
+\r
+#elif (DOSX & DJGPP)\r
+  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
+\r
+#else\r
+  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
+#endif\r
+  return (TRUE);\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+#if (DOSX & PHARLAP)\r
+  PUBLIC int PktReceive (BYTE *buf, int max)\r
+  {\r
+    WORD inOfs  = *rxInOfsFp;\r
+    WORD outOfs = *rxOutOfsFp;\r
+\r
+    if (outOfs != inOfs)\r
+    {\r
+      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);\r
+      int size, len = max;\r
+\r
+      if (CheckElement(head))\r
+      {\r
+        size = min (head->firstCount, sizeof(RX_ELEMENT));\r
+        len  = min (size, max);\r
+        _fmemcpy (buf, &head->destin, len);\r
+      }\r
+      else\r
+        size = -1;\r
+\r
+      outOfs += sizeof (RX_ELEMENT);\r
+      if (outOfs > LAST_RX_BUF)\r
+          outOfs = FIRST_RX_BUF;\r
+      *rxOutOfsFp = outOfs;\r
+      return (size);\r
+    }\r
+    return (0);\r
+  }\r
+\r
+  PUBLIC void PktQueueBusy (BOOL busy)\r
+  {\r
+    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;\r
+    if (*rxOutOfsFp > LAST_RX_BUF)\r
+        *rxOutOfsFp = FIRST_RX_BUF;\r
+    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;\r
+  }\r
+\r
+  PUBLIC WORD PktBuffersUsed (void)\r
+  {\r
+    WORD inOfs  = *rxInOfsFp;\r
+    WORD outOfs = *rxOutOfsFp;\r
+\r
+    if (inOfs >= outOfs)\r
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
+  }\r
+\r
+  PUBLIC DWORD PktRxDropped (void)\r
+  {\r
+    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));\r
+  }\r
+\r
+#elif (DOSX & DJGPP)\r
+  PUBLIC int PktReceive (BYTE *buf, int max)\r
+  {\r
+    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
+\r
+    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))\r
+    {\r
+      RX_ELEMENT head;\r
+      int  size, len = max;\r
+\r
+      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);\r
+      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);\r
+      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);\r
+\r
+      if (CheckElement(&head))\r
+      {\r
+        size = min (head.firstCount, sizeof(RX_ELEMENT));\r
+        len  = min (size, max);\r
+        dosmemget (realBase+ofs+6, len, buf);\r
+      }\r
+      else\r
+        size = -1;\r
+\r
+      ofs += sizeof (RX_ELEMENT);\r
+      if (ofs > LAST_RX_BUF)\r
+           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
+      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
+      return (size);\r
+    }\r
+    return (0);\r
+  }\r
+\r
+  PUBLIC void PktQueueBusy (BOOL busy)\r
+  {\r
+    WORD ofs;\r
+\r
+    disable();\r
+    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);\r
+    if (busy)\r
+       ofs += sizeof (RX_ELEMENT);\r
+\r
+    if (ofs > LAST_RX_BUF)\r
+         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
+    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
+    _farpokel (_dos_ds, realBase+pktDrop, 0UL);\r
+    enable();\r
+  }\r
+\r
+  PUBLIC WORD PktBuffersUsed (void)\r
+  {\r
+    WORD inOfs, outOfs;\r
+\r
+    disable();\r
+    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);\r
+    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
+    enable();\r
+    if (inOfs >= outOfs)\r
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
+  }\r
+\r
+  PUBLIC DWORD PktRxDropped (void)\r
+  {\r
+    return _farpeekl (_dos_ds, realBase+pktDrop);\r
+  }\r
+\r
+#elif (DOSX & DOS4GW)\r
+  PUBLIC int PktReceive (BYTE *buf, int max)\r
+  {\r
+    WORD ofs = *(WORD*) (realBase+rxOutOfs);\r
+\r
+    if (ofs != *(WORD*) (realBase+rxInOfs))\r
+    {\r
+      RX_ELEMENT head;\r
+      int  size, len = max;\r
+\r
+      head.firstCount  = *(WORD*) (realBase+ofs);\r
+      head.secondCount = *(WORD*) (realBase+ofs+2);\r
+      head.handle      = *(WORD*) (realBase+ofs+4);\r
+\r
+      if (CheckElement(&head))\r
+      {\r
+        size = min (head.firstCount, sizeof(RX_ELEMENT));\r
+        len  = min (size, max);\r
+        memcpy (buf, (const void*)(realBase+ofs+6), len);\r
+      }\r
+      else\r
+        size = -1;\r
+\r
+      ofs += sizeof (RX_ELEMENT);\r
+      if (ofs > LAST_RX_BUF)\r
+           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
+      else *(WORD*) (realBase+rxOutOfs) = ofs;\r
+      return (size);\r
+    }\r
+    return (0);\r
+  }\r
+\r
+  PUBLIC void PktQueueBusy (BOOL busy)\r
+  {\r
+    WORD ofs;\r
+\r
+    _disable();\r
+    ofs = *(WORD*) (realBase+rxInOfs);\r
+    if (busy)\r
+       ofs += sizeof (RX_ELEMENT);\r
+\r
+    if (ofs > LAST_RX_BUF)\r
+         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
+    else *(WORD*) (realBase+rxOutOfs) = ofs;\r
+    *(DWORD*) (realBase+pktDrop) = 0UL;\r
+    _enable();\r
+  }\r
+\r
+  PUBLIC WORD PktBuffersUsed (void)\r
+  {\r
+    WORD inOfs, outOfs;\r
+\r
+    _disable();\r
+    inOfs  = *(WORD*) (realBase+rxInOfs);\r
+    outOfs = *(WORD*) (realBase+rxOutOfs);\r
+    _enable();\r
+    if (inOfs >= outOfs)\r
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
+  }\r
+\r
+  PUBLIC DWORD PktRxDropped (void)\r
+  {\r
+    return *(DWORD*) (realBase+pktDrop);\r
+  }\r
+\r
+#else     /* real-mode small/large model */\r
+\r
+  PUBLIC int PktReceive (BYTE *buf, int max)\r
+  {\r
+    if (rxOutOfs != rxInOfs)\r
+    {\r
+      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);\r
+      int  size, len = max;\r
+\r
+      if (CheckElement(head))\r
+      {\r
+        size = min (head->firstCount, sizeof(RX_ELEMENT));\r
+        len  = min (size, max);\r
+        _fmemcpy (buf, &head->destin, len);\r
+      }\r
+      else\r
+        size = -1;\r
+\r
+      rxOutOfs += sizeof (RX_ELEMENT);\r
+      if (rxOutOfs > LAST_RX_BUF)\r
+          rxOutOfs = FIRST_RX_BUF;\r
+      return (size);\r
+    }\r
+    return (0);\r
+  }\r
+\r
+  PUBLIC void PktQueueBusy (BOOL busy)\r
+  {\r
+    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;\r
+    if (rxOutOfs > LAST_RX_BUF)\r
+        rxOutOfs = FIRST_RX_BUF;\r
+    pktDrop = 0L;\r
+  }\r
+\r
+  PUBLIC WORD PktBuffersUsed (void)\r
+  {\r
+    WORD inOfs  = rxInOfs;\r
+    WORD outOfs = rxOutOfs;\r
+\r
+    if (inOfs >= outOfs)\r
+       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));\r
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
+  }\r
+\r
+  PUBLIC DWORD PktRxDropped (void)\r
+  {\r
+    return (pktDrop);\r
+  }\r
+#endif\r
+\r
+/**************************************************************************/\r
+\r
+LOCAL __inline void PktFreeMem (void)\r
+{\r
+#if (DOSX & PHARLAP)\r
+  if (realSeg)\r
+  {\r
+    _dx_real_free (realSeg);\r
+    realSeg = 0;\r
+  }\r
+#elif (DOSX & DJGPP)\r
+  if (rm_mem.rm_segment)\r
+  {\r
+    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */\r
+\r
+    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)\r
+       _farpokel (_dos_ds, realBase + ofs, 0);\r
+    _go32_dpmi_free_dos_memory (&rm_mem);\r
+    rm_mem.rm_segment = 0;\r
+  }\r
+#elif (DOSX & DOS4GW)\r
+  if (rm_base_sel)\r
+  {\r
+    dpmi_real_free (rm_base_sel);\r
+    rm_base_sel = 0;\r
+  }\r
+#endif\r
+}\r
+\r
+/**************************************************************************/\r
+\r
+PUBLIC BOOL PktExitDriver (void)\r
+{           \r
+  if (pktInfo.handle)\r
+  {\r
+    if (!PktSetReceiverMode(PDRX_BROADCAST))\r
+       PUTS ("Error restoring receiver mode.");\r
+\r
+    if (!PktReleaseHandle(pktInfo.handle))\r
+       PUTS ("Error releasing PKT-DRVR handle.");\r
+\r
+    PktFreeMem();\r
+    pktInfo.handle = 0;\r
+  }\r
+\r
+  if (pcap_pkt_debug >= 1)\r
+     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "\r
+             "wrong-handle %lu\n",\r
+             intStat.tooSmall, intStat.tooLarge,\r
+             intStat.badSync, intStat.wrongHandle);\r
+  return (TRUE);\r
+}\r
+\r
+#if (DOSX & (DJGPP|DOS4GW))\r
+static void dump_pkt_stub (void)\r
+{\r
+  int i;\r
+\r
+  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",\r
+           PktReceiver);\r
+  for (i = 0; i < 15; i++)\r
+      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);\r
+  fputs ("\n", stderr);\r
+}\r
+#endif\r
+\r
+/*\r
+ * Front end initialization routine\r
+ */\r
+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)\r
+{\r
+  PKT_RX_MODE rxMode;\r
+  BOOL   writeInfo = (pcap_pkt_debug >= 3);\r
+\r
+  pktInfo.quiet = (pcap_pkt_debug < 3);\r
+\r
+#if (DOSX & PHARLAP) && defined(__HIGHC__)\r
+  if (_mwenv != 2)\r
+  {\r
+    fprintf (stderr, "Only Pharlap DOS extender supported.\n");\r
+    return (FALSE);\r
+  }\r
+#endif\r
+\r
+#if (DOSX & PHARLAP) && defined(__WATCOMC__)\r
+  if (_Extender != 1)\r
+  {\r
+    fprintf (stderr, "Only DOS4GW style extenders supported.\n");\r
+    return (FALSE);\r
+  }\r
+#endif\r
+\r
+  if (!PktSearchDriver())\r
+  {\r
+    PUTS ("Packet driver not found.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+  if (!PktGetDriverInfo())\r
+  {\r
+    PUTS ("Error getting pkt-drvr information.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+#if (DOSX & PHARLAP)\r
+  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,\r
+               &realBase, &protBase, (USHORT*)&realSeg))\r
+  {\r
+    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);\r
+    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);\r
+    *rxOutOfsFp = FIRST_RX_BUF;\r
+    *rxInOfsFp  = FIRST_RX_BUF;\r
+  }\r
+  else\r
+  {\r
+    PUTS ("Cannot allocate real-mode stub.");\r
+    return (FALSE);\r
+  }\r
+\r
+#elif (DOSX & (DJGPP|DOS4GW))\r
+  if (sizeof(real_stub_array) > 0xFFFF)\r
+  {\r
+    fprintf (stderr, "`real_stub_array[]' too big.\n");\r
+    return (FALSE);\r
+  }\r
+#if (DOSX & DJGPP)\r
+  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;\r
+\r
+  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)\r
+  {\r
+    PUTS ("real-mode init failed.");\r
+    return (FALSE);\r
+  }\r
+  realBase = (rm_mem.rm_segment << 4);\r
+  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);\r
+  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
+  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);\r
+\r
+#elif (DOSX & DOS4GW)\r
+  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);\r
+  if (!rm_base_seg)\r
+  {\r
+    PUTS ("real-mode init failed.");\r
+    return (FALSE);\r
+  }\r
+  realBase = (rm_base_seg << 4);\r
+  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));\r
+  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
+  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;\r
+\r
+#endif\r
+  {\r
+    int pushf = PktReceiver;\r
+\r
+    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */\r
+           real_stub_array[pushf]   != 0xFA)      /* cli   */\r
+    {\r
+      if (++para_skip > 16)\r
+      {\r
+        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");\r
+        para_skip = 0;\r
+        dump_pkt_stub();\r
+        return (FALSE);\r
+      }\r
+    }\r
+    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)\r
+    {\r
+      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");\r
+      return (FALSE);\r
+    }\r
+  }\r
+\r
+  if (pcap_pkt_debug > 2)\r
+      dump_pkt_stub();\r
+\r
+#else\r
+  rxOutOfs = FIRST_RX_BUF;\r
+  rxInOfs  = FIRST_RX_BUF;\r
+#endif\r
+\r
+  if (!PktSetAccess())\r
+  {\r
+    PUTS ("Error setting pkt-drvr access.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+  if (!PktGetAddress(&myAddress))\r
+  {\r
+    PUTS ("Error fetching adapter address.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+  if (!PktSetReceiverMode(mode))\r
+  {\r
+    PUTS ("Error setting receiver mode.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+  if (!PktGetReceiverMode(&rxMode))\r
+  {\r
+    PUTS ("Error getting receiver mode.");\r
+    PktFreeMem();\r
+    return (FALSE);\r
+  }\r
+\r
+  if (writeInfo)\r
+     printf ("Pkt-driver information:\n"\r
+             "  Version  : %d.%d\n"\r
+             "  Name     : %.15s\n"\r
+             "  Class    : %u (%s)\n"\r
+             "  Type     : %u\n"\r
+             "  Number   : %u\n"\r
+             "  Funcs    : %u\n"\r
+             "  Intr     : %Xh\n"\r
+             "  Handle   : %u\n"\r
+             "  Extended : %s\n"\r
+             "  Hi-perf  : %s\n"\r
+             "  RX mode  : %s\n"\r
+             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",\r
+\r
+             pktInfo.majVer, pktInfo.minVer, pktInfo.name,\r
+             pktInfo.class,  PktGetClassName(pktInfo.class),\r
+             pktInfo.type,   pktInfo.number,\r
+             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,\r
+             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",\r
+             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",\r
+             PktRXmodeStr(rxMode),\r
+             myAddress[0], myAddress[1], myAddress[2],\r
+             myAddress[3], myAddress[4], myAddress[5]);\r
+\r
+#if defined(DEBUG) && (DOSX & PHARLAP)\r
+  if (writeInfo)\r
+  {\r
+    DWORD    rAdr = realBase + (WORD)&PktReceiver;\r
+    unsigned sel, ofs;\r
+\r
+    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));\r
+    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));\r
+\r
+    sel = _FP_SEG (protBase);\r
+    ofs = _FP_OFF (protBase);\r
+    printf ("Protbase    = %04X:%08X\n", sel,ofs);\r
+    printf ("RealSeg     = %04X\n", realSeg);\r
+\r
+    sel = _FP_SEG (rxOutOfsFp);\r
+    ofs = _FP_OFF (rxOutOfsFp);\r
+    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);\r
+\r
+    sel = _FP_SEG (rxInOfsFp);\r
+    ofs = _FP_OFF (rxInOfsFp);\r
+    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);\r
+\r
+    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
+            *rxOutOfsFp, *rxInOfsFp);\r
+\r
+    PktQueueBusy (TRUE);\r
+    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
+            *rxOutOfsFp, *rxInOfsFp);\r
+  }\r
+#endif\r
+\r
+  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */\r
+  PktQueueBusy (TRUE);\r
+  return (TRUE);\r
+}\r
+\r
+\r
+/*\r
+ * DPMI functions only for Watcom + DOS4GW extenders\r
+ */\r
+#if (DOSX & DOS4GW)\r
+LOCAL DWORD dpmi_get_real_vector (int intr)\r
+{\r
+  union REGS r;\r
+\r
+  r.x.eax = 0x200;\r
+  r.x.ebx = (DWORD) intr;\r
+  int386 (0x31, &r, &r);\r
+  return ((r.w.cx << 4) + r.w.dx);\r
+}\r
+\r
+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)\r
+{\r
+  union REGS r;\r
+\r
+  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */\r
+  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */\r
+  int386 (0x31, &r, &r);\r
+  if (r.w.cflag & 1)\r
+     return (0);\r
+\r
+  *selector = r.w.dx;\r
+  return (r.w.ax);              /* Return segment address */\r
+}\r
+\r
+LOCAL void dpmi_real_free (WORD selector)\r
+{\r
+  union REGS r;\r
+\r
+  r.x.eax = 0x101;              /* DPMI free DOS memory */\r
+  r.x.ebx = selector;           /* Selector to free */\r
+  int386 (0x31, &r, &r);\r
+}\r
+#endif\r
+\r
+\r
+#if defined(DOSX) && (DOSX & PHARLAP)\r
+/*\r
+ * Description:\r
+ *     This routine allocates conventional memory for the specified block\r
+ *     of code (which must be within the first 64K of the protected mode\r
+ *     program segment) and copies the code to it.\r
+ *\r
+ *     The caller should free up the conventional memory block when it\r
+ *     is done with the conventional memory.\r
+ *\r
+ *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.\r
+ *\r
+ * Calling arguments:\r
+ *     start_offs      start of real mode code in program segment\r
+ *     end_offs        1 byte past end of real mode code in program segment\r
+ *     real_basep      returned;  real mode ptr to use as a base for the\r
+ *                        real mode code (eg, to get the real mode FAR\r
+ *                        addr of a function foo(), take\r
+ *                        real_basep + (ULONG) foo).\r
+ *                        This pointer is constructed such that\r
+ *                        offsets within the real mode segment are\r
+ *                        the same as the link-time offsets in the\r
+ *                        protected mode program segment\r
+ *     prot_basep      returned;  prot mode ptr to use as a base for getting\r
+ *                        to the conventional memory, also constructed\r
+ *                        so that adding the prot mode offset of a\r
+ *                        function or variable to the base gets you a\r
+ *                        ptr to the function or variable in the\r
+ *                        conventional memory block.\r
+ *     rmem_adrp       returned;  real mode para addr of allocated\r
+ *                        conventional memory block, to be used to free\r
+ *                        up the conventional memory when done.  DO NOT\r
+ *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE\r
+ *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT\r
+ *                        CORRECTLY.\r
+ *\r
+ * Returned values:\r
+ *     0      if error\r
+ *     1      if success\r
+ */\r
+int RealCopy (ULONG    start_offs,\r
+              ULONG    end_offs,\r
+              REALPTR *real_basep,\r
+              FARPTR  *prot_basep,\r
+              USHORT  *rmem_adrp)\r
+{\r
+  ULONG   rm_base;    /* base real mode para addr for accessing */\r
+                      /* allocated conventional memory          */\r
+  UCHAR  *source;     /* source pointer for copy                */\r
+  FARPTR  destin;     /* destination pointer for copy           */\r
+  ULONG   len;        /* number of bytes to copy                */\r
+  ULONG   temp;\r
+  USHORT  stemp;\r
+\r
+  /* First check for valid inputs\r
+   */\r
+  if (start_offs >= end_offs || end_offs > 0x10000)\r
+     return (FALSE);\r
+\r
+  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up\r
+   * the real mode pointer easily. Round up end_offs to make sure we allocate\r
+   * enough paragraphs\r
+   */\r
+  start_offs &= ~15;\r
+  end_offs = (15 + (end_offs << 4)) >> 4;\r
+\r
+  /* Allocate the conventional memory for our real mode code.  Remember to\r
+   * round byte count UP to 16-byte paragraph size.  We alloc it\r
+   * above the DOS data buffer so both the DOS data buffer and the appl\r
+   * conventional mem block can still be resized.\r
+   *\r
+   * First just try to alloc it;  if we can't get it, shrink the appl mem\r
+   * block down to the minimum, try to alloc the memory again, then grow the\r
+   * appl mem block back to the maximum.  (Don't try to shrink the DOS data\r
+   * buffer to free conventional memory;  it wouldn't be good for this routine\r
+   * to have the possible side effect of making file I/O run slower.)\r
+   */\r
+  len = ((end_offs - start_offs) + 15) >> 4;\r
+  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
+  {\r
+    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)\r
+       return (FALSE);\r
+\r
+    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
+       *rmem_adrp = 0;\r
+\r
+    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)\r
+    {\r
+      if (*rmem_adrp != 0)\r
+         _dx_real_free (*rmem_adrp);\r
+      return (FALSE);\r
+    }\r
+\r
+    if (*rmem_adrp == 0)\r
+       return (FALSE);\r
+  }\r
+\r
+  /* Construct real mode & protected mode pointers to access the allocated\r
+   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)\r
+   * boundary, because we rounded it down.\r
+   *\r
+   * We make the offsets come out rights by backing off the real mode selector\r
+   * by start_offs.\r
+   */\r
+  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);\r
+  RP_SET (*real_basep, 0, rm_base);\r
+  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);\r
+\r
+  /* Copy the real mode code/data to the allocated memory\r
+   */\r
+  source = (UCHAR *) start_offs;\r
+  destin = *prot_basep;\r
+  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));\r
+  len = end_offs - start_offs;\r
+  WriteFarMem (destin, source, len);\r
+\r
+  return (TRUE);\r
+}\r
+#endif /* DOSX && (DOSX & PHARLAP) */\r
diff --git a/msdos/pktdrvr.h b/msdos/pktdrvr.h
new file mode 100644 (file)
index 0000000..08898ae
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef __PKTDRVR_H\r
+#define __PKTDRVR_H\r
+\r
+#define PUBLIC\r
+#define LOCAL        static\r
+\r
+#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */\r
+#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */\r
+\r
+#ifdef __HIGHC__\r
+#pragma Off(Align_members)\r
+#else\r
+#pragma pack(1)\r
+#endif\r
+\r
+typedef enum  {                /* Packet-driver classes */\r
+        PD_ETHER      = 1,\r
+        PD_PRONET10   = 2,\r
+        PD_IEEE8025   = 3,\r
+        PD_OMNINET    = 4,\r
+        PD_APPLETALK  = 5,\r
+        PD_SLIP       = 6,\r
+        PD_STARTLAN   = 7,\r
+        PD_ARCNET     = 8,\r
+        PD_AX25       = 9,\r
+        PD_KISS       = 10,\r
+        PD_IEEE8023_2 = 11,\r
+        PD_FDDI8022   = 12,\r
+        PD_X25        = 13,\r
+        PD_LANstar    = 14,\r
+        PD_PPP        = 18\r
+      } PKT_CLASS;\r
+\r
+typedef enum  {             /* Packet-driver receive modes    */\r
+        PDRX_OFF    = 1,    /* turn off receiver              */\r
+        PDRX_DIRECT,        /* receive only to this interface */\r
+        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */\r
+        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */\r
+        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */\r
+        PDRX_ALL_PACKETS,   /* receive all packets on network */\r
+      } PKT_RX_MODE;\r
+\r
+typedef struct {\r
+        char type[8];\r
+        char len;\r
+      } PKT_FRAME;\r
+\r
+\r
+typedef struct {\r
+        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */\r
+        BYTE  number;       /* = 0 for single LAN adapter        */\r
+        WORD  type;         /* = 13 for 3C523                    */\r
+        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */\r
+        WORD  intr;         /* user interrupt vector number      */\r
+        WORD  handle;       /* Handle associated with session    */\r
+        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/\r
+        BOOL  quiet;        /* (don't) print errors to stdout    */\r
+        const char *error;  /* address of error string           */\r
+        BYTE  majVer;       /* Major driver implementation ver.  */\r
+        BYTE  minVer;       /* Minor driver implementation ver.  */\r
+        BYTE  dummyLen;     /* length of following data          */\r
+        WORD  MAClength;    /* HiPerformance data, N/A           */\r
+        WORD  MTU;          /* HiPerformance data, N/A           */\r
+        WORD  multicast;    /* HiPerformance data, N/A           */\r
+        WORD  rcvrBuffers;  /* valid for                         */\r
+        WORD  UMTbufs;      /*   High Performance drivers only   */\r
+        WORD  postEOIintr;  /*                  Usage ??         */\r
+      } PKT_INFO;\r
+\r
+#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */\r
+\r
+\r
+typedef struct {\r
+        DWORD inPackets;          /* # of packets received    */\r
+        DWORD outPackets;         /* # of packets transmitted */\r
+        DWORD inBytes;            /* # of bytes received      */\r
+        DWORD outBytes;           /* # of bytes transmitted   */\r
+        DWORD inErrors;           /* # of reception errors    */\r
+        DWORD outErrors;          /* # of transmission errors */\r
+        DWORD lost;               /* # of packets lost (RX)   */\r
+      } PKT_STAT;\r
+                   \r
+\r
+typedef struct {\r
+        ETHER destin;\r
+        ETHER source;\r
+        WORD  proto;\r
+        BYTE  data [TX_BUF_SIZE];\r
+      } TX_ELEMENT;\r
+\r
+typedef struct {\r
+        WORD  firstCount;         /* # of bytes on 1st         */\r
+        WORD  secondCount;        /* and 2nd upcall            */\r
+        WORD  handle;             /* instance that upcalled    */\r
+        ETHER destin;             /* E-net destination address */\r
+        ETHER source;             /* E-net source address      */\r
+        WORD  proto;              /* protocol number           */\r
+        BYTE  data [RX_BUF_SIZE];\r
+      } RX_ELEMENT;\r
+\r
+\r
+#ifdef __HIGHC__\r
+#pragma pop(Align_members)\r
+#else\r
+#pragma pack()\r
+#endif\r
+\r
+\r
+/*\r
+ * Prototypes for publics\r
+ */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+extern PKT_STAT    pktStat;     /* statistics for packets */\r
+extern PKT_INFO    pktInfo;     /* packet-driver information */\r
+\r
+extern PKT_RX_MODE receiveMode;\r
+extern ETHER       myAddress, ethBroadcast;\r
+\r
+extern BOOL  PktInitDriver (PKT_RX_MODE mode);\r
+extern BOOL  PktExitDriver (void);\r
+\r
+extern const char *PktGetErrorStr    (int errNum);\r
+extern const char *PktGetClassName   (WORD class);\r
+extern const char *PktRXmodeStr      (PKT_RX_MODE mode);\r
+extern BOOL        PktSearchDriver   (void);\r
+extern int         PktReceive        (BYTE *buf, int max);\r
+extern BOOL        PktTransmit       (const void *eth, int len);\r
+extern DWORD       PktRxDropped      (void);\r
+extern BOOL        PktReleaseHandle  (WORD handle);\r
+extern BOOL        PktTerminHandle   (WORD handle);\r
+extern BOOL        PktResetInterface (WORD handle);\r
+extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);\r
+extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);\r
+extern BOOL        PktGetStatistics  (WORD handle);\r
+extern BOOL        PktSessStatistics (WORD handle);\r
+extern BOOL        PktResetStatistics(WORD handle);\r
+extern BOOL        PktGetAddress     (ETHER *addr);\r
+extern BOOL        PktSetAddress     (const ETHER *addr);\r
+extern BOOL        PktGetDriverInfo  (void);\r
+extern BOOL        PktGetDriverParam (void);\r
+extern void        PktQueueBusy      (BOOL busy);\r
+extern WORD        PktBuffersUsed    (void);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __PKTDRVR_H */\r
+\r
diff --git a/msdos/readme.dos b/msdos/readme.dos
new file mode 100644 (file)
index 0000000..02ef1f7
--- /dev/null
@@ -0,0 +1,162 @@
+@(#) $Header: /tcpdump/master/libpcap/msdos/readme.dos,v 1.3 2004-12-19 19:47:01 guy Exp $ (LBL)
+
+libpcap for DOS
+---------------
+
+This file contains some notes on building and using libpcap for MS-DOS.
+Look in `README' and `pcap.man' for usage and details. These targets are
+supported:
+
+ - Borland C 4.0+ small or large model.
+ - Metaware HighC 3.1+ with PharLap DOS-extender
+ - GNU C 2.7+ with djgpp 2.01+ DOS extender
+ - Watcom C 11.x with DOS4GW extender
+
+Note: the files in the libpcap.zip contains short trucated filenames.
+  So for djgpp to work with these, disable the use of long file names by
+  setting "LFN=n" in the environment.
+
+Files specific to DOS are pcap-dos.[ch] and the assembly and C files in
+the MSDOS sub-directory. Remember to built lipcap libraries from the top
+install directory. And not from the MSDOS sub-directory.
+
+Note for djgpp users:
+  If you got the libpcap from the official site www.tcpdump, then that
+  distribution does NOT contain any sources for building 32-bit drivers.
+  Instead get the full version at
+     http://www.bgnett.no/~giva/pcap/libpcap.zip
+
+  and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
+
+
+
+Requirements
+------------
+
+DOS-libpcap currently only works reliably with a real-mode Ethernet packet-
+driver. This driver must be installed prior to using any program (e.g.
+tcpdump) compiled with libpcap. Work is underway to implement protected-
+mode drivers for 32-bit targets (djgpp only). The 3Com 3c509 driver is
+working almost perfectly. Due to lack of LAN-cards, I've not had the
+opportunity to test other drivers. These 32-bit drivers are modified
+Linux drivers.
+
+
+Required packages
+-----------------
+
+The following packages and tools must be present for all targets.
+
+1. Watt-32 tcp/ip library. This library is *not* used to send or
+   receive network data. It's mostly used to access the 'hosts'
+   file and other <netdb.h> features. Get 'watt32s*.zip' at:
+
+     http://www.bgnett.no/~giva/
+
+2. Exception handler and disassember library (libexc.a) is needed if
+   "USE_EXCEPT = 1" in common.dj. Available at:
+
+     http://www.bgnett.no/~giva/misc/exc_dx07.zip
+
+3. Flex & Bison is used to generate parser for the filter handler
+   pcap_compile:
+
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/flx254b.zip
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsn128b.zip
+
+4. NASM assembler v 0.98 or later is required when building djgpp and
+   Watcom targets:
+
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/nasm098p.zip
+
+5. sed (Stream Editor) is required for doing `make depend'.
+   It's available at
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed*.zip
+
+   A touch tool to update the time-stamp of a file. E.g.
+     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/grep*.zip
+
+6. For djgpp rm.exe and cp.exe are required. These should already be
+   part of your djgpp installation. Also required (experimental at the
+   time) for djgpp is DLX 2.91 or later. This tool is for the generation
+   of dynamically loadable modules.
+
+
+Compiling libpcap
+-----------------
+
+Follow these steps in building libpcap:
+
+1. Make sure you've installed Watt-32 properly (see it's `INSTALL' file).
+   During that installation a environment variable `WATT_ROOT' is set.
+   This variable is used for building libpcap also (`WATT_INC' is
+   deducted from `WATT_ROOT'). djgpp users should also define environment
+   variables `C_INCLUDE_PATH' and `LIBRARY_PATH' to point to the include
+   directory and library directory respectively.  E.g. put this in your
+   AUTOEXEC.BAT:
+     set C_INCLUDE_PATH=c:/net/watt/inc
+     set LIBRARY_PATH=c:/net/watt/lib
+
+2. Revise the msdos/common.dj file for your djgpp/gcc installation;
+   - change the value of `GCCLIB' to match location of libgcc.a.
+   - set `USE_32BIT_DRIVERS = 1' to build 32-bit driver objects.
+
+
+3. Build pcap by using appropriate makefile. For djgpp, use:
+     `make -f msdos/makefile.dj'  (i.e. GNU `make')
+
+   For a Watcom target say:
+     `wmake -f msdos\makefile.wc'
+
+   For a Borland target say:
+     `maker -f msdos\Makefile pcap_bc.lib'  (Borland's `maker.exe')
+
+   And for a HighC/Pharlap target say:
+     `maker -f msdos\Makefile pcap_hc.lib'  (Borland's `maker.exe')
+
+   You might like to change some `CFLAGS' -- only `DEBUG' define currently
+   have any effect. It shows a rotating "fan" in upper right corner of
+   screen.  Remove `DEBUG' if you don't like it. You could add
+   `-fomit-frame-pointer' to `CFLAGS' to speed up the generated code.
+   But note, this makes debugging and crash-traceback difficult. Only
+   add it if you're fully confident your application is 100% stable.
+
+   Note: Code in `USE_NDIS2' does not work at the moment.
+
+4. The resulting libraries are put in current directory. There's no
+   test-program for `libpcap'. Linking the library with `tcpdump' is
+   the ultimate test anyway.
+
+
+
+Extensions to libpcap
+---------------------
+
+I've included some extra functions to DOS-libpcap:
+
+  `pcap_config_hook (const char *name, const char *value)' 
+
+    Allows an application to set values of internal libpcap variables.
+    `name' is typically a left-side keyword with an associated `value'
+    that is called from application's configure process (see tcpdump's
+    config.c file). libpcap keeps a set of tables that are searched for
+    a name/value match. Currently only used to set debug-levels and
+    parameters for the 32-bit network drivers.
+
+  `pcap_set_wait (pcap_t *, void (*)(void), int)' :
+
+    Only effective when reading offline traffic from dump-files.
+    Function `pcap_offline_read()' will wait (and optionally yield)
+    before printing next packet. This will simulate the pace the packets
+    where actually recorded.
+
+
+
+Happy sniffing !
+
+
+Gisle Vanem <giva@bgnett.no>
+            <gvanem@broadpark.no>
+
+October 1999, 2004
+
diff --git a/nametoaddr.c b/nametoaddr.c
new file mode 100644 (file)
index 0000000..5835e4d
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (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.
+ *
+ * Name to id translation routines used by the scanner.
+ * These functions are not time critical.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.83 2008-02-06 10:21:30 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef DECNETLIB
+#include <sys/types.h>
+#include <netdnet/dnetdb.h>
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+
+#else /* WIN32 */
+
+#include <sys/param.h>
+#include <sys/types.h>                         /* concession to AIX */
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#endif /* WIN32 */
+
+#ifndef WIN32
+#ifdef HAVE_ETHER_HOSTTON
+/*
+ * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
+ * ether_hostton()?
+ */
+#ifdef HAVE_NETINET_IF_ETHER_H
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
+#include <net/if.h>    /* for "struct ifnet" in "struct arpcom" on Solaris */
+#include <netinet/if_ether.h>
+#endif /* HAVE_NETINET_IF_ETHER_H */
+#ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+#include <netinet/ether.h>
+#endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
+#endif /* HAVE_ETHER_HOSTTON */
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif /* WIN32 */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef NTOHL
+#define NTOHL(x) (x) = ntohl(x)
+#define NTOHS(x) (x) = ntohs(x)
+#endif
+
+static inline int xdtoi(int);
+
+/*
+ *  Convert host name to internet address.
+ *  Return 0 upon failure.
+ */
+bpf_u_int32 **
+pcap_nametoaddr(const char *name)
+{
+#ifndef h_addr
+       static bpf_u_int32 *hlist[2];
+#endif
+       bpf_u_int32 **p;
+       struct hostent *hp;
+
+       if ((hp = gethostbyname(name)) != NULL) {
+#ifndef h_addr
+               hlist[0] = (bpf_u_int32 *)hp->h_addr;
+               NTOHL(hp->h_addr);
+               return hlist;
+#else
+               for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
+                       NTOHL(**p);
+               return (bpf_u_int32 **)hp->h_addr_list;
+#endif
+       }
+       else
+               return 0;
+}
+
+#ifdef INET6
+struct addrinfo *
+pcap_nametoaddrinfo(const char *name)
+{
+       struct addrinfo hints, *res;
+       int error;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;        /*not really*/
+       hints.ai_protocol = IPPROTO_TCP;        /*not really*/
+       error = getaddrinfo(name, NULL, &hints, &res);
+       if (error)
+               return NULL;
+       else
+               return res;
+}
+#endif /*INET6*/
+
+/*
+ *  Convert net name to internet address.
+ *  Return 0 upon failure.
+ */
+bpf_u_int32
+pcap_nametonetaddr(const char *name)
+{
+#ifndef WIN32
+       struct netent *np;
+
+       if ((np = getnetbyname(name)) != NULL)
+               return np->n_net;
+       else
+               return 0;
+#else
+       /*
+        * There's no "getnetbyname()" on Windows.
+        */
+       return 0;
+#endif
+}
+
+/*
+ * Convert a port name to its port and protocol numbers.
+ * We assume only TCP or UDP.
+ * Return 0 upon failure.
+ */
+int
+pcap_nametoport(const char *name, int *port, int *proto)
+{
+       struct servent *sp;
+       int tcp_port = -1;
+       int udp_port = -1;
+
+       /*
+        * We need to check /etc/services for ambiguous entries.
+        * If we find the ambiguous entry, and it has the
+        * same port number, change the proto to PROTO_UNDEF
+        * so both TCP and UDP will be checked.
+        */
+       sp = getservbyname(name, "tcp");
+       if (sp != NULL) tcp_port = ntohs(sp->s_port);
+       sp = getservbyname(name, "udp");
+       if (sp != NULL) udp_port = ntohs(sp->s_port);
+       if (tcp_port >= 0) {
+               *port = tcp_port;
+               *proto = IPPROTO_TCP;
+               if (udp_port >= 0) {
+                       if (udp_port == tcp_port)
+                               *proto = PROTO_UNDEF;
+#ifdef notdef
+                       else
+                               /* Can't handle ambiguous names that refer
+                                  to different port numbers. */
+                               warning("ambiguous port %s in /etc/services",
+                                       name);
+#endif
+               }
+               return 1;
+       }
+       if (udp_port >= 0) {
+               *port = udp_port;
+               *proto = IPPROTO_UDP;
+               return 1;
+       }
+#if defined(ultrix) || defined(__osf__)
+       /* Special hack in case NFS isn't in /etc/services */
+       if (strcmp(name, "nfs") == 0) {
+               *port = 2049;
+               *proto = PROTO_UNDEF;
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+/*
+ * Convert a string in the form PPP-PPP, where correspond to ports, to
+ * a starting and ending port in a port range.
+ * Return 0 on failure.
+ */
+int
+pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
+{
+       u_int p1, p2;
+       char *off, *cpy;
+       int save_proto;
+
+       if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
+               if ((cpy = strdup(name)) == NULL)
+                       return 0;
+
+               if ((off = strchr(cpy, '-')) == NULL) {
+                       free(cpy);
+                       return 0;
+               }
+
+               *off = '\0';
+
+               if (pcap_nametoport(cpy, port1, proto) == 0) {
+                       free(cpy);
+                       return 0;
+               }
+               save_proto = *proto;
+
+               if (pcap_nametoport(off + 1, port2, proto) == 0) {
+                       free(cpy);
+                       return 0;
+               }
+
+               if (*proto != save_proto)
+                       *proto = PROTO_UNDEF;
+       } else {
+               *port1 = p1;
+               *port2 = p2;
+               *proto = PROTO_UNDEF;
+       }
+
+       return 1;
+}
+
+int
+pcap_nametoproto(const char *str)
+{
+       struct protoent *p;
+
+       p = getprotobyname(str);
+       if (p != 0)
+               return p->p_proto;
+       else
+               return PROTO_UNDEF;
+}
+
+#include "ethertype.h"
+
+struct eproto {
+       const char *s;
+       u_short p;
+};
+
+/* Static data base of ether protocol types. */
+struct eproto eproto_db[] = {
+       { "pup", ETHERTYPE_PUP },
+       { "xns", ETHERTYPE_NS },
+       { "ip", ETHERTYPE_IP },
+#ifdef INET6
+       { "ip6", ETHERTYPE_IPV6 },
+#endif
+       { "arp", ETHERTYPE_ARP },
+       { "rarp", ETHERTYPE_REVARP },
+       { "sprite", ETHERTYPE_SPRITE },
+       { "mopdl", ETHERTYPE_MOPDL },
+       { "moprc", ETHERTYPE_MOPRC },
+       { "decnet", ETHERTYPE_DN },
+       { "lat", ETHERTYPE_LAT },
+       { "sca", ETHERTYPE_SCA },
+       { "lanbridge", ETHERTYPE_LANBRIDGE },
+       { "vexp", ETHERTYPE_VEXP },
+       { "vprod", ETHERTYPE_VPROD },
+       { "atalk", ETHERTYPE_ATALK },
+       { "atalkarp", ETHERTYPE_AARP },
+       { "loopback", ETHERTYPE_LOOPBACK },
+       { "decdts", ETHERTYPE_DECDTS },
+       { "decdns", ETHERTYPE_DECDNS },
+       { (char *)0, 0 }
+};
+
+int
+pcap_nametoeproto(const char *s)
+{
+       struct eproto *p = eproto_db;
+
+       while (p->s != 0) {
+               if (strcmp(p->s, s) == 0)
+                       return p->p;
+               p += 1;
+       }
+       return PROTO_UNDEF;
+}
+
+#include "llc.h"
+
+/* Static data base of LLC values. */
+static struct eproto llc_db[] = {
+       { "iso", LLCSAP_ISONS },
+       { "stp", LLCSAP_8021D },
+       { "ipx", LLCSAP_IPX },
+       { "netbeui", LLCSAP_NETBEUI },
+       { (char *)0, 0 }
+};
+
+int
+pcap_nametollc(const char *s)
+{
+       struct eproto *p = llc_db;
+
+       while (p->s != 0) {
+               if (strcmp(p->s, s) == 0)
+                       return p->p;
+               p += 1;
+       }
+       return PROTO_UNDEF;
+}
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+int
+__pcap_atoin(const char *s, bpf_u_int32 *addr)
+{
+       u_int n;
+       int len;
+
+       *addr = 0;
+       len = 0;
+       while (1) {
+               n = 0;
+               while (*s && *s != '.')
+                       n = n * 10 + *s++ - '0';
+               *addr <<= 8;
+               *addr |= n & 0xff;
+               len += 8;
+               if (*s == '\0')
+                       return len;
+               ++s;
+       }
+       /* NOTREACHED */
+}
+
+int
+__pcap_atodn(const char *s, bpf_u_int32 *addr)
+{
+#define AREASHIFT 10
+#define AREAMASK 0176000
+#define NODEMASK 01777
+
+       u_int node, area;
+
+       if (sscanf(s, "%d.%d", &area, &node) != 2)
+               bpf_error("malformed decnet address '%s'", s);
+
+       *addr = (area << AREASHIFT) & AREAMASK;
+       *addr |= (node & NODEMASK);
+
+       return(32);
+}
+
+/*
+ * Convert 's', which can have the one of the forms:
+ *
+ *     "xx:xx:xx:xx:xx:xx"
+ *     "xx.xx.xx.xx.xx.xx"
+ *     "xx-xx-xx-xx-xx-xx"
+ *     "xxxx.xxxx.xxxx"
+ *     "xxxxxxxxxxxx"
+ *
+ * (or various mixes of ':', '.', and '-') into a new
+ * ethernet address.  Assumes 's' is well formed.
+ */
+u_char *
+pcap_ether_aton(const char *s)
+{
+       register u_char *ep, *e;
+       register u_int d;
+
+       e = ep = (u_char *)malloc(6);
+
+       while (*s) {
+               if (*s == ':' || *s == '.' || *s == '-')
+                       s += 1;
+               d = xdtoi(*s++);
+               if (isxdigit((unsigned char)*s)) {
+                       d <<= 4;
+                       d |= xdtoi(*s++);
+               }
+               *ep++ = d;
+       }
+
+       return (e);
+}
+
+#ifndef HAVE_ETHER_HOSTTON
+/* Roll our own */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+       register struct pcap_etherent *ep;
+       register u_char *ap;
+       static FILE *fp = NULL;
+       static int init = 0;
+
+       if (!init) {
+               fp = fopen(PCAP_ETHERS_FILE, "r");
+               ++init;
+               if (fp == NULL)
+                       return (NULL);
+       } else if (fp == NULL)
+               return (NULL);
+       else
+               rewind(fp);
+
+       while ((ep = pcap_next_etherent(fp)) != NULL) {
+               if (strcmp(ep->name, name) == 0) {
+                       ap = (u_char *)malloc(6);
+                       if (ap != NULL) {
+                               memcpy(ap, ep->addr, 6);
+                               return (ap);
+                       }
+                       break;
+               }
+       }
+       return (NULL);
+}
+#else
+
+#if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON
+#ifndef HAVE_STRUCT_ETHER_ADDR
+struct ether_addr {
+       unsigned char ether_addr_octet[6];
+};
+#endif
+extern int ether_hostton(const char *, struct ether_addr *);
+#endif
+
+/* Use the os supplied routines */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+       register u_char *ap;
+       u_char a[6];
+
+       ap = NULL;
+       if (ether_hostton(name, (struct ether_addr *)a) == 0) {
+               ap = (u_char *)malloc(6);
+               if (ap != NULL)
+                       memcpy((char *)ap, (char *)a, 6);
+       }
+       return (ap);
+}
+#endif
+
+u_short
+__pcap_nametodnaddr(const char *name)
+{
+#ifdef DECNETLIB
+       struct nodeent *getnodebyname();
+       struct nodeent *nep;
+       unsigned short res;
+
+       nep = getnodebyname(name);
+       if (nep == ((struct nodeent *)0))
+               bpf_error("unknown decnet host name '%s'\n", name);
+
+       memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
+       return(res);
+#else
+       bpf_error("decnet name support not included, '%s' cannot be translated\n",
+               name);
+       return(0);
+#endif
+}
diff --git a/nlpid.h b/nlpid.h
new file mode 100644 (file)
index 0000000..5327a36
--- /dev/null
+++ b/nlpid.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996
+ *     Juniper Networks, Inc.  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.  The name of Juniper Networks 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/nlpid.h,v 1.2 2002-12-06 00:01:34 hannes Exp $ (Juniper)
+ */
+
+/* Types missing from some systems */
+
+/*
+ * Network layer prototocol identifiers
+ */
+#ifndef ISO8473_CLNP
+#define ISO8473_CLNP           0x81
+#endif
+#ifndef        ISO9542_ESIS
+#define        ISO9542_ESIS            0x82
+#endif
+#ifndef ISO9542X25_ESIS
+#define ISO9542X25_ESIS                0x8a
+#endif
+#ifndef        ISO10589_ISIS
+#define        ISO10589_ISIS           0x83
+#endif
+/*
+ * this does not really belong in the nlpid.h file
+ * however we need it for generating nice
+ * IS-IS related BPF filters
+ */
+#define ISIS_L1_LAN_IIH      15
+#define ISIS_L2_LAN_IIH      16
+#define ISIS_PTP_IIH         17
+#define ISIS_L1_LSP          18
+#define ISIS_L2_LSP          20
+#define ISIS_L1_CSNP         24
+#define ISIS_L2_CSNP         25
+#define ISIS_L1_PSNP         26
+#define ISIS_L2_PSNP         27
+
+#ifndef ISO8878A_CONS
+#define        ISO8878A_CONS           0x84
+#endif
+#ifndef        ISO10747_IDRP
+#define        ISO10747_IDRP           0x85
+#endif
diff --git a/optimize.c b/optimize.c
new file mode 100644 (file)
index 0000000..6bbda95
--- /dev/null
@@ -0,0 +1,2347 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 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.
+ *
+ *  Optimization module for tcpdump intermediate representation.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.91 2008-01-02 04:16:46 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef BDEBUG
+extern int dflag;
+#endif
+
+#if defined(MSDOS) && !defined(__DJGPP__)
+extern int _w32_ffs (int mask);
+#define ffs _w32_ffs
+#endif
+
+#if defined(WIN32) && defined (_MSC_VER)
+int ffs(int mask);
+#endif
+
+/*
+ * Represents a deleted instruction.
+ */
+#define NOP -1
+
+/*
+ * Register numbers for use-def values.
+ * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory
+ * location.  A_ATOM is the accumulator and X_ATOM is the index
+ * register.
+ */
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+/*
+ * This define is used to represent *both* the accumulator and
+ * x register in use-def computations.
+ * Currently, the use-def code assumes only one definition per instruction.
+ */
+#define AX_ATOM N_ATOMS
+
+/*
+ * A flag to indicate that further optimization is needed.
+ * Iterative passes are continued until a given pass yields no
+ * branch movement.
+ */
+static int done;
+
+/*
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark' is
+ * incremented.  This automatically makes each element unmarked.
+ */
+static int cur_mark;
+#define isMarked(p) ((p)->mark == cur_mark)
+#define unMarkAll() cur_mark += 1
+#define Mark(p) ((p)->mark = cur_mark)
+
+static void opt_init(struct block *);
+static void opt_cleanup(void);
+
+static void make_marks(struct block *);
+static void mark_code(struct block *);
+
+static void intern_blocks(struct block *);
+
+static int eq_slist(struct slist *, struct slist *);
+
+static void find_levels_r(struct block *);
+
+static void find_levels(struct block *);
+static void find_dom(struct block *);
+static void propedom(struct edge *);
+static void find_edom(struct block *);
+static void find_closure(struct block *);
+static int atomuse(struct stmt *);
+static int atomdef(struct stmt *);
+static void compute_local_ud(struct block *);
+static void find_ud(struct block *);
+static void init_val(void);
+static int F(int, int, int);
+static inline void vstore(struct stmt *, int *, int, int);
+static void opt_blk(struct block *, int);
+static int use_conflict(struct block *, struct block *);
+static void opt_j(struct edge *);
+static void or_pullup(struct block *);
+static void and_pullup(struct block *);
+static void opt_blks(struct block *, int);
+static inline void link_inedge(struct edge *, struct block *);
+static void find_inedges(struct block *);
+static void opt_root(struct block **);
+static void opt_loop(struct block *, int);
+static void fold_op(struct stmt *, int, int);
+static inline struct slist *this_op(struct slist *);
+static void opt_not(struct block *);
+static void opt_peep(struct block *);
+static void opt_stmt(struct stmt *, int[], int);
+static void deadstmt(struct stmt *, struct stmt *[]);
+static void opt_deadstores(struct block *);
+static struct block *fold_edge(struct block *, struct edge *);
+static inline int eq_blk(struct block *, struct block *);
+static u_int slength(struct slist *);
+static int count_blocks(struct block *);
+static void number_blks_r(struct block *);
+static u_int count_stmts(struct block *);
+static int convert_code_r(struct block *);
+#ifdef BDEBUG
+static void opt_dump(struct block *);
+#endif
+
+static int n_blocks;
+struct block **blocks;
+static int n_edges;
+struct edge **edges;
+
+/*
+ * A bit vector set representation of the dominators.
+ * We round up the set size to the next power of two.
+ */
+static int nodewords;
+static int edgewords;
+struct block **levels;
+bpf_u_int32 *space;
+#define BITS_PER_WORD (8*sizeof(bpf_u_int32))
+/*
+ * True if a is in uset {p}
+ */
+#define SET_MEMBER(p, a) \
+((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+
+/*
+ * Add 'a' to uset p.
+ */
+#define SET_INSERT(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * Delete 'a' from uset p.
+ */
+#define SET_DELETE(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * a := a intersect b
+ */
+#define SET_INTERSECT(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ &= *_y++;\
+}
+
+/*
+ * a := a - b
+ */
+#define SET_SUBTRACT(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ &=~ *_y++;\
+}
+
+/*
+ * a := a union b
+ */
+#define SET_UNION(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ |= *_y++;\
+}
+
+static uset all_dom_sets;
+static uset all_closure_sets;
+static uset all_edge_sets;
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+static void
+find_levels_r(b)
+       struct block *b;
+{
+       int level;
+
+       if (isMarked(b))
+               return;
+
+       Mark(b);
+       b->link = 0;
+
+       if (JT(b)) {
+               find_levels_r(JT(b));
+               find_levels_r(JF(b));
+               level = MAX(JT(b)->level, JF(b)->level) + 1;
+       } else
+               level = 0;
+       b->level = level;
+       b->link = levels[level];
+       levels[level] = b;
+}
+
+/*
+ * Level graph.  The levels go from 0 at the leaves to
+ * N_LEVELS at the root.  The levels[] array points to the
+ * first node of the level list, whose elements are linked
+ * with the 'link' field of the struct block.
+ */
+static void
+find_levels(root)
+       struct block *root;
+{
+       memset((char *)levels, 0, n_blocks * sizeof(*levels));
+       unMarkAll();
+       find_levels_r(root);
+}
+
+/*
+ * Find dominator relationships.
+ * Assumes graph has been leveled.
+ */
+static void
+find_dom(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+       bpf_u_int32 *x;
+
+       /*
+        * Initialize sets to contain all nodes.
+        */
+       x = all_dom_sets;
+       i = n_blocks * nodewords;
+       while (--i >= 0)
+               *x++ = ~0;
+       /* Root starts off empty. */
+       for (i = nodewords; --i >= 0;)
+               root->dom[i] = 0;
+
+       /* root->level is the highest level no found. */
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b; b = b->link) {
+                       SET_INSERT(b->dom, b->id);
+                       if (JT(b) == 0)
+                               continue;
+                       SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
+                       SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
+               }
+       }
+}
+
+static void
+propedom(ep)
+       struct edge *ep;
+{
+       SET_INSERT(ep->edom, ep->id);
+       if (ep->succ) {
+               SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
+               SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
+       }
+}
+
+/*
+ * Compute edge dominators.
+ * Assumes graph has been leveled and predecessors established.
+ */
+static void
+find_edom(root)
+       struct block *root;
+{
+       int i;
+       uset x;
+       struct block *b;
+
+       x = all_edge_sets;
+       for (i = n_edges * edgewords; --i >= 0; )
+               x[i] = ~0;
+
+       /* root->level is the highest level no found. */
+       memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));
+       memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b != 0; b = b->link) {
+                       propedom(&b->et);
+                       propedom(&b->ef);
+               }
+       }
+}
+
+/*
+ * Find the backwards transitive closure of the flow graph.  These sets
+ * are backwards in the sense that we find the set of nodes that reach
+ * a given node, not the set of nodes that can be reached by a node.
+ *
+ * Assumes graph has been leveled.
+ */
+static void
+find_closure(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+
+       /*
+        * Initialize sets to contain no nodes.
+        */
+       memset((char *)all_closure_sets, 0,
+             n_blocks * nodewords * sizeof(*all_closure_sets));
+
+       /* root->level is the highest level no found. */
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b; b = b->link) {
+                       SET_INSERT(b->closure, b->id);
+                       if (JT(b) == 0)
+                               continue;
+                       SET_UNION(JT(b)->closure, b->closure, nodewords);
+                       SET_UNION(JF(b)->closure, b->closure, nodewords);
+               }
+       }
+}
+
+/*
+ * Return the register number that is used by s.  If A and X are both
+ * used, return AX_ATOM.  If no register is used, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomuse(s)
+       struct stmt *s;
+{
+       register int c = s->code;
+
+       if (c == NOP)
+               return -1;
+
+       switch (BPF_CLASS(c)) {
+
+       case BPF_RET:
+               return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
+                       (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
+
+       case BPF_LD:
+       case BPF_LDX:
+               return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
+                       (BPF_MODE(c) == BPF_MEM) ? s->k : -1;
+
+       case BPF_ST:
+               return A_ATOM;
+
+       case BPF_STX:
+               return X_ATOM;
+
+       case BPF_JMP:
+       case BPF_ALU:
+               if (BPF_SRC(c) == BPF_X)
+                       return AX_ATOM;
+               return A_ATOM;
+
+       case BPF_MISC:
+               return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Return the register number that is defined by 's'.  We assume that
+ * a single stmt cannot define more than one register.  If no register
+ * is defined, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomdef(s)
+       struct stmt *s;
+{
+       if (s->code == NOP)
+               return -1;
+
+       switch (BPF_CLASS(s->code)) {
+
+       case BPF_LD:
+       case BPF_ALU:
+               return A_ATOM;
+
+       case BPF_LDX:
+               return X_ATOM;
+
+       case BPF_ST:
+       case BPF_STX:
+               return s->k;
+
+       case BPF_MISC:
+               return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
+       }
+       return -1;
+}
+
+/*
+ * Compute the sets of registers used, defined, and killed by 'b'.
+ *
+ * "Used" means that a statement in 'b' uses the register before any
+ * statement in 'b' defines it, i.e. it uses the value left in
+ * that register by a predecessor block of this block.
+ * "Defined" means that a statement in 'b' defines it.
+ * "Killed" means that a statement in 'b' defines it before any
+ * statement in 'b' uses it, i.e. it kills the value left in that
+ * register by a predecessor block of this block.
+ */
+static void
+compute_local_ud(b)
+       struct block *b;
+{
+       struct slist *s;
+       atomset def = 0, use = 0, kill = 0;
+       int atom;
+
+       for (s = b->stmts; s; s = s->next) {
+               if (s->s.code == NOP)
+                       continue;
+               atom = atomuse(&s->s);
+               if (atom >= 0) {
+                       if (atom == AX_ATOM) {
+                               if (!ATOMELEM(def, X_ATOM))
+                                       use |= ATOMMASK(X_ATOM);
+                               if (!ATOMELEM(def, A_ATOM))
+                                       use |= ATOMMASK(A_ATOM);
+                       }
+                       else if (atom < N_ATOMS) {
+                               if (!ATOMELEM(def, atom))
+                                       use |= ATOMMASK(atom);
+                       }
+                       else
+                               abort();
+               }
+               atom = atomdef(&s->s);
+               if (atom >= 0) {
+                       if (!ATOMELEM(use, atom))
+                               kill |= ATOMMASK(atom);
+                       def |= ATOMMASK(atom);
+               }
+       }
+       if (BPF_CLASS(b->s.code) == BPF_JMP) {
+               /*
+                * XXX - what about RET?
+                */
+               atom = atomuse(&b->s);
+               if (atom >= 0) {
+                       if (atom == AX_ATOM) {
+                               if (!ATOMELEM(def, X_ATOM))
+                                       use |= ATOMMASK(X_ATOM);
+                               if (!ATOMELEM(def, A_ATOM))
+                                       use |= ATOMMASK(A_ATOM);
+                       }
+                       else if (atom < N_ATOMS) {
+                               if (!ATOMELEM(def, atom))
+                                       use |= ATOMMASK(atom);
+                       }
+                       else
+                               abort();
+               }
+       }
+
+       b->def = def;
+       b->kill = kill;
+       b->in_use = use;
+}
+
+/*
+ * Assume graph is already leveled.
+ */
+static void
+find_ud(root)
+       struct block *root;
+{
+       int i, maxlevel;
+       struct block *p;
+
+       /*
+        * root->level is the highest level no found;
+        * count down from there.
+        */
+       maxlevel = root->level;
+       for (i = maxlevel; i >= 0; --i)
+               for (p = levels[i]; p; p = p->link) {
+                       compute_local_ud(p);
+                       p->out_use = 0;
+               }
+
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       p->out_use |= JT(p)->in_use | JF(p)->in_use;
+                       p->in_use |= p->out_use &~ p->kill;
+               }
+       }
+}
+
+/*
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme.  Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
+ */
+struct valnode {
+       int code;
+       int v0, v1;
+       int val;
+       struct valnode *next;
+};
+
+#define MODULUS 213
+static struct valnode *hashtbl[MODULUS];
+static int curval;
+static int maxval;
+
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
+
+struct vmapinfo {
+       int is_const;
+       bpf_int32 const_val;
+};
+
+struct vmapinfo *vmap;
+struct valnode *vnode_base;
+struct valnode *next_vnode;
+
+static void
+init_val()
+{
+       curval = 0;
+       next_vnode = vnode_base;
+       memset((char *)vmap, 0, maxval * sizeof(*vmap));
+       memset((char *)hashtbl, 0, sizeof hashtbl);
+}
+
+/* Because we really don't have an IR, this stuff is a little messy. */
+static int
+F(code, v0, v1)
+       int code;
+       int v0, v1;
+{
+       u_int hash;
+       int val;
+       struct valnode *p;
+
+       hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
+       hash %= MODULUS;
+
+       for (p = hashtbl[hash]; p; p = p->next)
+               if (p->code == code && p->v0 == v0 && p->v1 == v1)
+                       return p->val;
+
+       val = ++curval;
+       if (BPF_MODE(code) == BPF_IMM &&
+           (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
+               vmap[val].const_val = v0;
+               vmap[val].is_const = 1;
+       }
+       p = next_vnode++;
+       p->val = val;
+       p->code = code;
+       p->v0 = v0;
+       p->v1 = v1;
+       p->next = hashtbl[hash];
+       hashtbl[hash] = p;
+
+       return val;
+}
+
+static inline void
+vstore(s, valp, newval, alter)
+       struct stmt *s;
+       int *valp;
+       int newval;
+       int alter;
+{
+       if (alter && *valp == newval)
+               s->code = NOP;
+       else
+               *valp = newval;
+}
+
+static void
+fold_op(s, v0, v1)
+       struct stmt *s;
+       int v0, v1;
+{
+       bpf_u_int32 a, b;
+
+       a = vmap[v0].const_val;
+       b = vmap[v1].const_val;
+
+       switch (BPF_OP(s->code)) {
+       case BPF_ADD:
+               a += b;
+               break;
+
+       case BPF_SUB:
+               a -= b;
+               break;
+
+       case BPF_MUL:
+               a *= b;
+               break;
+
+       case BPF_DIV:
+               if (b == 0)
+                       bpf_error("division by zero");
+               a /= b;
+               break;
+
+       case BPF_AND:
+               a &= b;
+               break;
+
+       case BPF_OR:
+               a |= b;
+               break;
+
+       case BPF_LSH:
+               a <<= b;
+               break;
+
+       case BPF_RSH:
+               a >>= b;
+               break;
+
+       case BPF_NEG:
+               a = -a;
+               break;
+
+       default:
+               abort();
+       }
+       s->k = a;
+       s->code = BPF_LD|BPF_IMM;
+       done = 0;
+}
+
+static inline struct slist *
+this_op(s)
+       struct slist *s;
+{
+       while (s != 0 && s->s.code == NOP)
+               s = s->next;
+       return s;
+}
+
+static void
+opt_not(b)
+       struct block *b;
+{
+       struct block *tmp = JT(b);
+
+       JT(b) = JF(b);
+       JF(b) = tmp;
+}
+
+static void
+opt_peep(b)
+       struct block *b;
+{
+       struct slist *s;
+       struct slist *next, *last;
+       int val;
+
+       s = b->stmts;
+       if (s == 0)
+               return;
+
+       last = s;
+       for (/*empty*/; /*empty*/; s = next) {
+               /*
+                * Skip over nops.
+                */
+               s = this_op(s);
+               if (s == 0)
+                       break;  /* nothing left in the block */
+
+               /*
+                * Find the next real instruction after that one
+                * (skipping nops).
+                */
+               next = this_op(s->next);
+               if (next == 0)
+                       break;  /* no next instruction */
+               last = next;
+
+               /*
+                * st  M[k]     -->     st  M[k]
+                * ldx M[k]             tax
+                */
+               if (s->s.code == BPF_ST &&
+                   next->s.code == (BPF_LDX|BPF_MEM) &&
+                   s->s.k == next->s.k) {
+                       done = 0;
+                       next->s.code = BPF_MISC|BPF_TAX;
+               }
+               /*
+                * ld  #k       -->     ldx  #k
+                * tax                  txa
+                */
+               if (s->s.code == (BPF_LD|BPF_IMM) &&
+                   next->s.code == (BPF_MISC|BPF_TAX)) {
+                       s->s.code = BPF_LDX|BPF_IMM;
+                       next->s.code = BPF_MISC|BPF_TXA;
+                       done = 0;
+               }
+               /*
+                * This is an ugly special case, but it happens
+                * when you say tcp[k] or udp[k] where k is a constant.
+                */
+               if (s->s.code == (BPF_LD|BPF_IMM)) {
+                       struct slist *add, *tax, *ild;
+
+                       /*
+                        * Check that X isn't used on exit from this
+                        * block (which the optimizer might cause).
+                        * We know the code generator won't generate
+                        * any local dependencies.
+                        */
+                       if (ATOMELEM(b->out_use, X_ATOM))
+                               continue;
+
+                       /*
+                        * Check that the instruction following the ldi
+                        * is an addx, or it's an ldxms with an addx
+                        * following it (with 0 or more nops between the
+                        * ldxms and addx).
+                        */
+                       if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
+                               add = next;
+                       else
+                               add = this_op(next->next);
+                       if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
+                               continue;
+
+                       /*
+                        * Check that a tax follows that (with 0 or more
+                        * nops between them).
+                        */
+                       tax = this_op(add->next);
+                       if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
+                               continue;
+
+                       /*
+                        * Check that an ild follows that (with 0 or more
+                        * nops between them).
+                        */
+                       ild = this_op(tax->next);
+                       if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
+                           BPF_MODE(ild->s.code) != BPF_IND)
+                               continue;
+                       /*
+                        * We want to turn this sequence:
+                        *
+                        * (004) ldi     #0x2           {s}
+                        * (005) ldxms   [14]           {next}  -- optional
+                        * (006) addx                   {add}
+                        * (007) tax                    {tax}
+                        * (008) ild     [x+0]          {ild}
+                        *
+                        * into this sequence:
+                        *
+                        * (004) nop
+                        * (005) ldxms   [14]
+                        * (006) nop
+                        * (007) nop
+                        * (008) ild     [x+2]
+                        *
+                        * XXX We need to check that X is not
+                        * subsequently used, because we want to change
+                        * what'll be in it after this sequence.
+                        *
+                        * We know we can eliminate the accumulator
+                        * modifications earlier in the sequence since
+                        * it is defined by the last stmt of this sequence
+                        * (i.e., the last statement of the sequence loads
+                        * a value into the accumulator, so we can eliminate
+                        * earlier operations on the accumulator).
+                        */
+                       ild->s.k += s->s.k;
+                       s->s.code = NOP;
+                       add->s.code = NOP;
+                       tax->s.code = NOP;
+                       done = 0;
+               }
+       }
+       /*
+        * If the comparison at the end of a block is an equality
+        * comparison against a constant, and nobody uses the value
+        * we leave in the A register at the end of a block, and
+        * the operation preceding the comparison is an arithmetic
+        * operation, we can sometime optimize it away.
+        */
+       if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
+           !ATOMELEM(b->out_use, A_ATOM)) {
+               /*
+                * We can optimize away certain subtractions of the
+                * X register.
+                */
+               if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
+                       val = b->val[X_ATOM];
+                       if (vmap[val].is_const) {
+                               /*
+                                * If we have a subtract to do a comparison,
+                                * and the X register is a known constant,
+                                * we can merge this value into the
+                                * comparison:
+                                *
+                                * sub x  ->    nop
+                                * jeq #y       jeq #(x+y)
+                                */
+                               b->s.k += vmap[val].const_val;
+                               last->s.code = NOP;
+                               done = 0;
+                       } else if (b->s.k == 0) {
+                               /*
+                                * If the X register isn't a constant,
+                                * and the comparison in the test is
+                                * against 0, we can compare with the
+                                * X register, instead:
+                                *
+                                * sub x  ->    nop
+                                * jeq #0       jeq x
+                                */
+                               last->s.code = NOP;
+                               b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
+                               done = 0;
+                       }
+               }
+               /*
+                * Likewise, a constant subtract can be simplified:
+                *
+                * sub #x ->    nop
+                * jeq #y ->    jeq #(x+y)
+                */
+               else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
+                       last->s.code = NOP;
+                       b->s.k += last->s.k;
+                       done = 0;
+               }
+               /*
+                * And, similarly, a constant AND can be simplified
+                * if we're testing against 0, i.e.:
+                *
+                * and #k       nop
+                * jeq #0  ->   jset #k
+                */
+               else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+                   b->s.k == 0) {
+                       b->s.k = last->s.k;
+                       b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+                       last->s.code = NOP;
+                       done = 0;
+                       opt_not(b);
+               }
+       }
+       /*
+        * jset #0        ->   never
+        * jset #ffffffff ->   always
+        */
+       if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
+               if (b->s.k == 0)
+                       JT(b) = JF(b);
+               if (b->s.k == 0xffffffff)
+                       JF(b) = JT(b);
+       }
+       /*
+        * If we're comparing against the index register, and the index
+        * register is a known constant, we can just compare against that
+        * constant.
+        */
+       val = b->val[X_ATOM];
+       if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
+               bpf_int32 v = vmap[val].const_val;
+               b->s.code &= ~BPF_X;
+               b->s.k = v;
+       }
+       /*
+        * If the accumulator is a known constant, we can compute the
+        * comparison result.
+        */
+       val = b->val[A_ATOM];
+       if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+               bpf_int32 v = vmap[val].const_val;
+               switch (BPF_OP(b->s.code)) {
+
+               case BPF_JEQ:
+                       v = v == b->s.k;
+                       break;
+
+               case BPF_JGT:
+                       v = (unsigned)v > b->s.k;
+                       break;
+
+               case BPF_JGE:
+                       v = (unsigned)v >= b->s.k;
+                       break;
+
+               case BPF_JSET:
+                       v &= b->s.k;
+                       break;
+
+               default:
+                       abort();
+               }
+               if (JF(b) != JT(b))
+                       done = 0;
+               if (v)
+                       JF(b) = JT(b);
+               else
+                       JT(b) = JF(b);
+       }
+}
+
+/*
+ * Compute the symbolic value of expression of 's', and update
+ * anything it defines in the value table 'val'.  If 'alter' is true,
+ * do various optimizations.  This code would be cleaner if symbolic
+ * evaluation and code transformations weren't folded together.
+ */
+static void
+opt_stmt(s, val, alter)
+       struct stmt *s;
+       int val[];
+       int alter;
+{
+       int op;
+       int v;
+
+       switch (s->code) {
+
+       case BPF_LD|BPF_ABS|BPF_W:
+       case BPF_LD|BPF_ABS|BPF_H:
+       case BPF_LD|BPF_ABS|BPF_B:
+               v = F(s->code, s->k, 0L);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_IND|BPF_W:
+       case BPF_LD|BPF_IND|BPF_H:
+       case BPF_LD|BPF_IND|BPF_B:
+               v = val[X_ATOM];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
+                       s->k += vmap[v].const_val;
+                       v = F(s->code, s->k, 0L);
+                       done = 0;
+               }
+               else
+                       v = F(s->code, s->k, v);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_LEN:
+               v = F(s->code, 0L, 0L);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_IMM:
+               v = K(s->k);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LDX|BPF_IMM:
+               v = K(s->k);
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_LDX|BPF_MSH|BPF_B:
+               v = F(s->code, s->k, 0L);
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_ALU|BPF_NEG:
+               if (alter && vmap[val[A_ATOM]].is_const) {
+                       s->code = BPF_LD|BPF_IMM;
+                       s->k = -vmap[val[A_ATOM]].const_val;
+                       val[A_ATOM] = K(s->k);
+               }
+               else
+                       val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_K:
+       case BPF_ALU|BPF_SUB|BPF_K:
+       case BPF_ALU|BPF_MUL|BPF_K:
+       case BPF_ALU|BPF_DIV|BPF_K:
+       case BPF_ALU|BPF_AND|BPF_K:
+       case BPF_ALU|BPF_OR|BPF_K:
+       case BPF_ALU|BPF_LSH|BPF_K:
+       case BPF_ALU|BPF_RSH|BPF_K:
+               op = BPF_OP(s->code);
+               if (alter) {
+                       if (s->k == 0) {
+                               /* don't optimize away "sub #0"
+                                * as it may be needed later to
+                                * fixup the generated math code */
+                               if (op == BPF_ADD ||
+                                   op == BPF_LSH || op == BPF_RSH ||
+                                   op == BPF_OR) {
+                                       s->code = NOP;
+                                       break;
+                               }
+                               if (op == BPF_MUL || op == BPF_AND) {
+                                       s->code = BPF_LD|BPF_IMM;
+                                       val[A_ATOM] = K(s->k);
+                                       break;
+                               }
+                       }
+                       if (vmap[val[A_ATOM]].is_const) {
+                               fold_op(s, val[A_ATOM], K(s->k));
+                               val[A_ATOM] = K(s->k);
+                               break;
+                       }
+               }
+               val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_X:
+       case BPF_ALU|BPF_SUB|BPF_X:
+       case BPF_ALU|BPF_MUL|BPF_X:
+       case BPF_ALU|BPF_DIV|BPF_X:
+       case BPF_ALU|BPF_AND|BPF_X:
+       case BPF_ALU|BPF_OR|BPF_X:
+       case BPF_ALU|BPF_LSH|BPF_X:
+       case BPF_ALU|BPF_RSH|BPF_X:
+               op = BPF_OP(s->code);
+               if (alter && vmap[val[X_ATOM]].is_const) {
+                       if (vmap[val[A_ATOM]].is_const) {
+                               fold_op(s, val[A_ATOM], val[X_ATOM]);
+                               val[A_ATOM] = K(s->k);
+                       }
+                       else {
+                               s->code = BPF_ALU|BPF_K|op;
+                               s->k = vmap[val[X_ATOM]].const_val;
+                               done = 0;
+                               val[A_ATOM] =
+                                       F(s->code, val[A_ATOM], K(s->k));
+                       }
+                       break;
+               }
+               /*
+                * Check if we're doing something to an accumulator
+                * that is 0, and simplify.  This may not seem like
+                * much of a simplification but it could open up further
+                * optimizations.
+                * XXX We could also check for mul by 1, etc.
+                */
+               if (alter && vmap[val[A_ATOM]].is_const
+                   && vmap[val[A_ATOM]].const_val == 0) {
+                       if (op == BPF_ADD || op == BPF_OR) {
+                               s->code = BPF_MISC|BPF_TXA;
+                               vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+                               break;
+                       }
+                       else if (op == BPF_MUL || op == BPF_DIV ||
+                                op == BPF_AND || op == BPF_LSH || op == BPF_RSH) {
+                               s->code = BPF_LD|BPF_IMM;
+                               s->k = 0;
+                               vstore(s, &val[A_ATOM], K(s->k), alter);
+                               break;
+                       }
+                       else if (op == BPF_NEG) {
+                               s->code = NOP;
+                               break;
+                       }
+               }
+               val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
+               break;
+
+       case BPF_MISC|BPF_TXA:
+               vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+               break;
+
+       case BPF_LD|BPF_MEM:
+               v = val[s->k];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LD|BPF_IMM;
+                       s->k = vmap[v].const_val;
+                       done = 0;
+               }
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_MISC|BPF_TAX:
+               vstore(s, &val[X_ATOM], val[A_ATOM], alter);
+               break;
+
+       case BPF_LDX|BPF_MEM:
+               v = val[s->k];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LDX|BPF_IMM;
+                       s->k = vmap[v].const_val;
+                       done = 0;
+               }
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_ST:
+               vstore(s, &val[s->k], val[A_ATOM], alter);
+               break;
+
+       case BPF_STX:
+               vstore(s, &val[s->k], val[X_ATOM], alter);
+               break;
+       }
+}
+
+static void
+deadstmt(s, last)
+       register struct stmt *s;
+       register struct stmt *last[];
+{
+       register int atom;
+
+       atom = atomuse(s);
+       if (atom >= 0) {
+               if (atom == AX_ATOM) {
+                       last[X_ATOM] = 0;
+                       last[A_ATOM] = 0;
+               }
+               else
+                       last[atom] = 0;
+       }
+       atom = atomdef(s);
+       if (atom >= 0) {
+               if (last[atom]) {
+                       done = 0;
+                       last[atom]->code = NOP;
+               }
+               last[atom] = s;
+       }
+}
+
+static void
+opt_deadstores(b)
+       register struct block *b;
+{
+       register struct slist *s;
+       register int atom;
+       struct stmt *last[N_ATOMS];
+
+       memset((char *)last, 0, sizeof last);
+
+       for (s = b->stmts; s != 0; s = s->next)
+               deadstmt(&s->s, last);
+       deadstmt(&b->s, last);
+
+       for (atom = 0; atom < N_ATOMS; ++atom)
+               if (last[atom] && !ATOMELEM(b->out_use, atom)) {
+                       last[atom]->code = NOP;
+                       done = 0;
+               }
+}
+
+static void
+opt_blk(b, do_stmts)
+       struct block *b;
+       int do_stmts;
+{
+       struct slist *s;
+       struct edge *p;
+       int i;
+       bpf_int32 aval, xval;
+
+#if 0
+       for (s = b->stmts; s && s->next; s = s->next)
+               if (BPF_CLASS(s->s.code) == BPF_JMP) {
+                       do_stmts = 0;
+                       break;
+               }
+#endif
+
+       /*
+        * Initialize the atom values.
+        */
+       p = b->in_edges;
+       if (p == 0) {
+               /*
+                * We have no predecessors, so everything is undefined
+                * upon entry to this block.
+                */
+               memset((char *)b->val, 0, sizeof(b->val));
+       } else {
+               /*
+                * Inherit values from our predecessors.
+                *
+                * First, get the values from the predecessor along the
+                * first edge leading to this node.
+                */
+               memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
+               /*
+                * Now look at all the other nodes leading to this node.
+                * If, for the predecessor along that edge, a register
+                * has a different value from the one we have (i.e.,
+                * control paths are merging, and the merging paths
+                * assign different values to that register), give the
+                * register the undefined value of 0.
+                */
+               while ((p = p->next) != NULL) {
+                       for (i = 0; i < N_ATOMS; ++i)
+                               if (b->val[i] != p->pred->val[i])
+                                       b->val[i] = 0;
+               }
+       }
+       aval = b->val[A_ATOM];
+       xval = b->val[X_ATOM];
+       for (s = b->stmts; s; s = s->next)
+               opt_stmt(&s->s, b->val, do_stmts);
+
+       /*
+        * This is a special case: if we don't use anything from this
+        * block, and we load the accumulator or index register with a
+        * value that is already there, or if this block is a return,
+        * eliminate all the statements.
+        *
+        * XXX - what if it does a store?
+        *
+        * XXX - why does it matter whether we use anything from this
+        * block?  If the accumulator or index register doesn't change
+        * its value, isn't that OK even if we use that value?
+        *
+        * XXX - if we load the accumulator with a different value,
+        * and the block ends with a conditional branch, we obviously
+        * can't eliminate it, as the branch depends on that value.
+        * For the index register, the conditional branch only depends
+        * on the index register value if the test is against the index
+        * register value rather than a constant; if nothing uses the
+        * value we put into the index register, and we're not testing
+        * against the index register's value, and there aren't any
+        * other problems that would keep us from eliminating this
+        * block, can we eliminate it?
+        */
+       if (do_stmts &&
+           ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval &&
+             xval != 0 && b->val[X_ATOM] == xval) ||
+            BPF_CLASS(b->s.code) == BPF_RET)) {
+               if (b->stmts != 0) {
+                       b->stmts = 0;
+                       done = 0;
+               }
+       } else {
+               opt_peep(b);
+               opt_deadstores(b);
+       }
+       /*
+        * Set up values for branch optimizer.
+        */
+       if (BPF_SRC(b->s.code) == BPF_K)
+               b->oval = K(b->s.k);
+       else
+               b->oval = b->val[X_ATOM];
+       b->et.code = b->s.code;
+       b->ef.code = -b->s.code;
+}
+
+/*
+ * Return true if any register that is used on exit from 'succ', has
+ * an exit value that is different from the corresponding exit value
+ * from 'b'.
+ */
+static int
+use_conflict(b, succ)
+       struct block *b, *succ;
+{
+       int atom;
+       atomset use = succ->out_use;
+
+       if (use == 0)
+               return 0;
+
+       for (atom = 0; atom < N_ATOMS; ++atom)
+               if (ATOMELEM(use, atom))
+                       if (b->val[atom] != succ->val[atom])
+                               return 1;
+       return 0;
+}
+
+static struct block *
+fold_edge(child, ep)
+       struct block *child;
+       struct edge *ep;
+{
+       int sense;
+       int aval0, aval1, oval0, oval1;
+       int code = ep->code;
+
+       if (code < 0) {
+               code = -code;
+               sense = 0;
+       } else
+               sense = 1;
+
+       if (child->s.code != code)
+               return 0;
+
+       aval0 = child->val[A_ATOM];
+       oval0 = child->oval;
+       aval1 = ep->pred->val[A_ATOM];
+       oval1 = ep->pred->oval;
+
+       if (aval0 != aval1)
+               return 0;
+
+       if (oval0 == oval1)
+               /*
+                * The operands of the branch instructions are
+                * identical, so the result is true if a true
+                * branch was taken to get here, otherwise false.
+                */
+               return sense ? JT(child) : JF(child);
+
+       if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
+               /*
+                * At this point, we only know the comparison if we
+                * came down the true branch, and it was an equality
+                * comparison with a constant.
+                *
+                * I.e., if we came down the true branch, and the branch
+                * was an equality comparison with a constant, we know the
+                * accumulator contains that constant.  If we came down
+                * the false branch, or the comparison wasn't with a
+                * constant, we don't know what was in the accumulator.
+                *
+                * We rely on the fact that distinct constants have distinct
+                * value numbers.
+                */
+               return JF(child);
+
+       return 0;
+}
+
+static void
+opt_j(ep)
+       struct edge *ep;
+{
+       register int i, k;
+       register struct block *target;
+
+       if (JT(ep->succ) == 0)
+               return;
+
+       if (JT(ep->succ) == JF(ep->succ)) {
+               /*
+                * Common branch targets can be eliminated, provided
+                * there is no data dependency.
+                */
+               if (!use_conflict(ep->pred, ep->succ->et.succ)) {
+                       done = 0;
+                       ep->succ = JT(ep->succ);
+               }
+       }
+       /*
+        * For each edge dominator that matches the successor of this
+        * edge, promote the edge successor to the its grandchild.
+        *
+        * XXX We violate the set abstraction here in favor a reasonably
+        * efficient loop.
+        */
+ top:
+       for (i = 0; i < edgewords; ++i) {
+               register bpf_u_int32 x = ep->edom[i];
+
+               while (x != 0) {
+                       k = ffs(x) - 1;
+                       x &=~ (1 << k);
+                       k += i * BITS_PER_WORD;
+
+                       target = fold_edge(ep->succ, edges[k]);
+                       /*
+                        * Check that there is no data dependency between
+                        * nodes that will be violated if we move the edge.
+                        */
+                       if (target != 0 && !use_conflict(ep->pred, target)) {
+                               done = 0;
+                               ep->succ = target;
+                               if (JT(target) != 0)
+                                       /*
+                                        * Start over unless we hit a leaf.
+                                        */
+                                       goto top;
+                               return;
+                       }
+               }
+       }
+}
+
+
+static void
+or_pullup(b)
+       struct block *b;
+{
+       int val, at_top;
+       struct block *pull;
+       struct block **diffp, **samep;
+       struct edge *ep;
+
+       ep = b->in_edges;
+       if (ep == 0)
+               return;
+
+       /*
+        * Make sure each predecessor loads the same value.
+        * XXX why?
+        */
+       val = ep->pred->val[A_ATOM];
+       for (ep = ep->next; ep != 0; ep = ep->next)
+               if (val != ep->pred->val[A_ATOM])
+                       return;
+
+       if (JT(b->in_edges->pred) == b)
+               diffp = &JT(b->in_edges->pred);
+       else
+               diffp = &JF(b->in_edges->pred);
+
+       at_top = 1;
+       while (1) {
+               if (*diffp == 0)
+                       return;
+
+               if (JT(*diffp) != JT(b))
+                       return;
+
+               if (!SET_MEMBER((*diffp)->dom, b->id))
+                       return;
+
+               if ((*diffp)->val[A_ATOM] != val)
+                       break;
+
+               diffp = &JF(*diffp);
+               at_top = 0;
+       }
+       samep = &JF(*diffp);
+       while (1) {
+               if (*samep == 0)
+                       return;
+
+               if (JT(*samep) != JT(b))
+                       return;
+
+               if (!SET_MEMBER((*samep)->dom, b->id))
+                       return;
+
+               if ((*samep)->val[A_ATOM] == val)
+                       break;
+
+               /* XXX Need to check that there are no data dependencies
+                  between dp0 and dp1.  Currently, the code generator
+                  will not produce such dependencies. */
+               samep = &JF(*samep);
+       }
+#ifdef notdef
+       /* XXX This doesn't cover everything. */
+       for (i = 0; i < N_ATOMS; ++i)
+               if ((*samep)->val[i] != pred->val[i])
+                       return;
+#endif
+       /* Pull up the node. */
+       pull = *samep;
+       *samep = JF(pull);
+       JF(pull) = *diffp;
+
+       /*
+        * At the top of the chain, each predecessor needs to point at the
+        * pulled up node.  Inside the chain, there is only one predecessor
+        * to worry about.
+        */
+       if (at_top) {
+               for (ep = b->in_edges; ep != 0; ep = ep->next) {
+                       if (JT(ep->pred) == b)
+                               JT(ep->pred) = pull;
+                       else
+                               JF(ep->pred) = pull;
+               }
+       }
+       else
+               *diffp = pull;
+
+       done = 0;
+}
+
+static void
+and_pullup(b)
+       struct block *b;
+{
+       int val, at_top;
+       struct block *pull;
+       struct block **diffp, **samep;
+       struct edge *ep;
+
+       ep = b->in_edges;
+       if (ep == 0)
+               return;
+
+       /*
+        * Make sure each predecessor loads the same value.
+        */
+       val = ep->pred->val[A_ATOM];
+       for (ep = ep->next; ep != 0; ep = ep->next)
+               if (val != ep->pred->val[A_ATOM])
+                       return;
+
+       if (JT(b->in_edges->pred) == b)
+               diffp = &JT(b->in_edges->pred);
+       else
+               diffp = &JF(b->in_edges->pred);
+
+       at_top = 1;
+       while (1) {
+               if (*diffp == 0)
+                       return;
+
+               if (JF(*diffp) != JF(b))
+                       return;
+
+               if (!SET_MEMBER((*diffp)->dom, b->id))
+                       return;
+
+               if ((*diffp)->val[A_ATOM] != val)
+                       break;
+
+               diffp = &JT(*diffp);
+               at_top = 0;
+       }
+       samep = &JT(*diffp);
+       while (1) {
+               if (*samep == 0)
+                       return;
+
+               if (JF(*samep) != JF(b))
+                       return;
+
+               if (!SET_MEMBER((*samep)->dom, b->id))
+                       return;
+
+               if ((*samep)->val[A_ATOM] == val)
+                       break;
+
+               /* XXX Need to check that there are no data dependencies
+                  between diffp and samep.  Currently, the code generator
+                  will not produce such dependencies. */
+               samep = &JT(*samep);
+       }
+#ifdef notdef
+       /* XXX This doesn't cover everything. */
+       for (i = 0; i < N_ATOMS; ++i)
+               if ((*samep)->val[i] != pred->val[i])
+                       return;
+#endif
+       /* Pull up the node. */
+       pull = *samep;
+       *samep = JT(pull);
+       JT(pull) = *diffp;
+
+       /*
+        * At the top of the chain, each predecessor needs to point at the
+        * pulled up node.  Inside the chain, there is only one predecessor
+        * to worry about.
+        */
+       if (at_top) {
+               for (ep = b->in_edges; ep != 0; ep = ep->next) {
+                       if (JT(ep->pred) == b)
+                               JT(ep->pred) = pull;
+                       else
+                               JF(ep->pred) = pull;
+               }
+       }
+       else
+               *diffp = pull;
+
+       done = 0;
+}
+
+static void
+opt_blks(root, do_stmts)
+       struct block *root;
+       int do_stmts;
+{
+       int i, maxlevel;
+       struct block *p;
+
+       init_val();
+       maxlevel = root->level;
+
+       find_inedges(root);
+       for (i = maxlevel; i >= 0; --i)
+               for (p = levels[i]; p; p = p->link)
+                       opt_blk(p, do_stmts);
+
+       if (do_stmts)
+               /*
+                * No point trying to move branches; it can't possibly
+                * make a difference at this point.
+                */
+               return;
+
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       opt_j(&p->et);
+                       opt_j(&p->ef);
+               }
+       }
+
+       find_inedges(root);
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       or_pullup(p);
+                       and_pullup(p);
+               }
+       }
+}
+
+static inline void
+link_inedge(parent, child)
+       struct edge *parent;
+       struct block *child;
+{
+       parent->next = child->in_edges;
+       child->in_edges = parent;
+}
+
+static void
+find_inedges(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+
+       for (i = 0; i < n_blocks; ++i)
+               blocks[i]->in_edges = 0;
+
+       /*
+        * Traverse the graph, adding each edge to the predecessor
+        * list of its successors.  Skip the leaves (i.e. level 0).
+        */
+       for (i = root->level; i > 0; --i) {
+               for (b = levels[i]; b != 0; b = b->link) {
+                       link_inedge(&b->et, JT(b));
+                       link_inedge(&b->ef, JF(b));
+               }
+       }
+}
+
+static void
+opt_root(b)
+       struct block **b;
+{
+       struct slist *tmp, *s;
+
+       s = (*b)->stmts;
+       (*b)->stmts = 0;
+       while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
+               *b = JT(*b);
+
+       tmp = (*b)->stmts;
+       if (tmp != 0)
+               sappend(s, tmp);
+       (*b)->stmts = s;
+
+       /*
+        * If the root node is a return, then there is no
+        * point executing any statements (since the bpf machine
+        * has no side effects).
+        */
+       if (BPF_CLASS((*b)->s.code) == BPF_RET)
+               (*b)->stmts = 0;
+}
+
+static void
+opt_loop(root, do_stmts)
+       struct block *root;
+       int do_stmts;
+{
+
+#ifdef BDEBUG
+       if (dflag > 1) {
+               printf("opt_loop(root, %d) begin\n", do_stmts);
+               opt_dump(root);
+       }
+#endif
+       do {
+               done = 1;
+               find_levels(root);
+               find_dom(root);
+               find_closure(root);
+               find_ud(root);
+               find_edom(root);
+               opt_blks(root, do_stmts);
+#ifdef BDEBUG
+               if (dflag > 1) {
+                       printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done);
+                       opt_dump(root);
+               }
+#endif
+       } while (!done);
+}
+
+/*
+ * Optimize the filter code in its dag representation.
+ */
+void
+bpf_optimize(rootp)
+       struct block **rootp;
+{
+       struct block *root;
+
+       root = *rootp;
+
+       opt_init(root);
+       opt_loop(root, 0);
+       opt_loop(root, 1);
+       intern_blocks(root);
+#ifdef BDEBUG
+       if (dflag > 1) {
+               printf("after intern_blocks()\n");
+               opt_dump(root);
+       }
+#endif
+       opt_root(rootp);
+#ifdef BDEBUG
+       if (dflag > 1) {
+               printf("after opt_root()\n");
+               opt_dump(root);
+       }
+#endif
+       opt_cleanup();
+}
+
+static void
+make_marks(p)
+       struct block *p;
+{
+       if (!isMarked(p)) {
+               Mark(p);
+               if (BPF_CLASS(p->s.code) != BPF_RET) {
+                       make_marks(JT(p));
+                       make_marks(JF(p));
+               }
+       }
+}
+
+/*
+ * Mark code array such that isMarked(i) is true
+ * only for nodes that are alive.
+ */
+static void
+mark_code(p)
+       struct block *p;
+{
+       cur_mark += 1;
+       make_marks(p);
+}
+
+/*
+ * True iff the two stmt lists load the same value from the packet into
+ * the accumulator.
+ */
+static int
+eq_slist(x, y)
+       struct slist *x, *y;
+{
+       while (1) {
+               while (x && x->s.code == NOP)
+                       x = x->next;
+               while (y && y->s.code == NOP)
+                       y = y->next;
+               if (x == 0)
+                       return y == 0;
+               if (y == 0)
+                       return x == 0;
+               if (x->s.code != y->s.code || x->s.k != y->s.k)
+                       return 0;
+               x = x->next;
+               y = y->next;
+       }
+}
+
+static inline int
+eq_blk(b0, b1)
+       struct block *b0, *b1;
+{
+       if (b0->s.code == b1->s.code &&
+           b0->s.k == b1->s.k &&
+           b0->et.succ == b1->et.succ &&
+           b0->ef.succ == b1->ef.succ)
+               return eq_slist(b0->stmts, b1->stmts);
+       return 0;
+}
+
+static void
+intern_blocks(root)
+       struct block *root;
+{
+       struct block *p;
+       int i, j;
+       int done1; /* don't shadow global */
+ top:
+       done1 = 1;
+       for (i = 0; i < n_blocks; ++i)
+               blocks[i]->link = 0;
+
+       mark_code(root);
+
+       for (i = n_blocks - 1; --i >= 0; ) {
+               if (!isMarked(blocks[i]))
+                       continue;
+               for (j = i + 1; j < n_blocks; ++j) {
+                       if (!isMarked(blocks[j]))
+                               continue;
+                       if (eq_blk(blocks[i], blocks[j])) {
+                               blocks[i]->link = blocks[j]->link ?
+                                       blocks[j]->link : blocks[j];
+                               break;
+                       }
+               }
+       }
+       for (i = 0; i < n_blocks; ++i) {
+               p = blocks[i];
+               if (JT(p) == 0)
+                       continue;
+               if (JT(p)->link) {
+                       done1 = 0;
+                       JT(p) = JT(p)->link;
+               }
+               if (JF(p)->link) {
+                       done1 = 0;
+                       JF(p) = JF(p)->link;
+               }
+       }
+       if (!done1)
+               goto top;
+}
+
+static void
+opt_cleanup()
+{
+       free((void *)vnode_base);
+       free((void *)vmap);
+       free((void *)edges);
+       free((void *)space);
+       free((void *)levels);
+       free((void *)blocks);
+}
+
+/*
+ * Return the number of stmts in 's'.
+ */
+static u_int
+slength(s)
+       struct slist *s;
+{
+       u_int n = 0;
+
+       for (; s; s = s->next)
+               if (s->s.code != NOP)
+                       ++n;
+       return n;
+}
+
+/*
+ * Return the number of nodes reachable by 'p'.
+ * All nodes should be initially unmarked.
+ */
+static int
+count_blocks(p)
+       struct block *p;
+{
+       if (p == 0 || isMarked(p))
+               return 0;
+       Mark(p);
+       return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
+}
+
+/*
+ * Do a depth first search on the flow graph, numbering the
+ * the basic blocks, and entering them into the 'blocks' array.`
+ */
+static void
+number_blks_r(p)
+       struct block *p;
+{
+       int n;
+
+       if (p == 0 || isMarked(p))
+               return;
+
+       Mark(p);
+       n = n_blocks++;
+       p->id = n;
+       blocks[n] = p;
+
+       number_blks_r(JT(p));
+       number_blks_r(JF(p));
+}
+
+/*
+ * Return the number of stmts in the flowgraph reachable by 'p'.
+ * The nodes should be unmarked before calling.
+ *
+ * Note that "stmts" means "instructions", and that this includes
+ *
+ *     side-effect statements in 'p' (slength(p->stmts));
+ *
+ *     statements in the true branch from 'p' (count_stmts(JT(p)));
+ *
+ *     statements in the false branch from 'p' (count_stmts(JF(p)));
+ *
+ *     the conditional jump itself (1);
+ *
+ *     an extra long jump if the true branch requires it (p->longjt);
+ *
+ *     an extra long jump if the false branch requires it (p->longjf).
+ */
+static u_int
+count_stmts(p)
+       struct block *p;
+{
+       u_int n;
+
+       if (p == 0 || isMarked(p))
+               return 0;
+       Mark(p);
+       n = count_stmts(JT(p)) + count_stmts(JF(p));
+       return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
+}
+
+/*
+ * Allocate memory.  All allocation is done before optimization
+ * is begun.  A linear bound on the size of all data structures is computed
+ * from the total number of blocks and/or statements.
+ */
+static void
+opt_init(root)
+       struct block *root;
+{
+       bpf_u_int32 *p;
+       int i, n, max_stmts;
+
+       /*
+        * First, count the blocks, so we can malloc an array to map
+        * block number to block.  Then, put the blocks into the array.
+        */
+       unMarkAll();
+       n = count_blocks(root);
+       blocks = (struct block **)calloc(n, sizeof(*blocks));
+       if (blocks == NULL)
+               bpf_error("malloc");
+       unMarkAll();
+       n_blocks = 0;
+       number_blks_r(root);
+
+       n_edges = 2 * n_blocks;
+       edges = (struct edge **)calloc(n_edges, sizeof(*edges));
+       if (edges == NULL)
+               bpf_error("malloc");
+
+       /*
+        * The number of levels is bounded by the number of nodes.
+        */
+       levels = (struct block **)calloc(n_blocks, sizeof(*levels));
+       if (levels == NULL)
+               bpf_error("malloc");
+
+       edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;
+       nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
+
+       /* XXX */
+       space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)
+                                + n_edges * edgewords * sizeof(*space));
+       if (space == NULL)
+               bpf_error("malloc");
+       p = space;
+       all_dom_sets = p;
+       for (i = 0; i < n; ++i) {
+               blocks[i]->dom = p;
+               p += nodewords;
+       }
+       all_closure_sets = p;
+       for (i = 0; i < n; ++i) {
+               blocks[i]->closure = p;
+               p += nodewords;
+       }
+       all_edge_sets = p;
+       for (i = 0; i < n; ++i) {
+               register struct block *b = blocks[i];
+
+               b->et.edom = p;
+               p += edgewords;
+               b->ef.edom = p;
+               p += edgewords;
+               b->et.id = i;
+               edges[i] = &b->et;
+               b->ef.id = n_blocks + i;
+               edges[n_blocks + i] = &b->ef;
+               b->et.pred = b;
+               b->ef.pred = b;
+       }
+       max_stmts = 0;
+       for (i = 0; i < n; ++i)
+               max_stmts += slength(blocks[i]->stmts) + 1;
+       /*
+        * We allocate at most 3 value numbers per statement,
+        * so this is an upper bound on the number of valnodes
+        * we'll need.
+        */
+       maxval = 3 * max_stmts;
+       vmap = (struct vmapinfo *)calloc(maxval, sizeof(*vmap));
+       vnode_base = (struct valnode *)calloc(maxval, sizeof(*vnode_base));
+       if (vmap == NULL || vnode_base == NULL)
+               bpf_error("malloc");
+}
+
+/*
+ * Some pointers used to convert the basic block form of the code,
+ * into the array form that BPF requires.  'fstart' will point to
+ * the malloc'd array while 'ftail' is used during the recursive traversal.
+ */
+static struct bpf_insn *fstart;
+static struct bpf_insn *ftail;
+
+#ifdef BDEBUG
+int bids[1000];
+#endif
+
+/*
+ * Returns true if successful.  Returns false if a branch has
+ * an offset that is too large.  If so, we have marked that
+ * branch so that on a subsequent iteration, it will be treated
+ * properly.
+ */
+static int
+convert_code_r(p)
+       struct block *p;
+{
+       struct bpf_insn *dst;
+       struct slist *src;
+       int slen;
+       u_int off;
+       int extrajmps;          /* number of extra jumps inserted */
+       struct slist **offset = NULL;
+
+       if (p == 0 || isMarked(p))
+               return (1);
+       Mark(p);
+
+       if (convert_code_r(JF(p)) == 0)
+               return (0);
+       if (convert_code_r(JT(p)) == 0)
+               return (0);
+
+       slen = slength(p->stmts);
+       dst = ftail -= (slen + 1 + p->longjt + p->longjf);
+               /* inflate length by any extra jumps */
+
+       p->offset = dst - fstart;
+
+       /* generate offset[] for convenience  */
+       if (slen) {
+               offset = (struct slist **)calloc(slen, sizeof(struct slist *));
+               if (!offset) {
+                       bpf_error("not enough core");
+                       /*NOTREACHED*/
+               }
+       }
+       src = p->stmts;
+       for (off = 0; off < slen && src; off++) {
+#if 0
+               printf("off=%d src=%x\n", off, src);
+#endif
+               offset[off] = src;
+               src = src->next;
+       }
+
+       off = 0;
+       for (src = p->stmts; src; src = src->next) {
+               if (src->s.code == NOP)
+                       continue;
+               dst->code = (u_short)src->s.code;
+               dst->k = src->s.k;
+
+               /* fill block-local relative jump */
+               if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {
+#if 0
+                       if (src->s.jt || src->s.jf) {
+                               bpf_error("illegal jmp destination");
+                               /*NOTREACHED*/
+                       }
+#endif
+                       goto filled;
+               }
+               if (off == slen - 2)    /*???*/
+                       goto filled;
+
+           {
+               int i;
+               int jt, jf;
+               const char *ljerr = "%s for block-local relative jump: off=%d";
+
+#if 0
+               printf("code=%x off=%d %x %x\n", src->s.code,
+                       off, src->s.jt, src->s.jf);
+#endif
+
+               if (!src->s.jt || !src->s.jf) {
+                       bpf_error(ljerr, "no jmp destination", off);
+                       /*NOTREACHED*/
+               }
+
+               jt = jf = 0;
+               for (i = 0; i < slen; i++) {
+                       if (offset[i] == src->s.jt) {
+                               if (jt) {
+                                       bpf_error(ljerr, "multiple matches", off);
+                                       /*NOTREACHED*/
+                               }
+
+                               dst->jt = i - off - 1;
+                               jt++;
+                       }
+                       if (offset[i] == src->s.jf) {
+                               if (jf) {
+                                       bpf_error(ljerr, "multiple matches", off);
+                                       /*NOTREACHED*/
+                               }
+                               dst->jf = i - off - 1;
+                               jf++;
+                       }
+               }
+               if (!jt || !jf) {
+                       bpf_error(ljerr, "no destination found", off);
+                       /*NOTREACHED*/
+               }
+           }
+filled:
+               ++dst;
+               ++off;
+       }
+       if (offset)
+               free(offset);
+
+#ifdef BDEBUG
+       bids[dst - fstart] = p->id + 1;
+#endif
+       dst->code = (u_short)p->s.code;
+       dst->k = p->s.k;
+       if (JT(p)) {
+               extrajmps = 0;
+               off = JT(p)->offset - (p->offset + slen) - 1;
+               if (off >= 256) {
+                   /* offset too large for branch, must add a jump */
+                   if (p->longjt == 0) {
+                       /* mark this instruction and retry */
+                       p->longjt++;
+                       return(0);
+                   }
+                   /* branch if T to following jump */
+                   dst->jt = extrajmps;
+                   extrajmps++;
+                   dst[extrajmps].code = BPF_JMP|BPF_JA;
+                   dst[extrajmps].k = off - extrajmps;
+               }
+               else
+                   dst->jt = off;
+               off = JF(p)->offset - (p->offset + slen) - 1;
+               if (off >= 256) {
+                   /* offset too large for branch, must add a jump */
+                   if (p->longjf == 0) {
+                       /* mark this instruction and retry */
+                       p->longjf++;
+                       return(0);
+                   }
+                   /* branch if F to following jump */
+                   /* if two jumps are inserted, F goes to second one */
+                   dst->jf = extrajmps;
+                   extrajmps++;
+                   dst[extrajmps].code = BPF_JMP|BPF_JA;
+                   dst[extrajmps].k = off - extrajmps;
+               }
+               else
+                   dst->jf = off;
+       }
+       return (1);
+}
+
+
+/*
+ * Convert flowgraph intermediate representation to the
+ * BPF array representation.  Set *lenp to the number of instructions.
+ *
+ * This routine does *NOT* leak the memory pointed to by fp.  It *must
+ * not* do free(fp) before returning fp; doing so would make no sense,
+ * as the BPF array pointed to by the return value of icode_to_fcode()
+ * must be valid - it's being returned for use in a bpf_program structure.
+ *
+ * If it appears that icode_to_fcode() is leaking, the problem is that
+ * the program using pcap_compile() is failing to free the memory in
+ * the BPF program when it's done - the leak is in the program, not in
+ * the routine that happens to be allocating the memory.  (By analogy, if
+ * a program calls fopen() without ever calling fclose() on the FILE *,
+ * it will leak the FILE structure; the leak is not in fopen(), it's in
+ * the program.)  Change the program to use pcap_freecode() when it's
+ * done with the filter program.  See the pcap man page.
+ */
+struct bpf_insn *
+icode_to_fcode(root, lenp)
+       struct block *root;
+       u_int *lenp;
+{
+       u_int n;
+       struct bpf_insn *fp;
+
+       /*
+        * Loop doing convert_code_r() until no branches remain
+        * with too-large offsets.
+        */
+       while (1) {
+           unMarkAll();
+           n = *lenp = count_stmts(root);
+
+           fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
+           if (fp == NULL)
+                   bpf_error("malloc");
+           memset((char *)fp, 0, sizeof(*fp) * n);
+           fstart = fp;
+           ftail = fp + n;
+
+           unMarkAll();
+           if (convert_code_r(root))
+               break;
+           free(fp);
+       }
+
+       return fp;
+}
+
+/*
+ * Make a copy of a BPF program and put it in the "fcode" member of
+ * a "pcap_t".
+ *
+ * If we fail to allocate memory for the copy, fill in the "errbuf"
+ * member of the "pcap_t" with an error message, and return -1;
+ * otherwise, return 0.
+ */
+int
+install_bpf_program(pcap_t *p, struct bpf_program *fp)
+{
+       size_t prog_size;
+
+       /*
+        * Validate the program.
+        */
+       if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                       "BPF program is not valid");
+               return (-1);
+       }
+
+       /*
+        * Free up any already installed program.
+        */
+       pcap_freecode(&p->fcode);
+
+       prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
+       p->fcode.bf_len = fp->bf_len;
+       p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
+       if (p->fcode.bf_insns == NULL) {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                        "malloc: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
+       return (0);
+}
+
+#ifdef BDEBUG
+static void
+opt_dump(root)
+       struct block *root;
+{
+       struct bpf_program f;
+
+       memset(bids, 0, sizeof bids);
+       f.bf_insns = icode_to_fcode(root, &f.bf_len);
+       bpf_dump(&f, 1);
+       putchar('\n');
+       free((char *)f.bf_insns);
+}
+#endif
diff --git a/org.tcpdump.chmod_bpf.plist b/org.tcpdump.chmod_bpf.plist
new file mode 100644 (file)
index 0000000..8ad6852
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Label</key>
+       <string>org.tcpdump.chmod_bpf</string>
+       <key>RunAtLoad</key>
+       <true/>
+       <key>Program</key>
+       <string>/usr/local/bin/chmod_bpf</string>
+       <key>ProgramArguments</key>
+       <array>
+               <string>/usr/local/bin/chmod_bpf</string>
+       </array>
+</dict>
+</plist>
diff --git a/packaging/pcap.spec.in b/packaging/pcap.spec.in
new file mode 100644 (file)
index 0000000..ff7b996
--- /dev/null
@@ -0,0 +1,77 @@
+%define prefix   /usr
+%define version @VERSION@
+
+Summary: A system-independent interface for user-level packet capture
+Name: libpcap
+Version: %version
+Release: 1
+Group: Development/Libraries
+License: BSD with advertising
+Source: @NAME@.tar.gz
+BuildRoot: /tmp/%{name}-buildroot
+URL: http://www.tcpdump.org
+
+Source: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz
+
+%description
+Libpcap provides a portable framework for low-level network
+monitoring.  Libpcap can provide network statistics collection,
+security monitoring and network debugging.  Since almost every system
+vendor provides a different interface for packet capture, the libpcap
+authors created this system-independent API to ease in porting and to
+alleviate the need for several system-dependent packet capture modules
+in each application.
+
+Install libpcap if you need to do low-level network traffic monitoring
+on your network.
+
+%package devel
+Summary: Libraries and header files for the libpcap library
+Group: Development/Libraries
+
+%description devel
+Libpcap provides a portable framework for low-level network
+monitoring.  Libpcap can provide network statistics collection,
+security monitoring and network debugging.  Since almost every system
+vendor provides a different interface for packet capture, the libpcap
+authors created this system-independent API to ease in porting and to
+alleviate the need for several system-dependent packet capture modules
+in each application.
+
+This package provides the libraries, include files, and other 
+resources needed for developing libpcap applications.
+%prep
+%setup -q
+
+%build
+export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"
+%configure
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+make DESTDIR=$RPM_BUILD_ROOT install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc LICENSE README CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec
+%{_libdir}/libpcap.so.*
+%{_mandir}/man7/pcap*.7*
+
+%files devel
+%defattr(-,root,root)
+%{_bindir}/pcap-config
+%{_includedir}/pcap/*.h
+%{_includedir}/pcap.h
+%{_includedir}/pcap-bpf.h
+%{_includedir}/pcap-namedb.h
+%{_libdir}/libpcap.so
+%{_libdir}/libpcap.a
+%{_mandir}/man1/pcap-config.1*
+%{_mandir}/man3/pcap*.3*
+%{_mandir}/man5/pcap*.5*
diff --git a/pcap-bpf.c b/pcap-bpf.c
new file mode 100644 (file)
index 0000000..944445f
--- /dev/null
@@ -0,0 +1,2732 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.116 2008-09-16 18:42:29 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+#ifdef HAVE_ZEROCOPY_BPF
+#include <sys/mman.h>
+#endif
+#include <sys/socket.h>
+#include <time.h>
+/*
+ * <net/bpf.h> defines ioctls, but doesn't include <sys/ioccom.h>.
+ *
+ * We include <sys/ioctl.h> as it might be necessary to declare ioctl();
+ * at least on *BSD and Mac OS X, it also defines various SIOC ioctls -
+ * we could include <sys/sockio.h>, but if we're already including
+ * <sys/ioctl.h>, which includes <sys/sockio.h> on those platforms,
+ * there's not much point in doing so.
+ *
+ * If we have <sys/ioccom.h>, we include it as well, to handle systems
+ * such as Solaris which don't arrange to include <sys/ioccom.h> if you
+ * include <sys/ioctl.h>
+ */
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <sys/utsname.h>
+
+#ifdef HAVE_ZEROCOPY_BPF
+#include <machine/atomic.h>
+#endif
+
+#include <net/if.h>
+
+#ifdef _AIX
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we need "struct bpf_config" from it.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+
+#include <sys/types.h>
+
+/*
+ * Prevent bpf.h from redefining the DLT_ values to their
+ * IFT_ values, as we're going to return the standard libpcap
+ * values, not IBM's non-standard IFT_ values.
+ */
+#undef _AIX
+#include <net/bpf.h>
+#define _AIX
+
+#include <net/if_types.h>              /* for IFT_ values */
+#include <sys/sysconfig.h>
+#include <sys/device.h>
+#include <sys/cfgodm.h>
+#include <cf.h>
+
+#ifdef __64BIT__
+#define domakedev makedev64
+#define getmajor major64
+#define bpf_hdr bpf_hdr32
+#else /* __64BIT__ */
+#define domakedev makedev
+#define getmajor major
+#endif /* __64BIT__ */
+
+#define BPF_NAME "bpf"
+#define BPF_MINORS 4
+#define DRIVER_PATH "/usr/lib/drivers"
+#define BPF_NODE "/dev/bpf"
+static int bpfloadedflag = 0;
+static int odmlockid = 0;
+
+static int bpf_load(char *errbuf);
+
+#else /* _AIX */
+
+#include <net/bpf.h>
+
+#endif /* _AIX */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_NET_IF_MEDIA_H
+# include <net/if_media.h>
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_DAG_API
+#include "pcap-dag.h"
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SNF_API
+#include "pcap-snf.h"
+#endif /* HAVE_SNF_API */
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef BIOCGDLTLIST
+# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
+#define HAVE_BSD_IEEE80211
+# endif
+
+# if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+static int find_802_11(struct bpf_dltlist *);
+
+#  ifdef HAVE_BSD_IEEE80211
+static int monitor_mode(pcap_t *, int);
+#  endif
+
+#  if defined(__APPLE__)
+static void remove_en(pcap_t *);
+static void remove_802_11(pcap_t *);
+#  endif
+
+# endif /* defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) */
+
+#endif /* BIOCGDLTLIST */
+
+#if defined(sun) && defined(LIFNAMSIZ) && defined(lifr_zoneid)
+#include <zone.h>
+#endif
+
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS     143
+#endif
+
+/*
+ * On OS X, we don't even get any of the 802.11-plus-radio-header DLT_'s
+ * defined, even though some of them are used by various Airport drivers.
+ */
+#ifndef DLT_PRISM_HEADER
+#define DLT_PRISM_HEADER       119
+#endif
+#ifndef DLT_AIRONET_HEADER
+#define DLT_AIRONET_HEADER     120
+#endif
+#ifndef DLT_IEEE802_11_RADIO
+#define DLT_IEEE802_11_RADIO   127
+#endif
+#ifndef DLT_IEEE802_11_RADIO_AVS
+#define DLT_IEEE802_11_RADIO_AVS 163
+#endif
+
+static int pcap_can_set_rfmon_bpf(pcap_t *p);
+static int pcap_activate_bpf(pcap_t *p);
+static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);
+static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t);
+static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
+
+/*
+ * For zerocopy bpf, the setnonblock/getnonblock routines need to modify
+ * p->md.timeout so we don't call select(2) if the pcap handle is in non-
+ * blocking mode.  We preserve the timeout supplied by pcap_open functions
+ * to make sure it does not get clobbered if the pcap handle moves between
+ * blocking and non-blocking mode.
+ */
+static int
+pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
+{ 
+#ifdef HAVE_ZEROCOPY_BPF
+       if (p->md.zerocopy) {
+               /*
+                * Use a negative value for the timeout to represent that the
+                * pcap handle is in non-blocking mode.
+                */
+               return (p->md.timeout < 0);
+       }
+#endif
+       return (pcap_getnonblock_fd(p, errbuf));
+}
+
+static int
+pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
+{   
+#ifdef HAVE_ZEROCOPY_BPF
+       if (p->md.zerocopy) {
+               /*
+                * Map each value to the corresponding 2's complement, to
+                * preserve the timeout value provided with pcap_set_timeout.
+                * (from pcap-linux.c).
+                */
+               if (nonblock) {
+                       if (p->md.timeout >= 0) {
+                               /*
+                                * Timeout is non-negative, so we're not
+                                * currently in non-blocking mode; set it
+                                * to the 2's complement, to make it
+                                * negative, as an indication that we're
+                                * in non-blocking mode.
+                                */
+                               p->md.timeout = p->md.timeout * -1 - 1;
+                       }
+               } else {
+                       if (p->md.timeout < 0) {
+                               /*
+                                * Timeout is negative, so we're currently
+                                * in blocking mode; reverse the previous
+                                * operation, to make the timeout non-negative
+                                * again.
+                                */
+                               p->md.timeout = (p->md.timeout + 1) * -1;
+                       }
+               }
+               return (0);
+       }
+#endif
+       return (pcap_setnonblock_fd(p, nonblock, errbuf));
+}
+
+#ifdef HAVE_ZEROCOPY_BPF
+/*
+ * Zero-copy BPF buffer routines to check for and acknowledge BPF data in
+ * shared memory buffers.
+ *
+ * pcap_next_zbuf_shm(): Check for a newly available shared memory buffer,
+ * and set up p->buffer and cc to reflect one if available.  Notice that if
+ * there was no prior buffer, we select zbuf1 as this will be the first
+ * buffer filled for a fresh BPF session.
+ */
+static int
+pcap_next_zbuf_shm(pcap_t *p, int *cc)
+{
+       struct bpf_zbuf_header *bzh;
+
+       if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) {
+               bzh = (struct bpf_zbuf_header *)p->md.zbuf1;
+               if (bzh->bzh_user_gen !=
+                   atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
+                       p->md.bzh = bzh;
+                       p->md.zbuffer = (u_char *)p->md.zbuf1;
+                       p->buffer = p->md.zbuffer + sizeof(*bzh);
+                       *cc = bzh->bzh_kernel_len;
+                       return (1);
+               }
+       } else if (p->md.zbuffer == p->md.zbuf1) {
+               bzh = (struct bpf_zbuf_header *)p->md.zbuf2;
+               if (bzh->bzh_user_gen !=
+                   atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
+                       p->md.bzh = bzh;
+                       p->md.zbuffer = (u_char *)p->md.zbuf2;
+                       p->buffer = p->md.zbuffer + sizeof(*bzh);
+                       *cc = bzh->bzh_kernel_len;
+                       return (1);
+               }
+       }
+       *cc = 0;
+       return (0);
+}
+
+/*
+ * pcap_next_zbuf() -- Similar to pcap_next_zbuf_shm(), except wait using
+ * select() for data or a timeout, and possibly force rotation of the buffer
+ * in the event we time out or are in immediate mode.  Invoke the shared
+ * memory check before doing system calls in order to avoid doing avoidable
+ * work.
+ */
+static int
+pcap_next_zbuf(pcap_t *p, int *cc)
+{
+       struct bpf_zbuf bz;
+       struct timeval tv;
+       struct timespec cur;
+       fd_set r_set;
+       int data, r;
+       int expire, tmout;
+
+#define TSTOMILLI(ts) (((ts)->tv_sec * 1000) + ((ts)->tv_nsec / 1000000))
+       /*
+        * Start out by seeing whether anything is waiting by checking the
+        * next shared memory buffer for data.
+        */
+       data = pcap_next_zbuf_shm(p, cc);
+       if (data)
+               return (data);
+       /*
+        * If a previous sleep was interrupted due to signal delivery, make
+        * sure that the timeout gets adjusted accordingly.  This requires
+        * that we analyze when the timeout should be been expired, and
+        * subtract the current time from that.  If after this operation,
+        * our timeout is less then or equal to zero, handle it like a
+        * regular timeout.
+        */
+       tmout = p->md.timeout;
+       if (tmout)
+               (void) clock_gettime(CLOCK_MONOTONIC, &cur);
+       if (p->md.interrupted && p->md.timeout) {
+               expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout;
+               tmout = expire - TSTOMILLI(&cur);
+#undef TSTOMILLI
+               if (tmout <= 0) {
+                       p->md.interrupted = 0;
+                       data = pcap_next_zbuf_shm(p, cc);
+                       if (data)
+                               return (data);
+                       if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
+                               (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BIOCROTZBUF: %s", strerror(errno));
+                               return (PCAP_ERROR);
+                       }
+                       return (pcap_next_zbuf_shm(p, cc));
+               }
+       }
+       /*
+        * No data in the buffer, so must use select() to wait for data or
+        * the next timeout.  Note that we only call select if the handle
+        * is in blocking mode.
+        */
+       if (p->md.timeout >= 0) {
+               FD_ZERO(&r_set);
+               FD_SET(p->fd, &r_set);
+               if (tmout != 0) {
+                       tv.tv_sec = tmout / 1000;
+                       tv.tv_usec = (tmout * 1000) % 1000000;
+               }
+               r = select(p->fd + 1, &r_set, NULL, NULL,
+                   p->md.timeout != 0 ? &tv : NULL);
+               if (r < 0 && errno == EINTR) {
+                       if (!p->md.interrupted && p->md.timeout) {
+                               p->md.interrupted = 1;
+                               p->md.firstsel = cur;
+                       }
+                       return (0);
+               } else if (r < 0) {
+                       (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "select: %s", strerror(errno));
+                       return (PCAP_ERROR);
+               }
+       }
+       p->md.interrupted = 0;
+       /*
+        * Check again for data, which may exist now that we've either been
+        * woken up as a result of data or timed out.  Try the "there's data"
+        * case first since it doesn't require a system call.
+        */
+       data = pcap_next_zbuf_shm(p, cc);
+       if (data)
+               return (data);
+       /*
+        * Try forcing a buffer rotation to dislodge timed out or immediate
+        * data.
+        */
+       if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
+               (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "BIOCROTZBUF: %s", strerror(errno));
+               return (PCAP_ERROR);
+       }
+       return (pcap_next_zbuf_shm(p, cc));
+}
+
+/*
+ * Notify kernel that we are done with the buffer.  We don't reset zbuffer so
+ * that we know which buffer to use next time around.
+ */
+static int
+pcap_ack_zbuf(pcap_t *p)
+{
+
+       atomic_store_rel_int(&p->md.bzh->bzh_user_gen,
+           p->md.bzh->bzh_kernel_gen);
+       p->md.bzh = NULL;
+       p->buffer = NULL;
+       return (0);
+}
+#endif /* HAVE_ZEROCOPY_BPF */
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+#ifdef HAVE_DAG_API
+       if (strstr(device, "dag"))
+               return (dag_create(device, ebuf));
+#endif /* HAVE_DAG_API */
+#ifdef HAVE_SNF_API
+       if (strstr(device, "snf"))
+               return (snf_create(device, ebuf));
+#endif /* HAVE_SNF_API */
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_bpf;
+       p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+       return (p);
+}
+
+/*
+ * On success, returns a file descriptor for a BPF device.
+ * On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
+ */
+static int
+bpf_open(pcap_t *p)
+{
+       int fd;
+#ifdef HAVE_CLONING_BPF
+       static const char device[] = "/dev/bpf";
+#else
+       int n = 0;
+       char device[sizeof "/dev/bpf0000000000"];
+#endif
+
+#ifdef _AIX
+       /*
+        * Load the bpf driver, if it isn't already loaded,
+        * and create the BPF device entries, if they don't
+        * already exist.
+        */
+       if (bpf_load(p->errbuf) == PCAP_ERROR)
+               return (PCAP_ERROR);
+#endif
+
+#ifdef HAVE_CLONING_BPF
+       if ((fd = open(device, O_RDWR)) == -1 &&
+           (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) {
+               if (errno == EACCES)
+                       fd = PCAP_ERROR_PERM_DENIED;
+               else
+                       fd = PCAP_ERROR;
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                 "(cannot open device) %s: %s", device, pcap_strerror(errno));
+       }
+#else
+       /*
+        * Go through all the minors and find one that isn't in use.
+        */
+       do {
+               (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+               /*
+                * Initially try a read/write open (to allow the inject
+                * method to work).  If that fails due to permission
+                * issues, fall back to read-only.  This allows a
+                * non-root user to be granted specific access to pcap
+                * capabilities via file permissions.
+                *
+                * XXX - we should have an API that has a flag that
+                * controls whether to open read-only or read-write,
+                * so that denial of permission to send (or inability
+                * to send, if sending packets isn't supported on
+                * the device in question) can be indicated at open
+                * time.
+                */
+               fd = open(device, O_RDWR);
+               if (fd == -1 && errno == EACCES)
+                       fd = open(device, O_RDONLY);
+       } while (fd < 0 && errno == EBUSY);
+
+       /*
+        * XXX better message for all minors used
+        */
+       if (fd < 0) {
+               switch (errno) {
+
+               case ENOENT:
+                       fd = PCAP_ERROR;
+                       if (n == 1) {
+                               /*
+                                * /dev/bpf0 doesn't exist, which
+                                * means we probably have no BPF
+                                * devices.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "(there are no BPF devices)");
+                       } else {
+                               /*
+                                * We got EBUSY on at least one
+                                * BPF device, so we have BPF
+                                * devices, but all the ones
+                                * that exist are busy.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "(all BPF devices are busy)");
+                       }
+                       break;
+
+               case EACCES:
+                       /*
+                        * Got EACCES on the last device we tried,
+                        * and EBUSY on all devices before that,
+                        * if any.
+                        */
+                       fd = PCAP_ERROR_PERM_DENIED;
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "(cannot open BPF device) %s: %s", device,
+                           pcap_strerror(errno));
+                       break;
+
+               default:
+                       /*
+                        * Some other problem.
+                        */
+                       fd = PCAP_ERROR;
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "(cannot open BPF device) %s: %s", device,
+                           pcap_strerror(errno));
+                       break;
+               }
+       }
+#endif
+
+       return (fd);
+}
+
+#ifdef BIOCGDLTLIST
+static int
+get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
+{
+       memset(bdlp, 0, sizeof(*bdlp));
+       if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) == 0) {
+               u_int i;
+               int is_ethernet;
+
+               bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
+               if (bdlp->bfl_list == NULL) {
+                       (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                           pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+
+               if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
+                       (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "BIOCGDLTLIST: %s", pcap_strerror(errno));
+                       free(bdlp->bfl_list);
+                       return (PCAP_ERROR);
+               }
+
+               /*
+                * OK, for real Ethernet devices, add DLT_DOCSIS to the
+                * list, so that an application can let you choose it,
+                * in case you're capturing DOCSIS traffic that a Cisco
+                * Cable Modem Termination System is putting out onto
+                * an Ethernet (it doesn't put an Ethernet header onto
+                * the wire, it puts raw DOCSIS frames out on the wire
+                * inside the low-level Ethernet framing).
+                *
+                * A "real Ethernet device" is defined here as a device
+                * that has a link-layer type of DLT_EN10MB and that has
+                * no alternate link-layer types; that's done to exclude
+                * 802.11 interfaces (which might or might not be the
+                * right thing to do, but I suspect it is - Ethernet <->
+                * 802.11 bridges would probably badly mishandle frames
+                * that don't have Ethernet headers).
+                *
+                * On Solaris with BPF, Ethernet devices also offer
+                * DLT_IPNET, so we, if DLT_IPNET is defined, we don't
+                * treat it as an indication that the device isn't an
+                * Ethernet.
+                */
+               if (v == DLT_EN10MB) {
+                       is_ethernet = 1;
+                       for (i = 0; i < bdlp->bfl_len; i++) {
+                               if (bdlp->bfl_list[i] != DLT_EN10MB
+#ifdef DLT_IPNET
+                                   && bdlp->bfl_list[i] != DLT_IPNET
+#endif
+                                   ) {
+                                       is_ethernet = 0;
+                                       break;
+                               }
+                       }
+                       if (is_ethernet) {
+                               /*
+                                * We reserved one more slot at the end of
+                                * the list.
+                                */
+                               bdlp->bfl_list[bdlp->bfl_len] = DLT_DOCSIS;
+                               bdlp->bfl_len++;
+                       }
+               }
+       } else {
+               /*
+                * EINVAL just means "we don't support this ioctl on
+                * this device"; don't treat it as an error.
+                */
+               if (errno != EINVAL) {
+                       (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "BIOCGDLTLIST: %s", pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+       }
+       return (0);
+}
+#endif
+
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
+#if defined(__APPLE__)
+       struct utsname osinfo;
+       struct ifreq ifr;
+       int fd;
+#ifdef BIOCGDLTLIST
+       struct bpf_dltlist bdl;
+#endif
+
+       /*
+        * The joys of monitor mode on OS X.
+        *
+        * Prior to 10.4, it's not supported at all.
+        *
+        * In 10.4, if adapter enN supports monitor mode, there's a
+        * wltN adapter corresponding to it; you open it, instead of
+        * enN, to get monitor mode.  You get whatever link-layer
+        * headers it supplies.
+        *
+        * In 10.5, and, we assume, later releases, if adapter enN
+        * supports monitor mode, it offers, among its selectable
+        * DLT_ values, values that let you get the 802.11 header;
+        * selecting one of those values puts the adapter into monitor
+        * mode (i.e., you can't get 802.11 headers except in monitor
+        * mode, and you can't get Ethernet headers in monitor mode).
+        */
+       if (uname(&osinfo) == -1) {
+               /*
+                * Can't get the OS version; just say "no".
+                */
+               return (0);
+       }
+       /*
+        * We assume osinfo.sysname is "Darwin", because
+        * __APPLE__ is defined.  We just check the version.
+        */
+       if (osinfo.release[0] < '8' && osinfo.release[1] == '.') {
+               /*
+                * 10.3 (Darwin 7.x) or earlier.
+                * Monitor mode not supported.
+                */
+               return (0);
+       }
+       if (osinfo.release[0] == '8' && osinfo.release[1] == '.') {
+               /*
+                * 10.4 (Darwin 8.x).  s/en/wlt/, and check
+                * whether the device exists.
+                */
+               if (strncmp(p->opt.source, "en", 2) != 0) {
+                       /*
+                        * Not an enN device; no monitor mode.
+                        */
+                       return (0);
+               }
+               fd = socket(AF_INET, SOCK_DGRAM, 0);
+               if (fd == -1) {
+                       (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "socket: %s", pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+               strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
+               strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+                       /*
+                        * No such device?
+                        */
+                       close(fd);
+                       return (0);
+               }
+               close(fd);
+               return (1);
+       }
+
+#ifdef BIOCGDLTLIST
+       /*
+        * Everything else is 10.5 or later; for those,
+        * we just open the enN device, and check whether
+        * we have any 802.11 devices.
+        *
+        * First, open a BPF device.
+        */
+       fd = bpf_open(p);
+       if (fd < 0)
+               return (fd);    /* fd is the appropriate error code */
+
+       /*
+        * Now bind to the device.
+        */
+       (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+       if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+               switch (errno) {
+
+               case ENXIO:
+                       /*
+                        * There's no such device.
+                        */
+                       close(fd);
+                       return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+               case ENETDOWN:
+                       /*
+                        * Return a "network down" indication, so that
+                        * the application can report that rather than
+                        * saying we had a mysterious failure and
+                        * suggest that they report a problem to the
+                        * libpcap developers.
+                        */
+                       close(fd);
+                       return (PCAP_ERROR_IFACE_NOT_UP);
+
+               default:
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "BIOCSETIF: %s: %s",
+                           p->opt.source, pcap_strerror(errno));
+                       close(fd);
+                       return (PCAP_ERROR);
+               }
+       }
+
+       /*
+        * We know the default link type -- now determine all the DLTs
+        * this interface supports.  If this fails with EINVAL, it's
+        * not fatal; we just don't get to use the feature later.
+        * (We don't care about DLT_DOCSIS, so we pass DLT_NULL
+        * as the default DLT for this adapter.)
+        */
+       if (get_dlt_list(fd, DLT_NULL, &bdl, p->errbuf) == PCAP_ERROR) {
+               close(fd);
+               return (PCAP_ERROR);
+       }
+       if (find_802_11(&bdl) != -1) {
+               /*
+                * We have an 802.11 DLT, so we can set monitor mode.
+                */
+               free(bdl.bfl_list);
+               close(fd);
+               return (1);
+       }
+       free(bdl.bfl_list);
+#endif /* BIOCGDLTLIST */
+       return (0);
+#elif defined(HAVE_BSD_IEEE80211)
+       int ret;
+
+       ret = monitor_mode(p, 0);
+       if (ret == PCAP_ERROR_RFMON_NOTSUP)
+               return (0);     /* not an error, just a "can't do" */
+       if (ret == 0)
+               return (1);     /* success */
+       return (ret);
+#else
+       return (0);
+#endif
+}
+
+static int
+pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
+{
+       struct bpf_stat s;
+
+       /*
+        * "ps_recv" counts packets handed to the filter, not packets
+        * that passed the filter.  This includes packets later dropped
+        * because we ran out of buffer space.
+        *
+        * "ps_drop" counts packets dropped inside the BPF device
+        * because we ran out of buffer space.  It doesn't count
+        * packets dropped by the interface driver.  It counts
+        * only packets that passed the filter.
+        *
+        * Both statistics include packets not yet read from the kernel
+        * by libpcap, and thus not yet seen by the application.
+        */
+       if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
+                   pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+
+       ps->ps_recv = s.bs_recv;
+       ps->ps_drop = s.bs_drop;
+       ps->ps_ifdrop = 0;
+       return (0);
+}
+
+static int
+pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       int n = 0;
+       register u_char *bp, *ep;
+       u_char *datap;
+#ifdef PCAP_FDDIPAD
+       register int pad;
+#endif
+#ifdef HAVE_ZEROCOPY_BPF
+       int i;
+#endif
+
+ again:
+       /*
+        * Has "pcap_breakloop()" been called?
+        */
+       if (p->break_loop) {
+               /*
+                * Yes - clear the flag that indicates that it
+                * has, and return PCAP_ERROR_BREAK to indicate
+                * that we were told to break out of the loop.
+                */
+               p->break_loop = 0;
+               return (PCAP_ERROR_BREAK);
+       }
+       cc = p->cc;
+       if (p->cc == 0) {
+               /*
+                * When reading without zero-copy from a file descriptor, we
+                * use a single buffer and return a length of data in the
+                * buffer.  With zero-copy, we update the p->buffer pointer
+                * to point at whatever underlying buffer contains the next
+                * data and update cc to reflect the data found in the
+                * buffer.
+                */
+#ifdef HAVE_ZEROCOPY_BPF
+               if (p->md.zerocopy) {
+                       if (p->buffer != NULL)
+                               pcap_ack_zbuf(p);
+                       i = pcap_next_zbuf(p, &cc);
+                       if (i == 0)
+                               goto again;
+                       if (i < 0)
+                               return (PCAP_ERROR);
+               } else
+#endif
+               {
+                       cc = read(p->fd, (char *)p->buffer, p->bufsize);
+               }
+               if (cc < 0) {
+                       /* Don't choke when we get ptraced */
+                       switch (errno) {
+
+                       case EINTR:
+                               goto again;
+
+#ifdef _AIX
+                       case EFAULT:
+                               /*
+                                * Sigh.  More AIX wonderfulness.
+                                *
+                                * For some unknown reason the uiomove()
+                                * operation in the bpf kernel extension
+                                * used to copy the buffer into user
+                                * space sometimes returns EFAULT. I have
+                                * no idea why this is the case given that
+                                * a kernel debugger shows the user buffer
+                                * is correct. This problem appears to
+                                * be mostly mitigated by the memset of
+                                * the buffer before it is first used.
+                                * Very strange.... Shaun Clowes
+                                *
+                                * In any case this means that we shouldn't
+                                * treat EFAULT as a fatal error; as we
+                                * don't have an API for returning
+                                * a "some packets were dropped since
+                                * the last packet you saw" indication,
+                                * we just ignore EFAULT and keep reading.
+                                */
+                               goto again;
+#endif
+
+                       case EWOULDBLOCK:
+                               return (0);
+
+                       case ENXIO:
+                               /*
+                                * The device on which we're capturing
+                                * went away.
+                                *
+                                * XXX - we should really return
+                                * PCAP_ERROR_IFACE_NOT_UP, but
+                                * pcap_dispatch() etc. aren't
+                                * defined to retur that.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "The interface went down");
+                               return (PCAP_ERROR);
+
+#if defined(sun) && !defined(BSD) && !defined(__svr4__) && !defined(__SVR4)
+                       /*
+                        * Due to a SunOS bug, after 2^31 bytes, the kernel
+                        * file offset overflows and read fails with EINVAL.
+                        * The lseek() to 0 will fix things.
+                        */
+                       case EINVAL:
+                               if (lseek(p->fd, 0L, SEEK_CUR) +
+                                   p->bufsize < 0) {
+                                       (void)lseek(p->fd, 0L, SEEK_SET);
+                                       goto again;
+                               }
+                               /* fall through */
+#endif
+                       }
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
+                           pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+               bp = p->buffer;
+       } else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.
+        */
+#define bhp ((struct bpf_hdr *)bp)
+       ep = bp + cc;
+#ifdef PCAP_FDDIPAD
+       pad = p->fddipad;
+#endif
+       while (bp < ep) {
+               register int caplen, hdrlen;
+
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return PCAP_ERROR_BREAK
+                * to indicate that we were told to break out of the loop,
+                * otherwise leave the flag set, so that the *next* call
+                * will break out of the loop without having read any
+                * packets, and return the number of packets we've
+                * processed so far.
+                */
+               if (p->break_loop) {
+                       p->bp = bp;
+                       p->cc = ep - bp;
+                       /*
+                        * ep is set based on the return value of read(),
+                        * but read() from a BPF device doesn't necessarily
+                        * return a value that's a multiple of the alignment
+                        * value for BPF_WORDALIGN().  However, whenever we
+                        * increment bp, we round up the increment value by
+                        * a value rounded up by BPF_WORDALIGN(), so we
+                        * could increment bp past ep after processing the
+                        * last packet in the buffer.
+                        *
+                        * We treat ep < bp as an indication that this
+                        * happened, and just set p->cc to 0.
+                        */
+                       if (p->cc < 0)
+                               p->cc = 0;
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (PCAP_ERROR_BREAK);
+                       } else
+                               return (n);
+               }
+
+               caplen = bhp->bh_caplen;
+               hdrlen = bhp->bh_hdrlen;
+               datap = bp + hdrlen;
+               /*
+                * Short-circuit evaluation: if using BPF filter
+                * in kernel, no need to do it now - we already know
+                * the packet passed the filter.
+                *
+#ifdef PCAP_FDDIPAD
+                * Note: the filter code was generated assuming
+                * that p->fddipad was the amount of padding
+                * before the header, as that's what's required
+                * in the kernel, so we run the filter before
+                * skipping that padding.
+#endif
+                */
+               if (p->md.use_bpf ||
+                   bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+                       struct pcap_pkthdr pkthdr;
+
+                       pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
+#ifdef _AIX
+                       /*
+                        * AIX's BPF returns seconds/nanoseconds time
+                        * stamps, not seconds/microseconds time stamps.
+                        */
+                       pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000;
+#else
+                       pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
+#endif
+#ifdef PCAP_FDDIPAD
+                       if (caplen > pad)
+                               pkthdr.caplen = caplen - pad;
+                       else
+                               pkthdr.caplen = 0;
+                       if (bhp->bh_datalen > pad)
+                               pkthdr.len = bhp->bh_datalen - pad;
+                       else
+                               pkthdr.len = 0;
+                       datap += pad;
+#else
+                       pkthdr.caplen = caplen;
+                       pkthdr.len = bhp->bh_datalen;
+#endif
+                       (*callback)(user, &pkthdr, datap);
+                       bp += BPF_WORDALIGN(caplen + hdrlen);
+                       if (++n >= cnt && cnt > 0) {
+                               p->bp = bp;
+                               p->cc = ep - bp;
+                               /*
+                                * See comment above about p->cc < 0.
+                                */
+                               if (p->cc < 0)
+                                       p->cc = 0;
+                               return (n);
+                       }
+               } else {
+                       /*
+                        * Skip this packet.
+                        */
+                       bp += BPF_WORDALIGN(caplen + hdrlen);
+               }
+       }
+#undef bhp
+       p->cc = 0;
+       return (n);
+}
+
+static int
+pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
+{
+       int ret;
+
+       ret = write(p->fd, buf, size);
+#ifdef __APPLE__
+       if (ret == -1 && errno == EAFNOSUPPORT) {
+               /*
+                * In Mac OS X, there's a bug wherein setting the
+                * BIOCSHDRCMPLT flag causes writes to fail; see,
+                * for example:
+                *
+                *      http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
+                *
+                * So, if, on OS X, we get EAFNOSUPPORT from the write, we
+                * assume it's due to that bug, and turn off that flag
+                * and try again.  If we succeed, it either means that
+                * somebody applied the fix from that URL, or other patches
+                * for that bug from
+                *
+                *      http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/
+                *
+                * and are running a Darwin kernel with those fixes, or
+                * that Apple fixed the problem in some OS X release.
+                */
+               u_int spoof_eth_src = 0;
+
+               if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+                       (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "send: can't turn off BIOCSHDRCMPLT: %s",
+                           pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+
+               /*
+                * Now try the write again.
+                */
+               ret = write(p->fd, buf, size);
+       }
+#endif /* __APPLE__ */
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+       return (ret);
+}
+
+#ifdef _AIX
+static int
+bpf_odminit(char *errbuf)
+{
+       char *errstr;
+
+       if (odm_initialize() == -1) {
+               if (odm_err_msg(odmerrno, &errstr) == -1)
+                       errstr = "Unknown error";
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "bpf_load: odm_initialize failed: %s",
+                   errstr);
+               return (PCAP_ERROR);
+       }
+
+       if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
+               if (odm_err_msg(odmerrno, &errstr) == -1)
+                       errstr = "Unknown error";
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
+                   errstr);
+               (void)odm_terminate();
+               return (PCAP_ERROR);
+       }
+
+       return (0);
+}
+
+static int
+bpf_odmcleanup(char *errbuf)
+{
+       char *errstr;
+
+       if (odm_unlock(odmlockid) == -1) {
+               if (errbuf != NULL) {
+                       if (odm_err_msg(odmerrno, &errstr) == -1)
+                               errstr = "Unknown error";
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "bpf_load: odm_unlock failed: %s",
+                           errstr);
+               }
+               return (PCAP_ERROR);
+       }
+
+       if (odm_terminate() == -1) {
+               if (errbuf != NULL) {
+                       if (odm_err_msg(odmerrno, &errstr) == -1)
+                               errstr = "Unknown error";
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "bpf_load: odm_terminate failed: %s",
+                           errstr);
+               }
+               return (PCAP_ERROR);
+       }
+
+       return (0);
+}
+
+static int
+bpf_load(char *errbuf)
+{
+       long major;
+       int *minors;
+       int numminors, i, rc;
+       char buf[1024];
+       struct stat sbuf;
+       struct bpf_config cfg_bpf;
+       struct cfg_load cfg_ld;
+       struct cfg_kmod cfg_km;
+
+       /*
+        * This is very very close to what happens in the real implementation
+        * but I've fixed some (unlikely) bug situations.
+        */
+       if (bpfloadedflag)
+               return (0);
+
+       if (bpf_odminit(errbuf) == PCAP_ERROR)
+               return (PCAP_ERROR);
+
+       major = genmajor(BPF_NAME);
+       if (major == -1) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "bpf_load: genmajor failed: %s", pcap_strerror(errno));
+               (void)bpf_odmcleanup(NULL);
+               return (PCAP_ERROR);
+       }
+
+       minors = getminor(major, &numminors, BPF_NAME);
+       if (!minors) {
+               minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
+               if (!minors) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "bpf_load: genminor failed: %s",
+                           pcap_strerror(errno));
+                       (void)bpf_odmcleanup(NULL);
+                       return (PCAP_ERROR);
+               }
+       }
+
+       if (bpf_odmcleanup(errbuf) == PCAP_ERROR)
+               return (PCAP_ERROR);
+
+       rc = stat(BPF_NODE "0", &sbuf);
+       if (rc == -1 && errno != ENOENT) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "bpf_load: can't stat %s: %s",
+                   BPF_NODE "0", pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+
+       if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
+               for (i = 0; i < BPF_MINORS; i++) {
+                       sprintf(buf, "%s%d", BPF_NODE, i);
+                       unlink(buf);
+                       if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "bpf_load: can't mknod %s: %s",
+                                   buf, pcap_strerror(errno));
+                               return (PCAP_ERROR);
+                       }
+               }
+       }
+
+       /* Check if the driver is loaded */
+       memset(&cfg_ld, 0x0, sizeof(cfg_ld));
+       cfg_ld.path = buf;
+       sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME);
+       if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) ||
+           (cfg_ld.kmid == 0)) {
+               /* Driver isn't loaded, load it now */
+               if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "bpf_load: could not load driver: %s",
+                           strerror(errno));
+                       return (PCAP_ERROR);
+               }
+       }
+
+       /* Configure the driver */
+       cfg_km.cmd = CFG_INIT;
+       cfg_km.kmid = cfg_ld.kmid;
+       cfg_km.mdilen = sizeof(cfg_bpf);
+       cfg_km.mdiptr = (void *)&cfg_bpf;
+       for (i = 0; i < BPF_MINORS; i++) {
+               cfg_bpf.devno = domakedev(major, i);
+               if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "bpf_load: could not configure driver: %s",
+                           strerror(errno));
+                       return (PCAP_ERROR);
+               }
+       }
+
+       bpfloadedflag = 1;
+
+       return (0);
+}
+#endif
+
+/*
+ * Turn off rfmon mode if necessary.
+ */
+static void
+pcap_cleanup_bpf(pcap_t *p)
+{
+#ifdef HAVE_BSD_IEEE80211
+       int sock;
+       struct ifmediareq req;
+       struct ifreq ifr;
+#endif
+
+       if (p->md.must_do_on_close != 0) {
+               /*
+                * There's something we have to do when closing this
+                * pcap_t.
+                */
+#ifdef HAVE_BSD_IEEE80211
+               if (p->md.must_do_on_close & MUST_CLEAR_RFMON) {
+                       /*
+                        * We put the interface into rfmon mode;
+                        * take it out of rfmon mode.
+                        *
+                        * XXX - if somebody else wants it in rfmon
+                        * mode, this code cannot know that, so it'll take
+                        * it out of rfmon mode.
+                        */
+                       sock = socket(AF_INET, SOCK_DGRAM, 0);
+                       if (sock == -1) {
+                               fprintf(stderr,
+                                   "Can't restore interface flags (socket() failed: %s).\n"
+                                   "Please adjust manually.\n",
+                                   strerror(errno));
+                       } else {
+                               memset(&req, 0, sizeof(req));
+                               strncpy(req.ifm_name, p->md.device,
+                                   sizeof(req.ifm_name));
+                               if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+                                       fprintf(stderr,
+                                           "Can't restore interface flags (SIOCGIFMEDIA failed: %s).\n"
+                                           "Please adjust manually.\n",
+                                           strerror(errno));
+                               } else {
+                                       if (req.ifm_current & IFM_IEEE80211_MONITOR) {
+                                               /*
+                                                * Rfmon mode is currently on;
+                                                * turn it off.
+                                                */
+                                               memset(&ifr, 0, sizeof(ifr));
+                                               (void)strncpy(ifr.ifr_name,
+                                                   p->md.device,
+                                                   sizeof(ifr.ifr_name));
+                                               ifr.ifr_media =
+                                                   req.ifm_current & ~IFM_IEEE80211_MONITOR;
+                                               if (ioctl(sock, SIOCSIFMEDIA,
+                                                   &ifr) == -1) {
+                                                       fprintf(stderr,
+                                                           "Can't restore interface flags (SIOCSIFMEDIA failed: %s).\n"
+                                                           "Please adjust manually.\n",
+                                                           strerror(errno));
+                                               }
+                                       }
+                               }
+                               close(sock);
+                       }
+               }
+#endif /* HAVE_BSD_IEEE80211 */
+
+               /*
+                * Take this pcap out of the list of pcaps for which we
+                * have to take the interface out of some mode.
+                */
+               pcap_remove_from_pcaps_to_close(p);
+               p->md.must_do_on_close = 0;
+       }
+
+#ifdef HAVE_ZEROCOPY_BPF
+       if (p->md.zerocopy) {
+               /*
+                * Delete the mappings.  Note that p->buffer gets
+                * initialized to one of the mmapped regions in
+                * this case, so do not try and free it directly;
+                * null it out so that pcap_cleanup_live_common()
+                * doesn't try to free it.
+                */
+               if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
+                       (void) munmap(p->md.zbuf1, p->md.zbufsize);
+               if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
+                       (void) munmap(p->md.zbuf2, p->md.zbufsize);
+               p->buffer = NULL;
+       }
+#endif
+       if (p->md.device != NULL) {
+               free(p->md.device);
+               p->md.device = NULL;
+       }
+       pcap_cleanup_live_common(p);
+}
+
+static int
+check_setif_failure(pcap_t *p, int error)
+{
+#ifdef __APPLE__
+       int fd;
+       struct ifreq ifr;
+       int err;
+#endif
+
+       if (error == ENXIO) {
+               /*
+                * No such device exists.
+                */
+#ifdef __APPLE__
+               if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) {
+                       /*
+                        * Monitor mode was requested, and we're trying
+                        * to open a "wltN" device.  Assume that this
+                        * is 10.4 and that we were asked to open an
+                        * "enN" device; if that device exists, return
+                        * "monitor mode not supported on the device".
+                        */
+                       fd = socket(AF_INET, SOCK_DGRAM, 0);
+                       if (fd != -1) {
+                               strlcpy(ifr.ifr_name, "en",
+                                   sizeof(ifr.ifr_name));
+                               strlcat(ifr.ifr_name, p->opt.source + 3,
+                                   sizeof(ifr.ifr_name));
+                               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+                                       /*
+                                        * We assume this failed because
+                                        * the underlying device doesn't
+                                        * exist.
+                                        */
+                                       err = PCAP_ERROR_NO_SUCH_DEVICE;
+                                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                           "SIOCGIFFLAGS on %s failed: %s",
+                                           ifr.ifr_name, pcap_strerror(errno));
+                               } else {
+                                       /*
+                                        * The underlying "enN" device
+                                        * exists, but there's no
+                                        * corresponding "wltN" device;
+                                        * that means that the "enN"
+                                        * device doesn't support
+                                        * monitor mode, probably because
+                                        * it's an Ethernet device rather
+                                        * than a wireless device.
+                                        */
+                                       err = PCAP_ERROR_RFMON_NOTSUP;
+                               }
+                               close(fd);
+                       } else {
+                               /*
+                                * We can't find out whether there's
+                                * an underlying "enN" device, so
+                                * just report "no such device".
+                                */
+                               err = PCAP_ERROR_NO_SUCH_DEVICE;
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "socket() failed: %s",
+                                   pcap_strerror(errno));
+                       }
+                       return (err);
+               }
+#endif
+               /*
+                * No such device.
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
+                   pcap_strerror(errno));
+               return (PCAP_ERROR_NO_SUCH_DEVICE);
+       } else if (errno == ENETDOWN) {
+               /*
+                * Return a "network down" indication, so that
+                * the application can report that rather than
+                * saying we had a mysterious failure and
+                * suggest that they report a problem to the
+                * libpcap developers.
+                */
+               return (PCAP_ERROR_IFACE_NOT_UP);
+       } else {
+               /*
+                * Some other error; fill in the error string, and
+                * return PCAP_ERROR.
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+                   p->opt.source, pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+}
+
+/*
+ * Default capture buffer size.
+ * 32K isn't very much for modern machines with fast networks; we
+ * pick .5M, as that's the maximum on at least some systems with BPF.
+ *
+ * However, on AIX 3.5, the larger buffer sized caused unrecoverable
+ * read failures under stress, so we leave it as 32K; yet another
+ * place where AIX's BPF is broken.
+ */
+#ifdef _AIX
+#define DEFAULT_BUFSIZE        32768
+#else
+#define DEFAULT_BUFSIZE        524288
+#endif
+
+static int
+pcap_activate_bpf(pcap_t *p)
+{
+       int status = 0;
+       int fd;
+#ifdef LIFNAMSIZ
+       char *zonesep;
+       struct lifreq ifr;
+       char *ifrname = ifr.lifr_name;
+       const size_t ifnamsiz = sizeof(ifr.lifr_name);
+#else
+       struct ifreq ifr;
+       char *ifrname = ifr.ifr_name;
+       const size_t ifnamsiz = sizeof(ifr.ifr_name);
+#endif
+       struct bpf_version bv;
+#ifdef __APPLE__
+       int sockfd;
+       char *wltdev = NULL;
+#endif
+#ifdef BIOCGDLTLIST
+       struct bpf_dltlist bdl;
+#if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+       int new_dlt;
+#endif
+#endif /* BIOCGDLTLIST */
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+       u_int spoof_eth_src = 1;
+#endif
+       u_int v;
+       struct bpf_insn total_insn;
+       struct bpf_program total_prog;
+       struct utsname osinfo;
+       int have_osinfo = 0;
+#ifdef HAVE_ZEROCOPY_BPF
+       struct bpf_zbuf bz;
+       u_int bufmode, zbufmax;
+#endif
+
+       fd = bpf_open(p);
+       if (fd < 0) {
+               status = fd;
+               goto bad;
+       }
+
+       p->fd = fd;
+
+       if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+       if (bv.bv_major != BPF_MAJOR_VERSION ||
+           bv.bv_minor < BPF_MINOR_VERSION) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "kernel bpf filter out of date");
+               status = PCAP_ERROR;
+               goto bad;
+       }
+
+#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
+       /*
+        * Check if the given source network device has a '/' separated
+        * zonename prefix string. The zonename prefixed source device
+        * can be used by libpcap consumers to capture network traffic
+        * in non-global zones from the global zone on Solaris 11 and
+        * above. If the zonename prefix is present then we strip the
+        * prefix and pass the zone ID as part of lifr_zoneid.
+        */
+       if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
+               char zonename[ZONENAME_MAX];
+               int  znamelen;
+               char *lnamep;
+
+               znamelen = zonesep - p->opt.source;
+               (void) strlcpy(zonename, p->opt.source, znamelen + 1);
+               lnamep = strdup(zonesep + 1);
+               ifr.lifr_zoneid = getzoneidbyname(zonename);
+               free(p->opt.source);
+               p->opt.source = lnamep;
+       }
+#endif
+
+       p->md.device = strdup(p->opt.source);
+       if (p->md.device == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+                    pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+
+       /*
+        * Attempt to find out the version of the OS on which we're running.
+        */
+       if (uname(&osinfo) == 0)
+               have_osinfo = 1;
+
+#ifdef __APPLE__
+       /*
+        * See comment in pcap_can_set_rfmon_bpf() for an explanation
+        * of why we check the version number.
+        */
+       if (p->opt.rfmon) {
+               if (have_osinfo) {
+                       /*
+                        * We assume osinfo.sysname is "Darwin", because
+                        * __APPLE__ is defined.  We just check the version.
+                        */
+                       if (osinfo.release[0] < '8' &&
+                           osinfo.release[1] == '.') {
+                               /*
+                                * 10.3 (Darwin 7.x) or earlier.
+                                */
+                               status = PCAP_ERROR_RFMON_NOTSUP;
+                               goto bad;
+                       }
+                       if (osinfo.release[0] == '8' &&
+                           osinfo.release[1] == '.') {
+                               /*
+                                * 10.4 (Darwin 8.x).  s/en/wlt/
+                                */
+                               if (strncmp(p->opt.source, "en", 2) != 0) {
+                                       /*
+                                        * Not an enN device; check
+                                        * whether the device even exists.
+                                        */
+                                       sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+                                       if (sockfd != -1) {
+                                               strlcpy(ifrname,
+                                                   p->opt.source, ifnamsiz);
+                                               if (ioctl(sockfd, SIOCGIFFLAGS,
+                                                   (char *)&ifr) < 0) {
+                                                       /*
+                                                        * We assume this
+                                                        * failed because
+                                                        * the underlying
+                                                        * device doesn't
+                                                        * exist.
+                                                        */
+                                                       status = PCAP_ERROR_NO_SUCH_DEVICE;
+                                                       snprintf(p->errbuf,
+                                                           PCAP_ERRBUF_SIZE,
+                                                           "SIOCGIFFLAGS failed: %s",
+                                                           pcap_strerror(errno));
+                                               } else
+                                                       status = PCAP_ERROR_RFMON_NOTSUP;
+                                               close(sockfd);
+                                       } else {
+                                               /*
+                                                * We can't find out whether
+                                                * the device exists, so just
+                                                * report "no such device".
+                                                */
+                                               status = PCAP_ERROR_NO_SUCH_DEVICE;
+                                               snprintf(p->errbuf,
+                                                   PCAP_ERRBUF_SIZE,
+                                                   "socket() failed: %s",
+                                                   pcap_strerror(errno));
+                                       }
+                                       goto bad;
+                               }
+                               wltdev = malloc(strlen(p->opt.source) + 2);
+                               if (wltdev == NULL) {
+                                       (void)snprintf(p->errbuf,
+                                           PCAP_ERRBUF_SIZE, "malloc: %s",
+                                           pcap_strerror(errno));
+                                       status = PCAP_ERROR;
+                                       goto bad;
+                               }
+                               strcpy(wltdev, "wlt");
+                               strcat(wltdev, p->opt.source + 2);
+                               free(p->opt.source);
+                               p->opt.source = wltdev;
+                       }
+                       /*
+                        * Everything else is 10.5 or later; for those,
+                        * we just open the enN device, and set the DLT.
+                        */
+               }
+       }
+#endif /* __APPLE__ */
+#ifdef HAVE_ZEROCOPY_BPF
+       /*
+        * If the BPF extension to set buffer mode is present, try setting
+        * the mode to zero-copy.  If that fails, use regular buffering.  If
+        * it succeeds but other setup fails, return an error to the user.
+        */
+       bufmode = BPF_BUFMODE_ZBUF;
+       if (ioctl(fd, BIOCSETBUFMODE, (caddr_t)&bufmode) == 0) {
+               /*
+                * We have zerocopy BPF; use it.
+                */
+               p->md.zerocopy = 1;
+
+               /*
+                * How to pick a buffer size: first, query the maximum buffer
+                * size supported by zero-copy.  This also lets us quickly
+                * determine whether the kernel generally supports zero-copy.
+                * Then, if a buffer size was specified, use that, otherwise
+                * query the default buffer size, which reflects kernel
+                * policy for a desired default.  Round to the nearest page
+                * size.
+                */
+               if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
+                           pcap_strerror(errno));
+                       goto bad;
+               }
+
+               if (p->opt.buffer_size != 0) {
+                       /*
+                        * A buffer size was explicitly specified; use it.
+                        */
+                       v = p->opt.buffer_size;
+               } else {
+                       if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+                           v < DEFAULT_BUFSIZE)
+                               v = DEFAULT_BUFSIZE;
+               }
+#ifndef roundup
+#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))  /* to any y */
+#endif
+               p->md.zbufsize = roundup(v, getpagesize());
+               if (p->md.zbufsize > zbufmax)
+                       p->md.zbufsize = zbufmax;
+               p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
+                   MAP_ANON, -1, 0);
+               p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
+                   MAP_ANON, -1, 0);
+               if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
+                           pcap_strerror(errno));
+                       goto bad;
+               }
+               bzero(&bz, sizeof(bz));
+               bz.bz_bufa = p->md.zbuf1;
+               bz.bz_bufb = p->md.zbuf2;
+               bz.bz_buflen = p->md.zbufsize;
+               if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
+                           pcap_strerror(errno));
+                       goto bad;
+               }
+               (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+               if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+                           p->opt.source, pcap_strerror(errno));
+                       goto bad;
+               }
+               v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
+       } else
+#endif
+       {
+               /*
+                * We don't have zerocopy BPF.
+                * Set the buffer size.
+                */
+               if (p->opt.buffer_size != 0) {
+                       /*
+                        * A buffer size was explicitly specified; use it.
+                        */
+                       if (ioctl(fd, BIOCSBLEN,
+                           (caddr_t)&p->opt.buffer_size) < 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BIOCSBLEN: %s: %s", p->opt.source,
+                                   pcap_strerror(errno));
+                               status = PCAP_ERROR;
+                               goto bad;
+                       }
+
+                       /*
+                        * Now bind to the device.
+                        */
+                       (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+#ifdef BIOCSETLIF
+                       if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
+#else
+                       if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0)
+#endif
+                       {
+                               status = check_setif_failure(p, errno);
+                               goto bad;
+                       }
+               } else {
+                       /*
+                        * No buffer size was explicitly specified.
+                        *
+                        * Try finding a good size for the buffer;
+                        * DEFAULT_BUFSIZE may be too big, so keep
+                        * cutting it in half until we find a size
+                        * that works, or run out of sizes to try.
+                        * If the default is larger, don't make it smaller.
+                        */
+                       if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+                           v < DEFAULT_BUFSIZE)
+                               v = DEFAULT_BUFSIZE;
+                       for ( ; v != 0; v >>= 1) {
+                               /*
+                                * Ignore the return value - this is because the
+                                * call fails on BPF systems that don't have
+                                * kernel malloc.  And if the call fails, it's
+                                * no big deal, we just continue to use the
+                                * standard buffer size.
+                                */
+                               (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
+
+                               (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+#ifdef BIOCSETLIF
+                               if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
+#else
+                               if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
+#endif
+                                       break;  /* that size worked; we're done */
+
+                               if (errno != ENOBUFS) {
+                                       status = check_setif_failure(p, errno);
+                                       goto bad;
+                               }
+                       }
+
+                       if (v == 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BIOCSBLEN: %s: No buffer size worked",
+                                   p->opt.source);
+                               status = PCAP_ERROR;
+                               goto bad;
+                       }
+               }
+       }
+
+       /* Get the data link layer type. */
+       if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+
+#ifdef _AIX
+       /*
+        * AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT.
+        */
+       switch (v) {
+
+       case IFT_ETHER:
+       case IFT_ISO88023:
+               v = DLT_EN10MB;
+               break;
+
+       case IFT_FDDI:
+               v = DLT_FDDI;
+               break;
+
+       case IFT_ISO88025:
+               v = DLT_IEEE802;
+               break;
+
+       case IFT_LOOP:
+               v = DLT_NULL;
+               break;
+
+       default:
+               /*
+                * We don't know what to map this to yet.
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+                   v);
+               status = PCAP_ERROR;
+               goto bad;
+       }
+#endif
+#if _BSDI_VERSION - 0 >= 199510
+       /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
+       switch (v) {
+
+       case DLT_SLIP:
+               v = DLT_SLIP_BSDOS;
+               break;
+
+       case DLT_PPP:
+               v = DLT_PPP_BSDOS;
+               break;
+
+       case 11:        /*DLT_FR*/
+               v = DLT_FRELAY;
+               break;
+
+       case 12:        /*DLT_C_HDLC*/
+               v = DLT_CHDLC;
+               break;
+       }
+#endif
+
+#ifdef BIOCGDLTLIST
+       /*
+        * We know the default link type -- now determine all the DLTs
+        * this interface supports.  If this fails with EINVAL, it's
+        * not fatal; we just don't get to use the feature later.
+        */
+       if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) {
+               status = PCAP_ERROR;
+               goto bad;
+       }
+       p->dlt_count = bdl.bfl_len;
+       p->dlt_list = bdl.bfl_list;
+
+#ifdef __APPLE__
+       /*
+        * Monitor mode fun, continued.
+        *
+        * For 10.5 and, we're assuming, later releases, as noted above,
+        * 802.1 adapters that support monitor mode offer both DLT_EN10MB,
+        * DLT_IEEE802_11, and possibly some 802.11-plus-radio-information
+        * DLT_ value.  Choosing one of the 802.11 DLT_ values will turn
+        * monitor mode on.
+        *
+        * Therefore, if the user asked for monitor mode, we filter out
+        * the DLT_EN10MB value, as you can't get that in monitor mode,
+        * and, if the user didn't ask for monitor mode, we filter out
+        * the 802.11 DLT_ values, because selecting those will turn
+        * monitor mode on.  Then, for monitor mode, if an 802.11-plus-
+        * radio DLT_ value is offered, we try to select that, otherwise
+        * we try to select DLT_IEEE802_11.
+        */
+       if (have_osinfo) {
+               if (isdigit((unsigned)osinfo.release[0]) &&
+                    (osinfo.release[0] == '9' ||
+                    isdigit((unsigned)osinfo.release[1]))) {
+                       /*
+                        * 10.5 (Darwin 9.x), or later.
+                        */
+                       new_dlt = find_802_11(&bdl);
+                       if (new_dlt != -1) {
+                               /*
+                                * We have at least one 802.11 DLT_ value,
+                                * so this is an 802.11 interface.
+                                * new_dlt is the best of the 802.11
+                                * DLT_ values in the list.
+                                */
+                               if (p->opt.rfmon) {
+                                       /*
+                                        * Our caller wants monitor mode.
+                                        * Purge DLT_EN10MB from the list
+                                        * of link-layer types, as selecting
+                                        * it will keep monitor mode off.
+                                        */
+                                       remove_en(p);
+
+                                       /*
+                                        * If the new mode we want isn't
+                                        * the default mode, attempt to
+                                        * select the new mode.
+                                        */
+                                       if (new_dlt != v) {
+                                               if (ioctl(p->fd, BIOCSDLT,
+                                                   &new_dlt) != -1) {
+                                                       /*
+                                                        * We succeeded;
+                                                        * make this the
+                                                        * new DLT_ value.
+                                                        */
+                                                       v = new_dlt;
+                                               }
+                                       }
+                               } else {
+                                       /*
+                                        * Our caller doesn't want
+                                        * monitor mode.  Unless this
+                                        * is being done by pcap_open_live(),
+                                        * purge the 802.11 link-layer types
+                                        * from the list, as selecting
+                                        * one of them will turn monitor
+                                        * mode on.
+                                        */
+                                       if (!p->oldstyle)
+                                               remove_802_11(p);
+                               }
+                       } else {
+                               if (p->opt.rfmon) {
+                                       /*
+                                        * The caller requested monitor
+                                        * mode, but we have no 802.11
+                                        * link-layer types, so they
+                                        * can't have it.
+                                        */
+                                       status = PCAP_ERROR_RFMON_NOTSUP;
+                                       goto bad;
+                               }
+                       }
+               }
+       }
+#elif defined(HAVE_BSD_IEEE80211)
+       /*
+        * *BSD with the new 802.11 ioctls.
+        * Do we want monitor mode?
+        */
+       if (p->opt.rfmon) {
+               /*
+                * Try to put the interface into monitor mode.
+                */
+               status = monitor_mode(p, 1);
+               if (status != 0) {
+                       /*
+                        * We failed.
+                        */
+                       goto bad;
+               }
+
+               /*
+                * We're in monitor mode.
+                * Try to find the best 802.11 DLT_ value and, if we
+                * succeed, try to switch to that mode if we're not
+                * already in that mode.
+                */
+               new_dlt = find_802_11(&bdl);
+               if (new_dlt != -1) {
+                       /*
+                        * We have at least one 802.11 DLT_ value.
+                        * new_dlt is the best of the 802.11
+                        * DLT_ values in the list.
+                        *
+                        * If the new mode we want isn't the default mode,
+                        * attempt to select the new mode.
+                        */
+                       if (new_dlt != v) {
+                               if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
+                                       /*
+                                        * We succeeded; make this the
+                                        * new DLT_ value.
+                                        */
+                                       v = new_dlt;
+                               }
+                       }
+               }
+       }
+#endif /* various platforms */
+#endif /* BIOCGDLTLIST */
+
+       /*
+        * If this is an Ethernet device, and we don't have a DLT_ list,
+        * give it a list with DLT_EN10MB and DLT_DOCSIS.  (That'd give
+        * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to
+        * do, but there's not much we can do about that without finding
+        * some other way of determining whether it's an Ethernet or 802.11
+        * device.)
+        */
+       if (v == DLT_EN10MB && p->dlt_count == 0) {
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+       }
+#ifdef PCAP_FDDIPAD
+       if (v == DLT_FDDI)
+               p->fddipad = PCAP_FDDIPAD;
+       else
+               p->fddipad = 0;
+#endif
+       p->linktype = v;
+
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+       /*
+        * Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so
+        * the link-layer source address isn't forcibly overwritten.
+        * (Should we ignore errors?  Should we do this only if
+        * we're open for writing?)
+        *
+        * XXX - I seem to remember some packet-sending bug in some
+        * BSDs - check CVS log for "bpf.c"?
+        */
+       if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+               (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "BIOCSHDRCMPLT: %s", pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+#endif
+       /* set timeout */
+#ifdef HAVE_ZEROCOPY_BPF
+       if (p->md.timeout != 0 && !p->md.zerocopy) {
+#else
+       if (p->md.timeout) {
+#endif
+               /*
+                * XXX - is this seconds/nanoseconds in AIX?
+                * (Treating it as such doesn't fix the timeout
+                * problem described below.)
+                *
+                * XXX - Mac OS X 10.6 mishandles BIOCSRTIMEOUT in
+                * 64-bit userland - it takes, as an argument, a
+                * "struct BPF_TIMEVAL", which has 32-bit tv_sec
+                * and tv_usec, rather than a "struct timeval".
+                *
+                * If this platform defines "struct BPF_TIMEVAL",
+                * we check whether the structure size in BIOCSRTIMEOUT
+                * is that of a "struct timeval" and, if not, we use
+                * a "struct BPF_TIMEVAL" rather than a "struct timeval".
+                * (That way, if the bug is fixed in a future release,
+                * we will still do the right thing.)
+                */
+               struct timeval to;
+#ifdef HAVE_STRUCT_BPF_TIMEVAL
+               struct BPF_TIMEVAL bpf_to;
+
+               if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) {
+                       bpf_to.tv_sec = p->md.timeout / 1000;
+                       bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000;
+                       if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+                               status = PCAP_ERROR;
+                               goto bad;
+                       }
+               } else {
+#endif
+                       to.tv_sec = p->md.timeout / 1000;
+                       to.tv_usec = (p->md.timeout * 1000) % 1000000;
+                       if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+                               status = PCAP_ERROR;
+                               goto bad;
+                       }
+#ifdef HAVE_STRUCT_BPF_TIMEVAL
+               }
+#endif
+       }
+
+#ifdef _AIX
+#ifdef BIOCIMMEDIATE
+       /*
+        * Darren Reed notes that
+        *
+        *      On AIX (4.2 at least), if BIOCIMMEDIATE is not set, the
+        *      timeout appears to be ignored and it waits until the buffer
+        *      is filled before returning.  The result of not having it
+        *      set is almost worse than useless if your BPF filter
+        *      is reducing things to only a few packets (i.e. one every
+        *      second or so).
+        *
+        * so we turn BIOCIMMEDIATE mode on if this is AIX.
+        *
+        * We don't turn it on for other platforms, as that means we
+        * get woken up for every packet, which may not be what we want;
+        * in the Winter 1993 USENIX paper on BPF, they say:
+        *
+        *      Since a process might want to look at every packet on a
+        *      network and the time between packets can be only a few
+        *      microseconds, it is not possible to do a read system call
+        *      per packet and BPF must collect the data from several
+        *      packets and return it as a unit when the monitoring
+        *      application does a read.
+        *
+        * which I infer is the reason for the timeout - it means we
+        * wait that amount of time, in the hopes that more packets
+        * will arrive and we'll get them all with one read.
+        *
+        * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other
+        * BSDs) causes the timeout to be ignored.
+        *
+        * On the other hand, some platforms (e.g., Linux) don't support
+        * timeouts, they just hand stuff to you as soon as it arrives;
+        * if that doesn't cause a problem on those platforms, it may
+        * be OK to have BIOCIMMEDIATE mode on BSD as well.
+        *
+        * (Note, though, that applications may depend on the read
+        * completing, even if no packets have arrived, when the timeout
+        * expires, e.g. GUI applications that have to check for input
+        * while waiting for packets to arrive; a non-zero timeout
+        * prevents "select()" from working right on FreeBSD and
+        * possibly other BSDs, as the timer doesn't start until a
+        * "read()" is done, so the timer isn't in effect if the
+        * application is blocked on a "select()", and the "select()"
+        * doesn't get woken up for a BPF device until the buffer
+        * fills up.)
+        */
+       v = 1;
+       if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+#endif /* BIOCIMMEDIATE */
+#endif /* _AIX */
+
+       if (p->opt.promisc) {
+               /* set promiscuous mode, just warn if it fails */
+               if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
+                           pcap_strerror(errno));
+                       status = PCAP_WARNING_PROMISC_NOTSUP;
+               }
+       }
+
+       if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+       p->bufsize = v;
+#ifdef HAVE_ZEROCOPY_BPF
+       if (!p->md.zerocopy) {
+#endif
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+#ifdef _AIX
+       /* For some strange reason this seems to prevent the EFAULT
+        * problems we have experienced from AIX BPF. */
+       memset(p->buffer, 0x0, p->bufsize);
+#endif
+#ifdef HAVE_ZEROCOPY_BPF
+       }
+#endif
+
+       /*
+        * If there's no filter program installed, there's
+        * no indication to the kernel of what the snapshot
+        * length should be, so no snapshotting is done.
+        *
+        * Therefore, when we open the device, we install
+        * an "accept everything" filter with the specified
+        * snapshot length.
+        */
+       total_insn.code = (u_short)(BPF_RET | BPF_K);
+       total_insn.jt = 0;
+       total_insn.jf = 0;
+       total_insn.k = p->snapshot;
+
+       total_prog.bf_len = 1;
+       total_prog.bf_insns = &total_insn;
+       if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+                   pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto bad;
+       }
+
+       /*
+        * On most BPF platforms, either you can do a "select()" or
+        * "poll()" on a BPF file descriptor and it works correctly,
+        * or you can do it and it will return "readable" if the
+        * hold buffer is full but not if the timeout expires *and*
+        * a non-blocking read will, if the hold buffer is empty
+        * but the store buffer isn't empty, rotate the buffers
+        * and return what packets are available.
+        *
+        * In the latter case, the fact that a non-blocking read
+        * will give you the available packets means you can work
+        * around the failure of "select()" and "poll()" to wake up
+        * and return "readable" when the timeout expires by using
+        * the timeout as the "select()" or "poll()" timeout, putting
+        * the BPF descriptor into non-blocking mode, and read from
+        * it regardless of whether "select()" reports it as readable
+        * or not.
+        *
+        * However, in FreeBSD 4.3 and 4.4, "select()" and "poll()"
+        * won't wake up and return "readable" if the timer expires
+        * and non-blocking reads return EWOULDBLOCK if the hold
+        * buffer is empty, even if the store buffer is non-empty.
+        *
+        * This means the workaround in question won't work.
+        *
+        * Therefore, on FreeBSD 4.3 and 4.4, we set "p->selectable_fd"
+        * to -1, which means "sorry, you can't use 'select()' or 'poll()'
+        * here".  On all other BPF platforms, we set it to the FD for
+        * the BPF device; in NetBSD, OpenBSD, and Darwin, a non-blocking
+        * read will, if the hold buffer is empty and the store buffer
+        * isn't empty, rotate the buffers and return what packets are
+        * there (and in sufficiently recent versions of OpenBSD
+        * "select()" and "poll()" should work correctly).
+        *
+        * XXX - what about AIX?
+        */
+       p->selectable_fd = p->fd;       /* assume select() works until we know otherwise */
+       if (have_osinfo) {
+               /*
+                * We can check what OS this is.
+                */
+               if (strcmp(osinfo.sysname, "FreeBSD") == 0) {
+                       if (strncmp(osinfo.release, "4.3-", 4) == 0 ||
+                            strncmp(osinfo.release, "4.4-", 4) == 0)
+                               p->selectable_fd = -1;
+               }
+       }
+
+       p->read_op = pcap_read_bpf;
+       p->inject_op = pcap_inject_bpf;
+       p->setfilter_op = pcap_setfilter_bpf;
+       p->setdirection_op = pcap_setdirection_bpf;
+       p->set_datalink_op = pcap_set_datalink_bpf;
+       p->getnonblock_op = pcap_getnonblock_bpf;
+       p->setnonblock_op = pcap_setnonblock_bpf;
+       p->stats_op = pcap_stats_bpf;
+       p->cleanup_op = pcap_cleanup_bpf;
+
+       return (status);
+ bad:
+       pcap_cleanup_bpf(p);
+       return (status);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+#ifdef HAVE_DAG_API
+       if (dag_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif /* HAVE_DAG_API */
+#ifdef HAVE_SNF_API
+       if (snf_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif /* HAVE_SNF_API */
+
+       return (0);
+}
+
+#ifdef HAVE_BSD_IEEE80211
+static int
+monitor_mode(pcap_t *p, int set)
+{
+       int sock;
+       struct ifmediareq req;
+       int *media_list;
+       int i;
+       int can_do;
+       struct ifreq ifr;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
+                   pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+
+       memset(&req, 0, sizeof req);
+       strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+
+       /*
+        * Find out how many media types we have.
+        */
+       if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+               /*
+                * Can't get the media types.
+                */
+               switch (errno) {
+
+               case ENXIO:
+                       /*
+                        * There's no such device.
+                        */
+                       close(sock);
+                       return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+               case EINVAL:
+                       /*
+                        * Interface doesn't support SIOC{G,S}IFMEDIA.
+                        */
+                       close(sock);
+                       return (PCAP_ERROR_RFMON_NOTSUP);
+
+               default:
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
+                       close(sock);
+                       return (PCAP_ERROR);
+               }
+       }
+       if (req.ifm_count == 0) {
+               /*
+                * No media types.
+                */
+               close(sock);
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+       /*
+        * Allocate a buffer to hold all the media types, and
+        * get the media types.
+        */
+       media_list = malloc(req.ifm_count * sizeof(int));
+       if (media_list == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                   pcap_strerror(errno));
+               close(sock);
+               return (PCAP_ERROR);
+       }
+       req.ifm_ulist = media_list;
+       if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
+                   pcap_strerror(errno));
+               free(media_list);
+               close(sock);
+               return (PCAP_ERROR);
+       }
+
+       /*
+        * Look for an 802.11 "automatic" media type.
+        * We assume that all 802.11 adapters have that media type,
+        * and that it will carry the monitor mode supported flag.
+        */
+       can_do = 0;
+       for (i = 0; i < req.ifm_count; i++) {
+               if (IFM_TYPE(media_list[i]) == IFM_IEEE80211
+                   && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) {
+                       /* OK, does it do monitor mode? */
+                       if (media_list[i] & IFM_IEEE80211_MONITOR) {
+                               can_do = 1;
+                               break;
+                       }
+               }
+       }
+       free(media_list);
+       if (!can_do) {
+               /*
+                * This adapter doesn't support monitor mode.
+                */
+               close(sock);
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+       if (set) {
+               /*
+                * Don't just check whether we can enable monitor mode,
+                * do so, if it's not already enabled.
+                */
+               if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) {
+                       /*
+                        * Monitor mode isn't currently on, so turn it on,
+                        * and remember that we should turn it off when the
+                        * pcap_t is closed.
+                        */
+
+                       /*
+                        * If we haven't already done so, arrange to have
+                        * "pcap_close_all()" called when we exit.
+                        */
+                       if (!pcap_do_addexit(p)) {
+                               /*
+                                * "atexit()" failed; don't put the interface
+                                * in monitor mode, just give up.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                    "atexit failed");
+                               close(sock);
+                               return (PCAP_ERROR);
+                       }
+                       memset(&ifr, 0, sizeof(ifr));
+                       (void)strncpy(ifr.ifr_name, p->opt.source,
+                           sizeof(ifr.ifr_name));
+                       ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
+                       if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                    "SIOCSIFMEDIA: %s", pcap_strerror(errno));
+                               close(sock);
+                               return (PCAP_ERROR);
+                       }
+
+                       p->md.must_do_on_close |= MUST_CLEAR_RFMON;
+
+                       /*
+                        * Add this to the list of pcaps to close when we exit.
+                        */
+                       pcap_add_to_pcaps_to_close(p);
+               }
+       }
+       return (0);
+}
+#endif /* HAVE_BSD_IEEE80211 */
+
+#if defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211))
+/*
+ * Check whether we have any 802.11 link-layer types; return the best
+ * of the 802.11 link-layer types if we find one, and return -1
+ * otherwise.
+ *
+ * DLT_IEEE802_11_RADIO, with the radiotap header, is considered the
+ * best 802.11 link-layer type; any of the other 802.11-plus-radio
+ * headers are second-best; 802.11 with no radio information is
+ * the least good.
+ */
+static int
+find_802_11(struct bpf_dltlist *bdlp)
+{
+       int new_dlt;
+       int i;
+
+       /*
+        * Scan the list of DLT_ values, looking for 802.11 values,
+        * and, if we find any, choose the best of them.
+        */
+       new_dlt = -1;
+       for (i = 0; i < bdlp->bfl_len; i++) {
+               switch (bdlp->bfl_list[i]) {
+
+               case DLT_IEEE802_11:
+                       /*
+                        * 802.11, but no radio.
+                        *
+                        * Offer this, and select it as the new mode
+                        * unless we've already found an 802.11
+                        * header with radio information.
+                        */
+                       if (new_dlt == -1)
+                               new_dlt = bdlp->bfl_list[i];
+                       break;
+
+               case DLT_PRISM_HEADER:
+               case DLT_AIRONET_HEADER:
+               case DLT_IEEE802_11_RADIO_AVS:
+                       /*
+                        * 802.11 with radio, but not radiotap.
+                        *
+                        * Offer this, and select it as the new mode
+                        * unless we've already found the radiotap DLT_.
+                        */
+                       if (new_dlt != DLT_IEEE802_11_RADIO)
+                               new_dlt = bdlp->bfl_list[i];
+                       break;
+
+               case DLT_IEEE802_11_RADIO:
+                       /*
+                        * 802.11 with radiotap.
+                        *
+                        * Offer this, and select it as the new mode.
+                        */
+                       new_dlt = bdlp->bfl_list[i];
+                       break;
+
+               default:
+                       /*
+                        * Not 802.11.
+                        */
+                       break;
+               }
+       }
+
+       return (new_dlt);
+}
+#endif /* defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)) */
+
+#if defined(__APPLE__) && defined(BIOCGDLTLIST)
+/*
+ * Remove DLT_EN10MB from the list of DLT_ values, as we're in monitor mode,
+ * and DLT_EN10MB isn't supported in monitor mode.
+ */
+static void
+remove_en(pcap_t *p)
+{
+       int i, j;
+
+       /*
+        * Scan the list of DLT_ values and discard DLT_EN10MB.
+        */
+       j = 0;
+       for (i = 0; i < p->dlt_count; i++) {
+               switch (p->dlt_list[i]) {
+
+               case DLT_EN10MB:
+                       /*
+                        * Don't offer this one.
+                        */
+                       continue;
+
+               default:
+                       /*
+                        * Just copy this mode over.
+                        */
+                       break;
+               }
+
+               /*
+                * Copy this DLT_ value to its new position.
+                */
+               p->dlt_list[j] = p->dlt_list[i];
+               j++;
+       }
+
+       /*
+        * Set the DLT_ count to the number of entries we copied.
+        */
+       p->dlt_count = j;
+}
+
+/*
+ * Remove 802.11 link-layer types from the list of DLT_ values, as
+ * we're not in monitor mode, and those DLT_ values will switch us
+ * to monitor mode.
+ */
+static void
+remove_802_11(pcap_t *p)
+{
+       int i, j;
+
+       /*
+        * Scan the list of DLT_ values and discard 802.11 values.
+        */
+       j = 0;
+       for (i = 0; i < p->dlt_count; i++) {
+               switch (p->dlt_list[i]) {
+
+               case DLT_IEEE802_11:
+               case DLT_PRISM_HEADER:
+               case DLT_AIRONET_HEADER:
+               case DLT_IEEE802_11_RADIO:
+               case DLT_IEEE802_11_RADIO_AVS:
+                       /*
+                        * 802.11.  Don't offer this one.
+                        */
+                       continue;
+
+               default:
+                       /*
+                        * Just copy this mode over.
+                        */
+                       break;
+               }
+
+               /*
+                * Copy this DLT_ value to its new position.
+                */
+               p->dlt_list[j] = p->dlt_list[i];
+               j++;
+       }
+
+       /*
+        * Set the DLT_ count to the number of entries we copied.
+        */
+       p->dlt_count = j;
+}
+#endif /* defined(__APPLE__) && defined(BIOCGDLTLIST) */
+
+static int
+pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
+{
+       /*
+        * Free any user-mode filter we might happen to have installed.
+        */
+       pcap_freecode(&p->fcode);
+
+       /*
+        * Try to install the kernel filter.
+        */
+       if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) == 0) {
+               /*
+                * It worked.
+                */
+               p->md.use_bpf = 1;      /* filtering in the kernel */
+
+               /*
+                * Discard any previously-received packets, as they might
+                * have passed whatever filter was formerly in effect, but
+                * might not pass this filter (BIOCSETF discards packets
+                * buffered in the kernel, so you can lose packets in any
+                * case).
+                */
+               p->cc = 0;
+               return (0);
+       }
+
+       /*
+        * We failed.
+        *
+        * If it failed with EINVAL, that's probably because the program
+        * is invalid or too big.  Validate it ourselves; if we like it
+        * (we currently allow backward branches, to support protochain),
+        * run it in userland.  (There's no notion of "too big" for
+        * userland.)
+        *
+        * Otherwise, just give up.
+        * XXX - if the copy of the program into the kernel failed,
+        * we will get EINVAL rather than, say, EFAULT on at least
+        * some kernels.
+        */
+       if (errno != EINVAL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * install_bpf_program() validates the program.
+        *
+        * XXX - what if we already have a filter in the kernel?
+        */
+       if (install_bpf_program(p, fp) < 0)
+               return (-1);
+       p->md.use_bpf = 0;      /* filtering in userland */
+       return (0);
+}
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
+#if defined(BIOCSDIRECTION)
+       u_int direction;
+
+       direction = (d == PCAP_D_IN) ? BPF_D_IN :
+           ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
+       if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
+               (void) snprintf(p->errbuf, sizeof(p->errbuf),
+                   "Cannot set direction to %s: %s",
+                       (d == PCAP_D_IN) ? "PCAP_D_IN" :
+                       ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
+                       strerror(errno));
+               return (-1);
+       }
+       return (0);
+#elif defined(BIOCSSEESENT)
+       u_int seesent;
+
+       /*
+        * We don't support PCAP_D_OUT.
+        */
+       if (d == PCAP_D_OUT) {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                   "Setting direction to PCAP_D_OUT is not supported on BPF");
+               return -1;
+       }
+
+       seesent = (d == PCAP_D_INOUT);
+       if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
+               (void) snprintf(p->errbuf, sizeof(p->errbuf),
+                   "Cannot set direction to %s: %s",
+                       (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
+                       strerror(errno));
+               return (-1);
+       }
+       return (0);
+#else
+       (void) snprintf(p->errbuf, sizeof(p->errbuf),
+           "This system doesn't support BIOCSSEESENT, so the direction can't be set");
+       return (-1);
+#endif
+}
+
+static int
+pcap_set_datalink_bpf(pcap_t *p, int dlt)
+{
+#ifdef BIOCSDLT
+       if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
+               (void) snprintf(p->errbuf, sizeof(p->errbuf),
+                   "Cannot set DLT %d: %s", dlt, strerror(errno));
+               return (-1);
+       }
+#endif
+       return (0);
+}
diff --git a/pcap-bpf.h b/pcap-bpf.h
new file mode 100644 (file)
index 0000000..7b7e90a
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007-04-01 21:43:55 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Some applications
+ * might expect to be able to include <pcap-bpf.h>.
+ */
+#include <pcap/bpf.h>
diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c
new file mode 100644 (file)
index 0000000..0c6c08d
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.c,v 1.15 2008-07-01 07:05:54 guy Exp $ (LBL)";
+#endif
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-bt-linux.h"
+#include "pcap/bluetooth.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#define BT_IFACE "bluetooth"
+#define BT_CTRL_SIZE 128
+
+/* forward declaration */
+static int bt_activate(pcap_t *);
+static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int bt_inject_linux(pcap_t *, const void *, size_t);
+static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
+static int bt_stats_linux(pcap_t *, struct pcap_stat *);
+
+int 
+bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+       pcap_if_t *found_dev = *alldevsp;
+       struct hci_dev_list_req *dev_list;
+       struct hci_dev_req *dev_req;
+       int i, sock;
+       int ret = 0;
+       
+       sock  = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+       if (sock < 0)
+       {
+               /* if bluetooth is not supported this this is not fatal*/ 
+               if (errno == EAFNOSUPPORT)
+                       return 0;
+               snprintf(err_str, PCAP_ERRBUF_SIZE,
+                   "Can't open raw Bluetooth socket: %s", strerror(errno));
+               return -1;
+       }
+
+       dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+       if (!dev_list) 
+       {
+               snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+                       HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+               ret = -1;
+               goto done;
+       }
+
+       dev_list->dev_num = HCI_MAX_DEV;
+
+       if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0) 
+       {
+               snprintf(err_str, PCAP_ERRBUF_SIZE,
+                   "Can't get Bluetooth device list via ioctl: %s",
+                   strerror(errno));
+               ret = -1;
+               goto free;
+       }
+
+       dev_req = dev_list->dev_req;
+       for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
+               char dev_name[20], dev_descr[30];
+               
+               snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
+               snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
+                       
+               if (pcap_add_if(&found_dev, dev_name, 0, 
+                      dev_descr, err_str) < 0)
+               {
+                       ret = -1;
+                       break;
+               }
+
+       }
+
+free:
+       free(dev_list);
+
+done:
+       close(sock);
+       return ret;
+}
+
+pcap_t *
+bt_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = bt_activate;
+       return (p);
+}
+
+static int
+bt_activate(pcap_t* handle)
+{
+       struct sockaddr_hci addr;
+       int opt;
+       int             dev_id;
+       struct hci_filter       flt;
+       int err = PCAP_ERROR;
+
+       /* get bt interface id */
+       if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't get Bluetooth device index from %s", 
+                        handle->opt.source);
+               return PCAP_ERROR;
+       }
+
+       /* Initialize some components of the pcap structure. */
+       handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header);
+       handle->offset = BT_CTRL_SIZE;
+       handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
+
+       handle->read_op = bt_read_linux;
+       handle->inject_op = bt_inject_linux;
+       handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+       handle->setdirection_op = bt_setdirection_linux;
+       handle->set_datalink_op = NULL; /* can't change data link type */
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->stats_op = bt_stats_linux;
+       handle->md.ifindex = dev_id;
+       
+       /* Create HCI socket */
+       handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+       if (handle->fd < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't create raw socket: %s", strerror(errno));
+               return PCAP_ERROR;
+       }
+
+       handle->buffer = malloc(handle->bufsize);
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+                       pcap_strerror(errno));
+               goto close_fail;
+       }
+
+       opt = 1;
+       if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't enable data direction info: %s", strerror(errno));
+               goto close_fail;
+       }
+
+       opt = 1;
+       if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't enable time stamp: %s", strerror(errno));
+               goto close_fail;
+       }
+
+       /* Setup filter, do not call hci function to avoid dependence on 
+        * external libs        */
+       memset(&flt, 0, sizeof(flt));
+       memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));   
+       memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask));
+       if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't set filter: %s", strerror(errno));
+               goto close_fail;
+       }
+
+
+       /* Bind socket to the HCI device */
+       addr.hci_family = AF_BLUETOOTH;
+       addr.hci_dev = handle->md.ifindex;
+       if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't attach to device %d: %s", handle->md.ifindex,
+                   strerror(errno));
+               goto close_fail;
+       }
+
+       if (handle->opt.rfmon) {
+               /*
+                * Monitor mode doesn't apply to Bluetooth devices.
+                */
+               err = PCAP_ERROR_RFMON_NOTSUP;
+               goto close_fail;
+       }
+
+       if (handle->opt.buffer_size != 0) {
+               /*
+                * Set the socket buffer size to the specified value.
+                */
+               if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+                   &handle->opt.buffer_size,
+                   sizeof(handle->opt.buffer_size)) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                "SO_RCVBUF: %s", pcap_strerror(errno));
+                       goto close_fail;
+               }
+       }
+
+       handle->selectable_fd = handle->fd;
+       return 0;
+
+close_fail:
+       pcap_cleanup_live_common(handle);
+       return err;
+}
+
+static int
+bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       struct cmsghdr *cmsg;
+       struct msghdr msg;
+       struct iovec  iv;
+       ssize_t ret;
+       struct pcap_pkthdr pkth;
+       pcap_bluetooth_h4_header* bthdr;
+
+       bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset];
+       iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)];
+       iv.iov_len  = handle->snapshot;
+       
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iv;
+       msg.msg_iovlen = 1;
+       msg.msg_control = handle->buffer;
+       msg.msg_controllen = handle->offset;
+
+       /* ignore interrupt system call error */
+       do {
+               ret = recvmsg(handle->fd, &msg, 0);
+               if (handle->break_loop)
+               {
+                       handle->break_loop = 0;
+                       return -2;
+               }
+       } while ((ret == -1) && (errno == EINTR));
+
+       if (ret < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't receive packet: %s", strerror(errno));
+               return -1;
+       }
+
+       pkth.caplen = ret;
+
+       /* get direction and timestamp*/ 
+       cmsg = CMSG_FIRSTHDR(&msg);
+       int in=0;
+       while (cmsg) {
+               switch (cmsg->cmsg_type) {
+                       case HCI_CMSG_DIR:
+                               memcpy(&in, CMSG_DATA(cmsg), sizeof in);
+                               break;
+                       case HCI_CMSG_TSTAMP:
+                               memcpy(&pkth.ts, CMSG_DATA(cmsg),
+                                   sizeof pkth.ts);
+                               break;
+               }
+               cmsg = CMSG_NXTHDR(&msg, cmsg);
+       }
+       if ((in && (handle->direction == PCAP_D_OUT)) || 
+                               ((!in) && (handle->direction == PCAP_D_IN)))
+               return 0;
+
+       bthdr->direction = htonl(in != 0);
+       pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
+       pkth.len = pkth.caplen;
+       if (handle->fcode.bf_insns == NULL ||
+           bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset],
+             pkth.len, pkth.caplen)) {
+               callback(user, &pkth, &handle->buffer[handle->offset]);
+               return 1;
+       }
+       return 0;       /* didn't pass filter */
+}
+
+static int
+bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+               "bluetooth devices");
+       return (-1);
+}                           
+
+
+static int 
+bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+       int ret;
+       struct hci_dev_info dev_info;
+       struct hci_dev_stats * s = &dev_info.stat;
+       dev_info.dev_id = handle->md.ifindex;
+       
+       /* ignore eintr */
+       do {
+               ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info);
+       } while ((ret == -1) && (errno == EINTR));
+           
+       if (ret < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't get stats via ioctl: %s", strerror(errno));
+               return (-1);
+               
+       }
+
+       /* we receive both rx and tx frames, so comulate all stats */   
+       stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx + 
+               s->acl_tx +s->sco_tx;
+       stats->ps_drop = s->err_rx + s->err_tx;
+       stats->ps_ifdrop = 0;
+       return 0;
+}
+
+static int 
+bt_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+       p->direction = d;
+       return 0;
+}
diff --git a/pcap-bt-linux.h b/pcap-bt-linux.h
new file mode 100644 (file)
index 0000000..ed01190
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.h,v 1.5 2008-04-04 19:37:45 guy Exp $ (LBL)
+ */
+
+/*
+ * Prototypes for Bluetooth-related functions
+ */
+int bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *bt_create(const char *device, char *ebuf);
diff --git a/pcap-can-linux.c b/pcap-can-linux.c
new file mode 100644 (file)
index 0000000..fb8e232
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2009 Felix Obenhuber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * SocketCan sniffing API implementation for Linux platform
+ * By Felix Obenhuber <felix@obenhuber.de>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-can-linux.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+
+#include <linux/can.h>
+#include <linux/can/raw.h>
+
+/* not yet defined anywhere */
+#ifndef PF_CAN
+#define PF_CAN 29
+#endif
+#ifndef AF_CAN
+#define AF_CAN PF_CAN
+#endif
+
+/* forward declaration */
+static int can_activate(pcap_t *);
+static int can_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int can_inject_linux(pcap_t *, const void *, size_t);
+static int can_setfilter_linux(pcap_t *, struct bpf_program *);
+static int can_setdirection_linux(pcap_t *, pcap_direction_t);
+static int can_stats_linux(pcap_t *, struct pcap_stat *);
+
+pcap_t *
+can_create(const char *device, char *ebuf)
+{
+       pcap_t* p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = can_activate;
+       return (p);
+}
+
+
+static int
+can_activate(pcap_t* handle)
+{
+       struct sockaddr_can addr;
+       struct ifreq ifr;
+
+       /* Initialize some components of the pcap structure. */
+       handle->bufsize = 24;
+       handle->offset = 8;
+       handle->linktype = DLT_CAN_SOCKETCAN;
+       handle->read_op = can_read_linux;
+       handle->inject_op = can_inject_linux;
+       handle->setfilter_op = can_setfilter_linux;
+       handle->setdirection_op = can_setdirection_linux;
+       handle->set_datalink_op = NULL;
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->stats_op = can_stats_linux;
+
+       /* Create socket */
+       handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+       if (handle->fd < 0)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s",
+                       errno, strerror(errno));
+               return PCAP_ERROR;
+       }
+
+       /* get interface index */
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+       if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "Unable to get interface index: %s",
+                       pcap_strerror(errno));
+               pcap_cleanup_live_common(handle);
+               return PCAP_ERROR;
+       }
+       handle->md.ifindex = ifr.ifr_ifindex;
+
+       /* allocate butter */
+       handle->buffer = malloc(handle->bufsize);
+       if (!handle->buffer)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+                       pcap_strerror(errno));
+               pcap_cleanup_live_common(handle);
+               return PCAP_ERROR;
+       }
+
+       /* Bind to the socket */
+       addr.can_family = AF_CAN;
+       addr.can_ifindex = handle->md.ifindex;
+       if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0  )
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
+                       handle->md.ifindex, errno, strerror(errno));
+               pcap_cleanup_live_common(handle);
+               return PCAP_ERROR;
+       }
+
+       if (handle->opt.rfmon)
+       {
+               /* Monitor mode doesn't apply to CAN devices. */
+               pcap_cleanup_live_common(handle);
+               return PCAP_ERROR;
+       }
+
+       handle->selectable_fd = handle->fd;
+       return 0;
+
+}
+
+
+static int
+can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       struct msghdr msg;
+       struct pcap_pkthdr pkth;
+       struct iovec iv;
+       struct can_frame* cf;
+
+       iv.iov_base = &handle->buffer[handle->offset];
+       iv.iov_len = handle->snapshot;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iv;
+       msg.msg_iovlen = 1;
+       msg.msg_control = handle->buffer;
+       msg.msg_controllen = handle->offset;
+
+       do
+       {
+               pkth.caplen = recvmsg(handle->fd, &msg, 0);
+               if (handle->break_loop)
+               {
+                       handle->break_loop = 0;
+                       return -2;
+               }
+       } while ((pkth.caplen == -1) && (errno == EINTR));
+
+       if (pkth.caplen < 0)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s",
+                       errno, strerror(errno));
+               return -1;
+       }
+
+       /* adjust capture len according to frame len */
+       cf = (struct can_frame*)&handle->buffer[8];
+       pkth.caplen -= 8 - cf->can_dlc;
+       pkth.len = pkth.caplen;
+
+       cf->can_id = htonl( cf->can_id );
+
+       if( -1 == gettimeofday(&pkth.ts, NULL) )
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s",
+                       errno, strerror(errno));
+               return -1;
+       }
+
+       callback(user, &pkth, &handle->buffer[8]);
+
+       return 1;
+}
+
+
+static int
+can_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       /* not yet implemented */
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+               "can devices");
+       return (-1);
+}
+
+
+static int
+can_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+       /* not yet implemented */
+       stats->ps_recv = 0;                      /* number of packets received */
+       stats->ps_drop = 0;                      /* number of packets dropped */
+       stats->ps_ifdrop = 0;            /* drops by interface -- only supported on some platforms */
+       return 0;
+}
+
+
+static int
+can_setfilter_linux(pcap_t *p, struct bpf_program *fp)
+{
+       /* not yet implemented */
+       return 0;
+}
+
+
+static int
+can_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+       /* no support for PCAP_D_OUT */
+       if (d == PCAP_D_OUT)
+       {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                       "Setting direction to PCAP_D_OUT is not supported on can");
+               return -1;
+       }
+
+       p->direction = d;
+
+       return 0;
+}
+
+
+/* eof */
diff --git a/pcap-can-linux.h b/pcap-can-linux.h
new file mode 100644 (file)
index 0000000..0c8f3b5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2009 Felix Obenhuber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Prototypes for SocketCAN related functions
+ */
+pcap_t* can_create(const char *device, char *ebuf);
diff --git a/pcap-canusb-linux.c b/pcap-canusb-linux.c
new file mode 100644 (file)
index 0000000..5abfe18
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2009 Felix Obenhuber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sockettrace sniffing API implementation for Linux platform
+ * By Felix Obenhuber <felix@obenhuber.de>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libusb-1.0/libusb.h>
+
+#include "pcap-int.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+
+#define CANUSB_IFACE "canusb"
+
+#define CANUSB_VID 0x0403
+#define CANUSB_PID 0x8990
+
+#define USE_THREAD 1
+
+#if USE_THREAD == 0
+#include <signal.h>
+#endif
+
+
+/* forward declaration */
+static int canusb_activate(pcap_t *);
+static int canusb_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int canusb_inject_linux(pcap_t *, const void *, size_t);
+static int canusb_setfilter_linux(pcap_t *, struct bpf_program *);
+static int canusb_setdirection_linux(pcap_t *, pcap_direction_t);
+static int canusb_stats_linux(pcap_t *, struct pcap_stat *);
+
+struct CAN_Msg
+{
+    uint32_t timestamp;
+    uint32_t id;
+    uint32_t length;
+    uint8_t data[8];
+};
+
+struct canusb_t
+{
+  libusb_context *ctx;
+  libusb_device_handle *dev;
+  char* src;
+  pthread_t worker;
+  int rdpipe, wrpipe;
+  volatile int* loop;
+};
+
+static struct canusb_t canusb;
+static volatile int loop;
+
+
+
+int canusb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+    libusb_context *fdctx;
+    libusb_device** devs;
+    unsigned char sernum[65];
+    unsigned char buf[96];
+    int cnt, i;
+    
+    libusb_init(&fdctx);
+        
+    cnt = libusb_get_device_list(fdctx,&devs);
+
+    for(i=0;i<cnt;i++)
+    {
+        int ret;
+        // Check if this device is interesting.
+        struct libusb_device_descriptor desc;
+        libusb_get_device_descriptor(devs[i],&desc);
+
+        if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID)) 
+          continue; //It is not, check next device
+          
+        //It is!
+        libusb_device_handle *dh = NULL;
+
+        if (ret = libusb_open(devs[i],&dh) == 0)
+        {
+               char dev_name[30];
+                 char dev_descr[50]; 
+            int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64);
+            sernum[n] = 0;
+
+               snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
+               snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
+            
+            libusb_close(dh);
+            
+            if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
+            {
+              libusb_free_device_list(devs,1);
+              return -1;
+            }
+        }
+    }
+
+    libusb_free_device_list(devs,1);
+    libusb_exit(fdctx);
+    return 0;
+}
+
+static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial)
+{
+    libusb_device_handle* dh;
+    libusb_device** devs;
+    unsigned char serial[65];
+    int cnt,i,n;
+    
+    cnt = libusb_get_device_list(ctx,&devs);
+
+    for(i=0;i<cnt;i++)
+    {    
+        // Check if this device is interesting.
+        struct libusb_device_descriptor desc;
+        libusb_get_device_descriptor(devs[i],&desc);
+
+        if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
+          continue;
+          
+        //Found one!
+        libusb_device_handle *dh = NULL;
+
+        if (libusb_open(devs[i],&dh) != 0) continue;
+
+        n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64);
+        serial[n] = 0;
+
+        if ((devserial) && (strcmp(serial,devserial) != 0))
+        {
+            libusb_close(dh);
+            continue;
+        }
+
+        if ((libusb_kernel_driver_active(dh,0)) && (libusb_detach_kernel_driver(dh,0) != 0))
+        {
+            libusb_close(dh);
+            continue;
+        }
+
+        if (libusb_set_configuration(dh,1) != 0)
+        {
+            libusb_close(dh);
+            continue;
+        }
+
+        if (libusb_claim_interface(dh,0) != 0)
+        {
+            libusb_close(dh);
+            continue;
+        }
+        
+        //Fount it!
+        libusb_free_device_list(devs,1);        
+        return dh;
+    }
+
+    libusb_free_device_list(devs,1);
+    return NULL;
+}
+
+
+pcap_t *
+canusb_create(const char *device, char *ebuf)
+{ 
+  pcap_t* p;
+               
+  libusb_init(&canusb.ctx);
+  
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+               
+  memset(&canusb, 0x00, sizeof(canusb));
+               
+       
+       p->activate_op = canusb_activate;
+       
+       canusb.src = strdup(p->opt.source);
+       return (p);
+}
+
+
+static void* canusb_capture_thread(struct canusb_t *canusb)
+{
+  struct libusb_context *ctx;
+  libusb_device_handle *dev;
+
+  int i, n;  
+  struct 
+  {
+    uint8_t rxsz, txsz;
+  } status;
+  
+  libusb_init(&ctx);
+  
+  char *serial = canusb->src + strlen(CANUSB_IFACE);  
+  dev = canusb_opendevice(ctx, serial);
+  
+  fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);  
+
+  while(*canusb->loop)
+  {
+    int sz, ret;
+    struct CAN_Msg msg;
+    
+    libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
+    //HACK!!!!! -> drop buffered data, read new one by reading twice.        
+    ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);                                   
+
+    for(i = 0; i<status.rxsz; i++)
+    {
+      libusb_bulk_transfer(dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);      
+      n = write(canusb->wrpipe, &msg, sizeof(msg));
+    }
+
+  }
+  
+  libusb_close(dev);
+  libusb_exit(ctx);
+  
+  return NULL;
+}
+
+static int canusb_startcapture(struct canusb_t* this)
+{
+  int pipefd[2];
+
+  if (pipe(pipefd) == -1) return -1;
+
+  canusb.rdpipe = pipefd[0];
+  canusb.wrpipe = pipefd[1];
+  canusb.loop = &loop;
+
+  loop = 1;  
+  pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb);
+
+  return canusb.rdpipe;
+}
+
+static void canusb_clearbufs(struct canusb_t* this)
+{
+        unsigned char cmd[16];
+        int al;
+
+        cmd[0] = 1;  //Empty incoming buffer
+        cmd[1] = 1;  //Empty outgoing buffer
+        cmd[3] = 0;  //Not a write to serial number
+        memset(&cmd[4],0,16-4);
+        
+        libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
+}
+
+
+static void canusb_close(pcap_t* handle)
+{
+  loop = 0;
+  pthread_join(canusb.worker, NULL);
+
+  if (canusb.dev)
+  {
+    libusb_close(canusb.dev);
+    canusb.dev = NULL;    
+  }    
+}
+
+
+
+static int canusb_activate(pcap_t* handle)
+{
+       handle->read_op = canusb_read_linux;
+
+       handle->inject_op = canusb_inject_linux;
+       handle->setfilter_op = canusb_setfilter_linux;
+       handle->setdirection_op = canusb_setdirection_linux;
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->stats_op = canusb_stats_linux;
+       handle->cleanup_op = canusb_close;
+
+       /* Initialize some components of the pcap structure. */
+       handle->bufsize = 32;
+       handle->offset = 8;
+       handle->linktype = DLT_CAN_SOCKETCAN;
+       handle->set_datalink_op = NULL;
+
+  char* serial = handle->opt.source + strlen("canusb");
+
+  canusb.dev = canusb_opendevice(canusb.ctx,serial);
+  if (!canusb.dev)
+  {
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:");  
+       return PCAP_ERROR;
+       }
+
+  canusb_clearbufs(&canusb);
+
+  handle->fd = canusb_startcapture(&canusb);
+       handle->selectable_fd = handle->fd;
+                       
+       return 0;
+}
+
+
+
+
+static int
+canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+  static struct timeval firstpacket = { -1, -1};
+  
+  int msgsent = 0;
+  int i = 0;
+  struct CAN_Msg msg;
+       struct pcap_pkthdr pkth;
+  
+  while(i < max_packets)
+  {
+    usleep(10 * 1000);
+    int n = read(handle->fd, &msg, sizeof(msg));
+    if (n <= 0) break;
+    pkth.caplen = pkth.len = n;
+    pkth.caplen -= 4;
+    pkth.caplen -= 8 - msg.length;
+    
+    if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
+      gettimeofday(&firstpacket, NULL);
+      
+    pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
+    pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
+    if (pkth.ts.tv_usec > 1000000)
+    {
+      pkth.ts.tv_usec -= 1000000;
+      pkth.ts.tv_sec++;
+    }
+
+    callback(user, &pkth, (void*)&msg.id);
+    i++;
+  }
+  
+  return i;
+}
+
+
+static int
+canusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       /* not yet implemented */
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
+       return (-1);
+}
+
+
+static int
+canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+       /* not yet implemented */
+       stats->ps_recv = 0;                      /* number of packets received */
+       stats->ps_drop = 0;                      /* number of packets dropped */
+       stats->ps_ifdrop = 0;            /* drops by interface -- only supported on some platforms */
+       return 0;
+}
+
+
+static int
+canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
+{
+       /* not yet implemented */
+       return 0;
+}
+
+
+static int
+canusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+       /* no support for PCAP_D_OUT */
+       if (d == PCAP_D_OUT)
+       {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                       "Setting direction to PCAP_D_OUT is not supported on this interface");
+               return -1;
+       }
+
+       p->direction = d;
+
+       return 0;
+}
+
+
+/* eof */
diff --git a/pcap-canusb-linux.h b/pcap-canusb-linux.h
new file mode 100644 (file)
index 0000000..f03053a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 Felix Obenhuber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Prototypes for SocketCAN related functions
+ */
+pcap_t* canusb_create(const char *device, char *ebuf);
+int canusb_listdevices(pcap_if_t **pdevlist, char* errbuf);
+
diff --git a/pcap-common.c b/pcap-common.c
new file mode 100644 (file)
index 0000000..31cf84d
--- /dev/null
@@ -0,0 +1,1158 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-common.c - common code for pcap and pcap-ng files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include "pcap-int.h"
+#include "pcap/usb.h"
+
+#include "pcap-common.h"
+
+/*
+ * We don't write DLT_* values to capture files, because they're not the
+ * same on all platforms.
+ *
+ * Unfortunately, the various flavors of BSD have not always used the same
+ * numerical values for the same data types, and various patches to
+ * libpcap for non-BSD OSes have added their own DLT_* codes for link
+ * layer encapsulation types seen on those OSes, and those codes have had,
+ * in some cases, values that were also used, on other platforms, for other
+ * link layer encapsulation types.
+ *
+ * This means that capture files of a type whose numerical DLT_* code
+ * means different things on different BSDs, or with different versions
+ * of libpcap, can't always be read on systems other than those like
+ * the one running on the machine on which the capture was made.
+ *
+ * Instead, we define here a set of LINKTYPE_* codes, and map DLT_* codes
+ * to LINKTYPE_* codes when writing a savefile header, and map LINKTYPE_*
+ * codes to DLT_* codes when reading a savefile header.
+ *
+ * For those DLT_* codes that have, as far as we know, the same values on
+ * all platforms (DLT_NULL through DLT_FDDI), we define LINKTYPE_xxx as
+ * DLT_xxx; that way, captures of those types can still be read by
+ * versions of libpcap that map LINKTYPE_* values to DLT_* values, and
+ * captures of those types written by versions of libpcap that map DLT_
+ * values to LINKTYPE_ values can still be read by older versions
+ * of libpcap.
+ *
+ * The other LINKTYPE_* codes are given values starting at 100, in the
+ * hopes that no DLT_* code will be given one of those values.
+ *
+ * In order to ensure that a given LINKTYPE_* code's value will refer to
+ * the same encapsulation type on all platforms, you should not allocate
+ * a new LINKTYPE_* value without consulting
+ * "tcpdump-workers@lists.tcpdump.org".  The tcpdump developers will
+ * allocate a value for you, and will not subsequently allocate it to
+ * anybody else; that value will be added to the "pcap.h" in the
+ * tcpdump.org Git repository, so that a future libpcap release will
+ * include it.
+ *
+ * You should, if possible, also contribute patches to libpcap and tcpdump
+ * to handle the new encapsulation type, so that they can also be checked
+ * into the tcpdump.org Git repository and so that they will appear in
+ * future libpcap and tcpdump releases.
+ *
+ * Do *NOT* assume that any values after the largest value in this file
+ * are available; you might not have the most up-to-date version of this
+ * file, and new values after that one might have been assigned.  Also,
+ * do *NOT* use any values below 100 - those might already have been
+ * taken by one (or more!) organizations.
+ *
+ * Any platform that defines additional DLT_* codes should:
+ *
+ *     request a LINKTYPE_* code and value from tcpdump.org,
+ *     as per the above;
+ *
+ *     add, in their version of libpcap, an entry to map
+ *     those DLT_* codes to the corresponding LINKTYPE_*
+ *     code;
+ *
+ *     redefine, in their "net/bpf.h", any DLT_* values
+ *     that collide with the values used by their additional
+ *     DLT_* codes, to remove those collisions (but without
+ *     making them collide with any of the LINKTYPE_*
+ *     values equal to 50 or above; they should also avoid
+ *     defining DLT_* values that collide with those
+ *     LINKTYPE_* values, either).
+ */
+#define LINKTYPE_NULL          DLT_NULL
+#define LINKTYPE_ETHERNET      DLT_EN10MB      /* also for 100Mb and up */
+#define LINKTYPE_EXP_ETHERNET  DLT_EN3MB       /* 3Mb experimental Ethernet */
+#define LINKTYPE_AX25          DLT_AX25
+#define LINKTYPE_PRONET                DLT_PRONET
+#define LINKTYPE_CHAOS         DLT_CHAOS
+#define LINKTYPE_IEEE802_5     DLT_IEEE802     /* DLT_IEEE802 is used for 802.5 Token Ring */
+#define LINKTYPE_ARCNET_BSD    DLT_ARCNET      /* BSD-style headers */
+#define LINKTYPE_SLIP          DLT_SLIP
+#define LINKTYPE_PPP           DLT_PPP
+#define LINKTYPE_FDDI          DLT_FDDI
+
+/*
+ * LINKTYPE_PPP is for use when there might, or might not, be an RFC 1662
+ * PPP in HDLC-like framing header (with 0xff 0x03 before the PPP protocol
+ * field) at the beginning of the packet.
+ *
+ * This is for use when there is always such a header; the address field
+ * might be 0xff, for regular PPP, or it might be an address field for Cisco
+ * point-to-point with HDLC framing as per section 4.3.1 of RFC 1547 ("Cisco
+ * HDLC").  This is, for example, what you get with NetBSD's DLT_PPP_SERIAL.
+ *
+ * We give it the same value as NetBSD's DLT_PPP_SERIAL, in the hopes that
+ * nobody else will choose a DLT_ value of 50, and so that DLT_PPP_SERIAL
+ * captures will be written out with a link type that NetBSD's tcpdump
+ * can read.
+ */
+#define LINKTYPE_PPP_HDLC      50              /* PPP in HDLC-like framing */
+
+#define LINKTYPE_PPP_ETHER     51              /* NetBSD PPP-over-Ethernet */
+
+#define LINKTYPE_SYMANTEC_FIREWALL 99          /* Symantec Enterprise Firewall */
+
+/*
+ * These correspond to DLT_s that have different values on different
+ * platforms; we map between these values in capture files and
+ * the DLT_ values as returned by pcap_datalink() and passed to
+ * pcap_open_dead().
+ */
+#define LINKTYPE_ATM_RFC1483   100             /* LLC/SNAP-encapsulated ATM */
+#define LINKTYPE_RAW           101             /* raw IP */
+#define LINKTYPE_SLIP_BSDOS    102             /* BSD/OS SLIP BPF header */
+#define LINKTYPE_PPP_BSDOS     103             /* BSD/OS PPP BPF header */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * LINKTYPE_MATCHING_MIN is the lowest such value; LINKTYPE_MATCHING_MAX
+ * is the highest such value.
+ */
+#define LINKTYPE_MATCHING_MIN  104             /* lowest value in the "matching" range */
+
+#define LINKTYPE_C_HDLC                104             /* Cisco HDLC */
+#define LINKTYPE_IEEE802_11    105             /* IEEE 802.11 (wireless) */
+#define LINKTYPE_ATM_CLIP      106             /* Linux Classical IP over ATM */
+#define LINKTYPE_FRELAY                107             /* Frame Relay */
+#define LINKTYPE_LOOP          108             /* OpenBSD loopback */
+#define LINKTYPE_ENC           109             /* OpenBSD IPSEC enc */
+
+/*
+ * These three types are reserved for future use.
+ */
+#define LINKTYPE_LANE8023      110             /* ATM LANE + 802.3 */
+#define LINKTYPE_HIPPI         111             /* NetBSD HIPPI */
+#define LINKTYPE_HDLC          112             /* NetBSD HDLC framing */
+
+#define LINKTYPE_LINUX_SLL     113             /* Linux cooked socket capture */
+#define LINKTYPE_LTALK         114             /* Apple LocalTalk hardware */
+#define LINKTYPE_ECONET                115             /* Acorn Econet */
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define LINKTYPE_IPFILTER      116
+
+#define LINKTYPE_PFLOG         117             /* OpenBSD DLT_PFLOG */
+#define LINKTYPE_CISCO_IOS     118             /* For Cisco-internal use */
+#define LINKTYPE_IEEE802_11_PRISM 119          /* 802.11 plus Prism II monitor mode radio metadata header */
+#define LINKTYPE_IEEE802_11_AIRONET 120                /* 802.11 plus FreeBSD Aironet driver radio metadata header */
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define LINKTYPE_HHDLC         121
+
+#define LINKTYPE_IP_OVER_FC    122             /* RFC 2625 IP-over-Fibre Channel */
+#define LINKTYPE_SUNATM                123             /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define LINKTYPE_RIO           124             /* RapidIO */
+#define LINKTYPE_PCI_EXP       125             /* PCI Express */
+#define LINKTYPE_AURORA                126             /* Xilinx Aurora link layer */
+
+#define LINKTYPE_IEEE802_11_RADIOTAP 127       /* 802.11 plus radiotap radio metadata header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define LINKTYPE_TZSP          128             /* Tazmen Sniffer Protocol */
+
+#define LINKTYPE_ARCNET_LINUX  129             /* Linux-style headers */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The corresponding
+ * DLT_s are used for passing on chassis-internal
+ * metainformation such as QOS profiles, etc..
+ */
+#define LINKTYPE_JUNIPER_MLPPP  130
+#define LINKTYPE_JUNIPER_MLFR   131
+#define LINKTYPE_JUNIPER_ES     132
+#define LINKTYPE_JUNIPER_GGSN   133
+#define LINKTYPE_JUNIPER_MFR    134
+#define LINKTYPE_JUNIPER_ATM2   135
+#define LINKTYPE_JUNIPER_SERVICES 136
+#define LINKTYPE_JUNIPER_ATM1   137
+
+#define LINKTYPE_APPLE_IP_OVER_IEEE1394 138    /* Apple IP-over-IEEE 1394 cooked header */
+
+#define LINKTYPE_MTP2_WITH_PHDR        139
+#define LINKTYPE_MTP2          140
+#define LINKTYPE_MTP3          141
+#define LINKTYPE_SCCP          142
+
+#define LINKTYPE_DOCSIS                143             /* DOCSIS MAC frames */
+
+#define LINKTYPE_LINUX_IRDA    144             /* Linux-IrDA */
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define LINKTYPE_IBM_SP                145
+#define LINKTYPE_IBM_SN                146
+
+/*
+ * Reserved for private use.  If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that LINKTYPE_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, in those cases, ask "tcpdump-workers@lists.tcpdump.org" for a
+ * new DLT_ and LINKTYPE_ value, as per the comment in pcap/bpf.h, and use
+ * the type you're given.
+ */
+#define LINKTYPE_USER0         147
+#define LINKTYPE_USER1         148
+#define LINKTYPE_USER2         149
+#define LINKTYPE_USER3         150
+#define LINKTYPE_USER4         151
+#define LINKTYPE_USER5         152
+#define LINKTYPE_USER6         153
+#define LINKTYPE_USER7         154
+#define LINKTYPE_USER8         155
+#define LINKTYPE_USER9         156
+#define LINKTYPE_USER10                157
+#define LINKTYPE_USER11                158
+#define LINKTYPE_USER12                159
+#define LINKTYPE_USER13                160
+#define LINKTYPE_USER14                161
+#define LINKTYPE_USER15                162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ *     http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ */
+#define LINKTYPE_IEEE802_11_AVS        163     /* 802.11 plus AVS radio metadata header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The corresponding
+ * DLT_s are used for passing on chassis-internal
+ * metainformation such as QOS profiles, etc..
+ */
+#define LINKTYPE_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define LINKTYPE_BACNET_MS_TP  165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define LINKTYPE_PPP_PPPD      166
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define LINKTYPE_JUNIPER_PPPOE     167
+#define LINKTYPE_JUNIPER_PPPOE_ATM 168
+
+#define LINKTYPE_GPRS_LLC      169             /* GPRS LLC */
+#define LINKTYPE_GPF_T         170             /* GPF-T (ITU-T G.7041/Y.1303) */
+#define LINKTYPE_GPF_F         171             /* GPF-T (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define LINKTYPE_GCOM_T1E1     172
+#define LINKTYPE_GCOM_SERIAL   173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define LINKTYPE_JUNIPER_PIC_PEER    174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems.  They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define LINKTYPE_ERF_ETH       175     /* Ethernet */
+#define LINKTYPE_ERF_POS       176     /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/).  Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define LINKTYPE_LINUX_LAPD    177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The Link Types are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define LINKTYPE_JUNIPER_ETHER  178
+#define LINKTYPE_JUNIPER_PPP    179
+#define LINKTYPE_JUNIPER_FRELAY 180
+#define LINKTYPE_JUNIPER_CHDLC  181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define LINKTYPE_MFR            182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define LINKTYPE_JUNIPER_VP     183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define LINKTYPE_A429           184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define LINKTYPE_A653_ICM       185
+
+/*
+ * USB packets, beginning with a USB setup header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define LINKTYPE_USB           186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define LINKTYPE_BLUETOOTH_HCI_H4      187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define LINKTYPE_IEEE802_16_MAC_CPS    188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define LINKTYPE_USB_LINUX             189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define LINKTYPE_CAN20B         190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define LINKTYPE_IEEE802_15_4_LINUX    191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * LINKTYPE_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define LINKTYPE_PPI                   192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define LINKTYPE_IEEE802_16_MAC_CPS_RADIO      193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define LINKTYPE_JUNIPER_ISM    194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ */
+#define LINKTYPE_IEEE802_15_4  195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define LINKTYPE_SITA          196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records.  Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define LINKTYPE_ERF           197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board.  Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define LINKTYPE_RAIF1         198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc..  Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define LINKTYPE_IPMB          199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define LINKTYPE_JUNIPER_ST     200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR    201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ *     http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define LINKTYPE_AX25_KISS     202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define LINKTYPE_LAPD          203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_PPP_WITH_DIR  204     /* PPP */
+#define LINKTYPE_C_HDLC_WITH_DIR 205   /* Cisco HDLC */
+#define LINKTYPE_FRELAY_WITH_DIR 206   /* Frame Relay */
+#define LINKTYPE_LAPB_WITH_DIR 207     /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define LINKTYPE_IPMB_LINUX    209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_FLEXRAY       210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_MOST          211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_LIN           212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_SERIAL    213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_XORAYA    214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define LINKTYPE_IEEE802_15_4_NONASK_PHY       215
+
+/* 
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg. 
+ */
+#define LINKTYPE_LINUX_EVDEV   216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define LINKTYPE_GSMTAP_UM     217
+#define LINKTYPE_GSMTAP_ABIS   218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define LINKTYPE_MPLS          219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define LINKTYPE_USB_LINUX_MMAPPED             220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define LINKTYPE_DECT          221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ *   I have already written dissectors for but need an OK from
+ *   legal before I can submit a patch.
+ *
+ */
+#define LINKTYPE_AOS           222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define LINKTYPE_WIHART                223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define LINKTYPE_FC_2          224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define LINKTYPE_FC_2_WITH_FRAME_DELIMS                225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ *     u_int8_t   dli_version;
+ *     u_int8_t   dli_family;
+ *     u_int16_t  dli_htype;
+ *     u_int32_t  dli_pktlen;
+ *     u_int32_t  dli_ifindex;
+ *     u_int32_t  dli_grifindex;
+ *     u_int32_t  dli_zsrc;
+ *     u_int32_t  dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define LINKTYPE_IPNET         226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN.  See Documentation/networking/can.txt in the Linux
+ * source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define LINKTYPE_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6.  Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define LINKTYPE_IPV4          228
+#define LINKTYPE_IPV6          229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define LINKTYPE_IEEE802_15_4_NOFCS            230
+
+/*
+ * Raw D-Bus:
+ *
+ *     http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ *     http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ *     http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define LINKTYPE_DBUS          231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ */
+#define LINKTYPE_JUNIPER_VS                    232
+#define LINKTYPE_JUNIPER_SRX_E2E               233
+#define LINKTYPE_JUNIPER_FIBRECHANNEL          234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver).  See
+ *
+ *     http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define LINKTYPE_DVB_CI                235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol.  Requested
+ * by Hans-Christoph Schemmel <hans-christoph.schemmel@cinterion.com>.
+ */
+#define LINKTYPE_MUX27010      236
+
+/*
+ * STANAG 5066 D_PDUs.  Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define LINKTYPE_STANAG_5066_D_PDU             237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ */
+#define LINKTYPE_JUNIPER_ATM_CEMIC             238
+
+/*
+ * NetFilter LOG messages 
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define LINKTYPE_NFLOG         239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define LINKTYPE_NETANALYZER   240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define LINKTYPE_NETANALYZER_TRANSPARENT       241
+
+/*
+ * IP-over-Infiniband, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define LINKTYPE_IPOIB         242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define LINKTYPE_MPEG_2_TS     243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define LINKTYPE_NG40          244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define LINKTYPE_NFC_LLCP      245
+
+/*
+ * pfsync output; DLT_PFSYNC is 18, which collides with DLT_CIP in
+ * SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and Mac OS X, and
+ * is 121, which collides with DLT_HHDLC, in FreeBSD.  We pick a
+ * shiny new link-layer header type value that doesn't collide with
+ * anything, in the hopes that future pfsync savefiles, if any,
+ * won't require special hacks to distinguish from other savefiles.
+ *
+ */
+#define LINKTYPE_PFSYNC                246
+
+#define LINKTYPE_MATCHING_MAX  246             /* highest value in the "matching" range */
+
+static struct linktype_map {
+       int     dlt;
+       int     linktype;
+} map[] = {
+       /*
+        * These DLT_* codes have LINKTYPE_* codes with values identical
+        * to the values of the corresponding DLT_* code.
+        */
+       { DLT_NULL,             LINKTYPE_NULL },
+       { DLT_EN10MB,           LINKTYPE_ETHERNET },
+       { DLT_EN3MB,            LINKTYPE_EXP_ETHERNET },
+       { DLT_AX25,             LINKTYPE_AX25 },
+       { DLT_PRONET,           LINKTYPE_PRONET },
+       { DLT_CHAOS,            LINKTYPE_CHAOS },
+       { DLT_IEEE802,          LINKTYPE_IEEE802_5 },
+       { DLT_ARCNET,           LINKTYPE_ARCNET_BSD },
+       { DLT_SLIP,             LINKTYPE_SLIP },
+       { DLT_PPP,              LINKTYPE_PPP },
+       { DLT_FDDI,             LINKTYPE_FDDI },
+       { DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL },
+
+       /*
+        * These DLT_* codes have different values on different
+        * platforms; we map them to LINKTYPE_* codes that
+        * have values that should never be equal to any DLT_*
+        * code.
+        */
+#ifdef DLT_FR
+       /* BSD/OS Frame Relay */
+       { DLT_FR,               LINKTYPE_FRELAY },
+#endif
+
+       { DLT_ATM_RFC1483,      LINKTYPE_ATM_RFC1483 },
+       { DLT_RAW,              LINKTYPE_RAW },
+       { DLT_SLIP_BSDOS,       LINKTYPE_SLIP_BSDOS },
+       { DLT_PPP_BSDOS,        LINKTYPE_PPP_BSDOS },
+
+       /* BSD/OS Cisco HDLC */
+       { DLT_C_HDLC,           LINKTYPE_C_HDLC },
+
+       /*
+        * These DLT_* codes are not on all platforms, but, so far,
+        * there don't appear to be any platforms that define
+        * other codes with those values; we map them to
+        * different LINKTYPE_* values anyway, just in case.
+        */
+
+       /* Linux ATM Classical IP */
+       { DLT_ATM_CLIP,         LINKTYPE_ATM_CLIP },
+
+       /* NetBSD sync/async serial PPP (or Cisco HDLC) */
+       { DLT_PPP_SERIAL,       LINKTYPE_PPP_HDLC },
+
+       /* NetBSD PPP over Ethernet */
+       { DLT_PPP_ETHER,        LINKTYPE_PPP_ETHER },
+
+       /*
+        * All LINKTYPE_ values between LINKTYPE_MATCHING_MIN
+        * and LINKTYPE_MATCHING_MAX are mapped to identical
+        * DLT_ values.
+        */
+
+       { -1,                   -1 }
+};
+
+int
+dlt_to_linktype(int dlt)
+{
+       int i;
+
+       /*
+        * Map DLT_PFSYNC, whatever it might be, to LINKTYPE_PFSYNC.
+        */
+       if (dlt == DLT_PFSYNC)
+               return (LINKTYPE_PFSYNC);
+
+       /*
+        * Map the values in the matching range.
+        */
+       if (dlt >= DLT_MATCHING_MIN && dlt <= DLT_MATCHING_MAX)
+               return (dlt);
+
+       /*
+        * Map the values outside that range.
+        */
+       for (i = 0; map[i].dlt != -1; i++) {
+               if (map[i].dlt == dlt)
+                       return (map[i].linktype);
+       }
+
+       /*
+        * If we don't have a mapping for this DLT_ code, return an
+        * error; that means that this is a value with no corresponding
+        * LINKTYPE_ code, and we need to assign one.
+        */
+       return (-1);
+}
+
+int
+linktype_to_dlt(int linktype)
+{
+       int i;
+
+       /*
+        * Map LINKTYPE_PFSYNC to DLT_PFSYNC, whatever it might be.
+        * LINKTYPE_PFSYNC is in the matching range, to make sure
+        * it's as safe from reuse as we can arrange, so we do
+        * this test first.
+        */
+       if (linktype == LINKTYPE_PFSYNC)
+               return (DLT_PFSYNC);
+
+       /*
+        * Map the values in the matching range.
+        */
+       if (linktype >= LINKTYPE_MATCHING_MIN &&
+           linktype <= LINKTYPE_MATCHING_MAX)
+               return (linktype);
+
+       /*
+        * Map the values outside that range.
+        */
+       for (i = 0; map[i].linktype != -1; i++) {
+               if (map[i].linktype == linktype)
+                       return (map[i].dlt);
+       }
+
+       /*
+        * If we don't have an entry for this link type, return
+        * the link type value; it may be a DLT_ value from an
+        * older version of libpcap.
+        */
+       return linktype;
+}
+
+/*
+ * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
+ * byte order when capturing (it's supplied directly from a
+ * memory-mapped buffer shared by the kernel).
+ *
+ * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED capture file,
+ * we need to convert it from the capturing host's byte order to
+ * the reading host's byte order.
+ */
+void
+swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+    int header_len_64_bytes)
+{
+       pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
+       bpf_u_int32 offset = 0;
+       usb_isodesc *pisodesc;
+       int32_t numdesc, i;
+
+       /*
+        * "offset" is the offset *past* the field we're swapping;
+        * we skip the field *before* checking to make sure
+        * the captured data length includes the entire field.
+        */
+
+       /*
+        * The URB id is a totally opaque value; do we really need to 
+        * convert it to the reading host's byte order???
+        */
+       offset += 8;                    /* skip past id */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->id = SWAPLL(uhdr->id);
+
+       offset += 4;                    /* skip past various 1-byte fields */
+
+       offset += 2;                    /* skip past bus_id */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
+
+       offset += 2;                    /* skip past various 1-byte fields */
+
+       offset += 8;                    /* skip past ts_sec */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
+
+       offset += 4;                    /* skip past ts_usec */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
+
+       offset += 4;                    /* skip past status */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->status = SWAPLONG(uhdr->status);
+
+       offset += 4;                    /* skip past urb_len */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->urb_len = SWAPLONG(uhdr->urb_len);
+
+       offset += 4;                    /* skip past data_len */
+       if (hdr->caplen < offset)
+               return;
+       uhdr->data_len = SWAPLONG(uhdr->data_len);
+
+       if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+               offset += 4;                    /* skip past s.iso.error_count */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
+
+               offset += 4;                    /* skip past s.iso.numdesc */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
+       } else
+               offset += 8;                    /* skip USB setup header */
+
+       if (header_len_64_bytes) {
+               /*
+                * This is either the "version 1" header, with
+                * 16 bytes of additional fields at the end, or
+                * a "version 0" header from a memory-mapped
+                * capture, with 16 bytes of zeroed-out padding
+                * at the end.  Byte swap them as if this were
+                * a "version 1" header.
+                */
+               offset += 4;                    /* skip past interval */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->interval = SWAPLONG(uhdr->interval);
+
+               offset += 4;                    /* skip past start_frame */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->start_frame = SWAPLONG(uhdr->start_frame);
+
+               offset += 4;                    /* skip past xfer_flags */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
+
+               offset += 4;                    /* skip past ndesc */
+               if (hdr->caplen < offset)
+                       return;
+               uhdr->ndesc = SWAPLONG(uhdr->ndesc);
+       }       
+
+       if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+               /* swap the values in struct linux_usb_isodesc */
+               pisodesc = (usb_isodesc *)(void *)(buf+offset);
+               numdesc = uhdr->s.iso.numdesc;
+               for (i = 0; i < numdesc; i++) {
+                       offset += 4;            /* skip past status */
+                       if (hdr->caplen < offset)
+                               return;
+                       pisodesc->status = SWAPLONG(pisodesc->status);
+
+                       offset += 4;            /* skip past offset */
+                       if (hdr->caplen < offset)
+                               return;
+                       pisodesc->offset = SWAPLONG(pisodesc->offset);
+
+                       offset += 4;            /* skip past len */
+                       if (hdr->caplen < offset)
+                               return;
+                       pisodesc->len = SWAPLONG(pisodesc->len);
+
+                       offset += 4;            /* skip past padding */
+
+                       pisodesc++;
+               }
+       }
+}
diff --git a/pcap-common.h b/pcap-common.h
new file mode 100644 (file)
index 0000000..0c80ba3
--- /dev/null
@@ -0,0 +1,25 @@
+
+/*
+ * We use the "receiver-makes-right" approach to byte order,
+ * because time is at a premium when we are writing the file.
+ * In other words, the pcap_file_header and pcap_pkthdr,
+ * records are written in host byte order.
+ * Note that the bytes of packet data are written out in the order in
+ * which they were received, so multi-byte fields in packets are not
+ * written in host byte order, they're written in whatever order the
+ * sending machine put them in.
+ *
+ * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
+ * machine (if the file was written in little-end order).
+ */
+#define        SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define        SWAPSHORT(y) \
+       ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
+
+extern int dlt_to_linktype(int dlt);
+
+extern int linktype_to_dlt(int linktype);
+
+extern void swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+    int header_len_64_bytes);
diff --git a/pcap-config.1 b/pcap-config.1
new file mode 100644 (file)
index 0000000..021f450
--- /dev/null
@@ -0,0 +1,74 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-config.1,v 1.1 2008-09-23 18:04:01 guy Exp $ (LBL)
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-CONFIG 1 "26 March 2009"
+.SH NAME
+pcap-config \- write libpcap compiler and linker flags to standard output
+.SH SYNOPSIS
+.na
+.B pcap-config
+[
+.B \-\-static
+]
+[
+.B \-\-cflags | \-\-libs | \-\-additional-libs
+]
+.ad
+.SH DESCRIPTION
+.LP
+When run with the
+.B \-\-cflags
+option,
+.I pcap-config
+writes to the standard output the
+.B \-I
+compiler flags required to include libpcap's header files.
+When run with the
+.B \-\-libs
+option,
+.I pcap-config
+writes to the standard output the
+.B \-L
+and
+.B \-l
+linker flags required to link with libpcap, including
+.B \-l
+flags for libraries required by libpcap.
+When run with the
+.B \-\-additional-libs
+option,
+.I pcap-config
+writes to the standard output the
+.B \-L
+and
+.B \-l
+flags for libraries required by libpcap, but not the
+.B \-lpcap
+flag to link with libpcap itself.
+.LP
+By default, it writes flags appropriate for compiling with a
+dynamically-linked version of libpcap; the
+.B \-\-static
+flag causes it to write flags appropriate for compiling with a
+statically-linked version of libpcap.
+.SH "SEE ALSO"
+pcap(3PCAP)
diff --git a/pcap-config.in b/pcap-config.in
new file mode 100644 (file)
index 0000000..206be3b
--- /dev/null
@@ -0,0 +1,89 @@
+#! /bin/sh
+
+#
+# Script to give the appropriate compiler flags and linker flags
+# to use when building code that uses libpcap.
+#
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+includedir="@includedir@"
+libdir="@libdir@"
+V_RPATH_OPT="@V_RPATH_OPT@"
+LIBS="@LIBS@"
+
+static=0
+show_cflags=0
+show_libs=0
+while [ "$#" != 0 ]
+do
+       case "$1" in
+
+       --static)
+               static=1
+               ;;
+
+       --cflags)
+               show_cflags=1
+               ;;
+
+       --libs)
+               show_libs=1
+               ;;
+
+       --additional-libs)
+               show_additional_libs=1
+               ;;
+       esac
+       shift
+done
+if [ "$V_RPATH_OPT" != "" ]
+then
+       #
+       # If libdir isn't /usr/lib, add it to the run-time linker path.
+       #
+       if [ "$libdir" != "/usr/lib" ]
+       then
+               RPATH=$V_RPATH_OPT$libdir
+       fi
+fi
+if [ "$static" = 1 ]
+then
+       #
+       # Include LIBS so that the flags include libraries containing
+       # routines that libpcap uses.
+       #
+       if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+       then
+               echo "-I$includedir -L$libdir -lpcap $LIBS"
+       elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+       then
+               echo "-I$includedir -L$libdir $LIBS"
+       elif [ "$show_cflags" = 1 ]
+       then
+               echo "-I$includedir"
+       elif [ "$show_libs" = 1 ]
+       then
+               echo "-L$libdir -lpcap $LIBS"
+       elif [ "$show_additional_libs" = 1 ]
+       then
+               echo "$LIBS"
+       fi
+else
+       #
+       # Omit LIBS - libpcap is assumed to be linked with those
+       # libraries, so there's no need to do so explicitly.
+       #
+       if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+       then
+               echo "-I$includedir -L$libdir $RPATH -lpcap"
+       elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+       then
+               echo "-I$includedir"
+       elif [ "$show_cflags" = 1 ]
+       then
+               echo "-I$includedir"
+       elif [ "$show_libs" = 1 ]
+       then
+               echo "-L$libdir $RPATH -lpcap"
+       fi
+fi
diff --git a/pcap-dag.c b/pcap-dag.c
new file mode 100644 (file)
index 0000000..b5de069
--- /dev/null
@@ -0,0 +1,1141 @@
+/*
+ * pcap-dag.c: Packet capture interface for Endace DAG card.
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible.  This code is compiled in several different ways depending on
+ * whether DAG_ONLY and HAVE_DAG_API are defined.  If HAVE_DAG_API is not
+ * defined it should not get compiled in, otherwise if DAG_ONLY is defined then
+ * the 'dag_' function calls are renamed to 'pcap_' equivalents.  If DAG_ONLY
+ * is not defined then nothing is altered - the dag_ functions will be
+ * called as required from their pcap-linux/bpf equivalents.
+ *
+ * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
+ * Modifications: Jesper Peterson  <support@endace.com>
+ *                Koryn Grant      <support@endace.com>
+ *                Stephen Donnelly <support@endace.com>
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+       "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.39 2008-04-14 20:40:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
+#include <net/if.h>
+
+#include "dagnew.h"
+#include "dagapi.h"
+
+#include "pcap-dag.h"
+
+#define ATM_CELL_SIZE          52
+#define ATM_HDR_SIZE           4
+
+/*
+ * A header containing additional MTP information.
+ */
+#define MTP2_SENT_OFFSET               0       /* 1 byte */
+#define MTP2_ANNEX_A_USED_OFFSET       1       /* 1 byte */
+#define MTP2_LINK_NUMBER_OFFSET                2       /* 2 bytes */
+#define MTP2_HDR_LEN                   4       /* length of the header */
+
+#define MTP2_ANNEX_A_NOT_USED      0
+#define MTP2_ANNEX_A_USED          1
+#define MTP2_ANNEX_A_USED_UNKNOWN  2
+
+/* SunATM pseudo header */
+struct sunatm_hdr {
+       unsigned char   flags;          /* destination and traffic type */
+       unsigned char   vpi;            /* VPI */
+       unsigned short  vci;            /* VCI */
+};
+
+typedef struct pcap_dag_node {
+       struct pcap_dag_node *next;
+       pcap_t *p;
+       pid_t pid;
+} pcap_dag_node_t;
+
+static pcap_dag_node_t *pcap_dags = NULL;
+static int atexit_handler_installed = 0;
+static const unsigned short endian_test_word = 0x0100;
+
+#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
+
+
+#ifdef DAG_ONLY
+/* This code is required when compiling for a DAG device only. */
+
+/* Replace dag function names with pcap equivalent. */
+#define dag_create pcap_create
+#define dag_platform_finddevs pcap_platform_finddevs
+#endif /* DAG_ONLY */
+
+#define MAX_DAG_PACKET 65536
+
+static unsigned char TempPkt[MAX_DAG_PACKET];
+
+static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
+static int dag_stats(pcap_t *p, struct pcap_stat *ps);
+static int dag_set_datalink(pcap_t *p, int dlt);
+static int dag_get_datalink(pcap_t *p);
+static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+
+static void
+delete_pcap_dag(pcap_t *p)
+{
+       pcap_dag_node_t *curr = NULL, *prev = NULL;
+
+       for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
+               /* empty */
+       }
+
+       if (curr != NULL && curr->p == p) {
+               if (prev != NULL) {
+                       prev->next = curr->next;
+               } else {
+                       pcap_dags = curr->next;
+               }
+       }
+}
+
+/*
+ * Performs a graceful shutdown of the DAG card, frees dynamic memory held
+ * in the pcap_t structure, and closes the file descriptor for the DAG card.
+ */
+
+static void
+dag_platform_cleanup(pcap_t *p)
+{
+       
+       if (p != NULL) {
+#ifdef HAVE_DAG_STREAMS_API
+               if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)
+                       fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+               
+               if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)
+                       fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+#else
+               if(dag_stop(p->fd) < 0)
+                       fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+#endif /* HAVE_DAG_STREAMS_API */
+               if(p->fd != -1) {
+                       if(dag_close(p->fd) < 0)
+                               fprintf(stderr,"dag_close: %s\n", strerror(errno));
+                       p->fd = -1;
+               }
+               delete_pcap_dag(p);
+               pcap_cleanup_live_common(p);
+       }
+       /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
+}
+
+static void
+atexit_handler(void)
+{
+       while (pcap_dags != NULL) {
+               if (pcap_dags->pid == getpid()) {
+                       dag_platform_cleanup(pcap_dags->p);
+               } else {
+                       delete_pcap_dag(pcap_dags->p);
+               }
+       }
+}
+
+static int
+new_pcap_dag(pcap_t *p)
+{
+       pcap_dag_node_t *node = NULL;
+
+       if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
+               return -1;
+       }
+
+       if (!atexit_handler_installed) {
+               atexit(atexit_handler);
+               atexit_handler_installed = 1;
+       }
+
+       node->next = pcap_dags;
+       node->p = p;
+       node->pid = getpid();
+
+       pcap_dags = node;
+
+       return 0;
+}
+
+static unsigned int
+dag_erf_ext_header_count(uint8_t * erf, size_t len)
+{
+       uint32_t hdr_num = 0;
+       uint8_t  hdr_type;
+
+       /* basic sanity checks */
+       if ( erf == NULL )
+               return 0;
+       if ( len < 16 )
+               return 0;
+
+       /* check if we have any extension headers */
+       if ( (erf[8] & 0x80) == 0x00 )
+               return 0;
+
+       /* loop over the extension headers */
+       do {
+       
+               /* sanity check we have enough bytes */
+               if ( len <= (24 + (hdr_num * 8)) )
+                       return hdr_num;
+
+               /* get the header type */
+               hdr_type = erf[(16 + (hdr_num * 8))];
+               hdr_num++;
+
+       } while ( hdr_type & 0x80 );
+
+       return hdr_num;
+}
+
+/*
+ *  Read at most max_packets from the capture stream and call the callback
+ *  for each of them. Returns the number of packets handled, -1 if an
+ *  error occured, or -2 if we were told to break out of the loop.
+ */
+static int
+dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       unsigned int processed = 0;
+       int flags = p->md.dag_offset_flags;
+       unsigned int nonblocking = flags & DAGF_NONBLOCK;
+       unsigned int num_ext_hdr = 0;
+
+       /* Get the next bufferful of packets (if necessary). */
+       while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that
+                        * it has, and return -2 to indicate that
+                        * we were told to break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return -2;
+               }
+
+#ifdef HAVE_DAG_STREAMS_API
+               /* dag_advance_stream() will block (unless nonblock is called)
+                * until 64kB of data has accumulated.
+                * If to_ms is set, it will timeout before 64kB has accumulated.
+                * We wait for 64kB because processing a few packets at a time
+                * can cause problems at high packet rates (>200kpps) due
+                * to inefficiencies.
+                * This does mean if to_ms is not specified the capture may 'hang'
+                * for long periods if the data rate is extremely slow (<64kB/sec)
+                * If non-block is specified it will return immediately. The user
+                * is then responsible for efficiency.
+                */
+               if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) {
+                    return -1;
+               }
+#else
+               /* dag_offset does not support timeouts */
+               p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
+#endif /* HAVE_DAG_STREAMS_API */
+
+               if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
+               {
+                       /* Pcap is configured to process only available packets, and there aren't any, return immediately. */
+                       return 0;
+               }
+               
+               if(!nonblocking &&
+                  p->md.dag_timeout &&
+                  (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
+               {
+                       /* Blocking mode, but timeout set and no data has arrived, return anyway.*/
+                       return 0;
+               }
+
+       }
+       
+       /* Process the packets. */
+       while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
+               
+               unsigned short packet_len = 0;
+               int caplen = 0;
+               struct pcap_pkthdr      pcap_header;
+               
+#ifdef HAVE_DAG_STREAMS_API
+               dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
+#else
+               dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
+#endif /* HAVE_DAG_STREAMS_API */
+
+               u_char *dp = ((u_char *)header); /* + dag_record_size; */
+               unsigned short rlen;
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that
+                        * it has, and return -2 to indicate that
+                        * we were told to break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return -2;
+               }
+               rlen = ntohs(header->rlen);
+               if (rlen < dag_record_size)
+               {
+                       strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
+                       return -1;
+               }
+               p->md.dag_mem_bottom += rlen;
+
+               /* Count lost packets. */
+               switch((header->type & 0x7f)) {
+                       /* in these types the color value overwrites the lctr */
+               case TYPE_COLOR_HDLC_POS:
+               case TYPE_COLOR_ETH:
+               case TYPE_DSM_COLOR_HDLC_POS:
+               case TYPE_DSM_COLOR_ETH:
+               case TYPE_COLOR_MC_HDLC_POS:
+               case TYPE_COLOR_HASH_ETH:
+               case TYPE_COLOR_HASH_POS:
+                       break;
+
+               default:
+                       if (header->lctr) {
+                               if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
+                                       p->md.stat.ps_drop = UINT_MAX;
+                               } else {
+                                       p->md.stat.ps_drop += ntohs(header->lctr);
+                               }
+                       }
+               }
+               
+               if ((header->type & 0x7f) == TYPE_PAD) {
+                       continue;
+               }
+
+               num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
+
+               /* ERF encapsulation */
+               /* The Extensible Record Format is not dropped for this kind of encapsulation, 
+                * and will be handled as a pseudo header by the decoding application.
+                * The information carried in the ERF header and in the optional subheader (if present)
+                * could be merged with the libpcap information, to offer a better decoding.
+                * The packet length is
+                * o the length of the packet on the link (header->wlen),
+                * o plus the length of the ERF header (dag_record_size), as the length of the 
+                *   pseudo header will be adjusted during the decoding,
+                * o plus the length of the optional subheader (if present).
+                *
+                * The capture length is header.rlen and the byte stuffing for alignment will be dropped
+                * if the capture length is greater than the packet length.
+                */
+               if (p->linktype == DLT_ERF) {
+                       packet_len = ntohs(header->wlen) + dag_record_size;
+                       caplen = rlen;
+                       switch ((header->type & 0x7f)) {
+                       case TYPE_MC_AAL5:
+                       case TYPE_MC_ATM:
+                       case TYPE_MC_HDLC:
+                       case TYPE_MC_RAW_CHANNEL:
+                       case TYPE_MC_RAW:
+                       case TYPE_MC_AAL2:
+                       case TYPE_COLOR_MC_HDLC_POS:
+                               packet_len += 4; /* MC header */
+                               break;
+
+                       case TYPE_COLOR_HASH_ETH:
+                       case TYPE_DSM_COLOR_ETH:
+                       case TYPE_COLOR_ETH:
+                       case TYPE_ETH:
+                               packet_len += 2; /* ETH header */
+                               break;
+                       } /* switch type */
+
+                       /* Include ERF extension headers */
+                       packet_len += (8 * num_ext_hdr);
+
+                       if (caplen > packet_len) {
+                               caplen = packet_len;
+                       }
+               } else {
+                       /* Other kind of encapsulation according to the header Type */
+
+                       /* Skip over generic ERF header */
+                       dp += dag_record_size;
+                       /* Skip over extension headers */
+                       dp += 8 * num_ext_hdr;
+                       
+                       switch((header->type & 0x7f)) {
+                       case TYPE_ATM:
+                       case TYPE_AAL5:
+                               if (header->type == TYPE_AAL5) {
+                                       packet_len = ntohs(header->wlen);
+                                       caplen = rlen - dag_record_size;
+                               }
+                       case TYPE_MC_ATM:
+                               if (header->type == TYPE_MC_ATM) {
+                                       caplen = packet_len = ATM_CELL_SIZE;
+                                       dp+=4;
+                               }
+                       case TYPE_MC_AAL5:
+                               if (header->type == TYPE_MC_AAL5) {
+                                       packet_len = ntohs(header->wlen);
+                                       caplen = rlen - dag_record_size - 4;
+                                       dp+=4;
+                               }
+                               if (header->type == TYPE_ATM) {
+                                       caplen = packet_len = ATM_CELL_SIZE;
+                               }
+                               if (p->linktype == DLT_SUNATM) {
+                                       struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
+                                       unsigned long rawatm;
+                                       
+                                       rawatm = ntohl(*((unsigned long *)dp));
+                                       sunatm->vci = htons((rawatm >>  4) & 0xffff);
+                                       sunatm->vpi = (rawatm >> 20) & 0x00ff;
+                                       sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | 
+                                               ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
+                                                ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : 
+                                                 ((dp[ATM_HDR_SIZE] == 0xaa &&
+                                                   dp[ATM_HDR_SIZE+1] == 0xaa &&
+                                                   dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
+
+                               } else {
+                                       packet_len -= ATM_HDR_SIZE;
+                                       caplen -= ATM_HDR_SIZE;
+                                       dp += ATM_HDR_SIZE;
+                               }
+                               break;
+
+                       case TYPE_COLOR_HASH_ETH:
+                       case TYPE_DSM_COLOR_ETH:
+                       case TYPE_COLOR_ETH:
+                       case TYPE_ETH:
+                               packet_len = ntohs(header->wlen);
+                               packet_len -= (p->md.dag_fcs_bits >> 3);
+                               caplen = rlen - dag_record_size - 2;
+                               if (caplen > packet_len) {
+                                       caplen = packet_len;
+                               }
+                               dp += 2;
+                               break;
+
+                       case TYPE_COLOR_HASH_POS:
+                       case TYPE_DSM_COLOR_HDLC_POS:
+                       case TYPE_COLOR_HDLC_POS:
+                       case TYPE_HDLC_POS:
+                               packet_len = ntohs(header->wlen);
+                               packet_len -= (p->md.dag_fcs_bits >> 3);
+                               caplen = rlen - dag_record_size;
+                               if (caplen > packet_len) {
+                                       caplen = packet_len;
+                               }
+                               break;
+
+                       case TYPE_COLOR_MC_HDLC_POS:
+                       case TYPE_MC_HDLC:
+                               packet_len = ntohs(header->wlen);
+                               packet_len -= (p->md.dag_fcs_bits >> 3);
+                               caplen = rlen - dag_record_size - 4;
+                               if (caplen > packet_len) {
+                                       caplen = packet_len;
+                               }
+                               /* jump the MC_HDLC_HEADER */
+                               dp += 4;
+#ifdef DLT_MTP2_WITH_PHDR
+                               if (p->linktype == DLT_MTP2_WITH_PHDR) {
+                                       /* Add the MTP2 Pseudo Header */
+                                       caplen += MTP2_HDR_LEN;
+                                       packet_len += MTP2_HDR_LEN;
+                                       
+                                       TempPkt[MTP2_SENT_OFFSET] = 0;
+                                       TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
+                                       *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
+                                       *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
+                                       memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
+                                       dp = TempPkt;
+                               }
+#endif
+                               break;
+
+                       case TYPE_IPV4:
+                       case TYPE_IPV6:
+                               packet_len = ntohs(header->wlen);
+                               caplen = rlen - dag_record_size;
+                               if (caplen > packet_len) {
+                                       caplen = packet_len;
+                               }
+                               break;
+
+                       /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
+                       case TYPE_MC_RAW:
+                       case TYPE_MC_RAW_CHANNEL:
+                       case TYPE_IP_COUNTER:
+                       case TYPE_TCP_FLOW_COUNTER:
+                       case TYPE_INFINIBAND:
+                       case TYPE_RAW_LINK:
+                       case TYPE_INFINIBAND_LINK:
+                       default:
+                               /* Unhandled ERF type.
+                                * Ignore rather than generating error
+                                */
+                               continue;
+                       } /* switch type */
+
+                       /* Skip over extension headers */
+                       caplen -= (8 * num_ext_hdr);
+
+               } /* ERF encapsulation */
+               
+               if (caplen > p->snapshot)
+                       caplen = p->snapshot;
+
+               /* Run the packet filter if there is one. */
+               if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+                       
+                       /* convert between timestamp formats */
+                       register unsigned long long ts;
+                               
+                       if (IS_BIGENDIAN()) {
+                               ts = SWAPLL(header->ts);
+                       } else {
+                               ts = header->ts;
+                       }
+
+                       pcap_header.ts.tv_sec = ts >> 32;
+                       ts = (ts & 0xffffffffULL) * 1000000;
+                       ts += 0x80000000; /* rounding */
+                       pcap_header.ts.tv_usec = ts >> 32;              
+                       if (pcap_header.ts.tv_usec >= 1000000) {
+                               pcap_header.ts.tv_usec -= 1000000;
+                               pcap_header.ts.tv_sec++;
+                       }
+
+                       /* Fill in our own header data */
+                       pcap_header.caplen = caplen;
+                       pcap_header.len = packet_len;
+       
+                       /* Count the packet. */
+                       p->md.stat.ps_recv++;
+       
+                       /* Call the user supplied callback function */
+                       callback(user, &pcap_header, dp);
+       
+                       /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
+                       processed++;
+                       if (processed == cnt && cnt > 0)
+                       {
+                               /* Reached the user-specified limit. */
+                               return cnt;
+                       }
+               }
+       }
+
+       return processed;
+}
+
+static int
+dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+       strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
+           PCAP_ERRBUF_SIZE);
+       return (-1);
+}
+
+/*
+ *  Get a handle for a live capture from the given DAG device.  Passing a NULL
+ *  device will result in a failure.  The promisc flag is ignored because DAG
+ *  cards are always promiscuous.  The to_ms parameter is used in setting the
+ *  API polling parameters.
+ *  
+ *  snaplen is now also ignored, until we get per-stream slen support. Set
+ *  slen with approprite DAG tool BEFORE pcap_activate().
+ *
+ *  See also pcap(3).
+ */
+static int dag_activate(pcap_t* handle)
+{
+#if 0
+       char conf[30]; /* dag configure string */
+#endif
+       char *s;
+       int n;
+       daginf_t* daginf;
+       char * newDev = NULL;
+       char * device = handle->opt.source;
+#ifdef HAVE_DAG_STREAMS_API
+       uint32_t mindata;
+       struct timeval maxwait;
+       struct timeval poll;
+#endif
+
+       if (device == NULL) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       /* Initialize some components of the pcap structure. */
+
+#ifdef HAVE_DAG_STREAMS_API
+       newDev = (char *)malloc(strlen(device) + 16);
+       if (newDev == NULL) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+               goto fail;
+       }
+       
+       /* Parse input name to get dag device and stream number if provided */
+       if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
+               goto fail;
+       }
+       device = newDev;
+
+       if (handle->md.dag_stream%2) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
+               goto fail;
+       }
+#else
+       if (strncmp(device, "/dev/", 5) != 0) {
+               newDev = (char *)malloc(strlen(device) + 5);
+               if (newDev == NULL) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+                       goto fail;
+               }
+               strcpy(newDev, "/dev/");
+               strcat(newDev, device);
+               device = newDev;
+       }
+#endif /* HAVE_DAG_STREAMS_API */
+
+       /* setup device parameters */
+       if((handle->fd = dag_open((char *)device)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+               goto fail;
+       }
+
+#ifdef HAVE_DAG_STREAMS_API
+       /* Open requested stream. Can fail if already locked or on error */
+       if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
+               goto failclose;
+       }
+
+       /* Set up default poll parameters for stream
+        * Can be overridden by pcap_set_nonblock()
+        */
+       if (dag_get_stream_poll(handle->fd, handle->md.dag_stream,
+                               &mindata, &maxwait, &poll) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+               goto faildetach;
+       }
+       
+       /* Amount of data to collect in Bytes before calling callbacks.
+        * Important for efficiency, but can introduce latency
+        * at low packet rates if to_ms not set!
+        */
+       mindata = 65536;
+
+       /* Obey md.timeout (was to_ms) if supplied. This is a good idea!
+        * Recommend 10-100ms. Calls will time out even if no data arrived.
+        */
+       maxwait.tv_sec = handle->md.timeout/1000;
+       maxwait.tv_usec = (handle->md.timeout%1000) * 1000;
+
+       if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
+                               mindata, &maxwait, &poll) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+               goto faildetach;
+       }
+               
+#else
+       if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
+               goto failclose;
+       }
+
+#endif /* HAVE_DAG_STREAMS_API */
+
+        /* XXX Not calling dag_configure() to set slen; this is unsafe in
+        * multi-stream environments as the gpp config is global.
+         * Once the firmware provides 'per-stream slen' this can be supported
+        * again via the Config API without side-effects */
+#if 0
+       /* set the card snap length to the specified snaplen parameter */
+       /* This is a really bad idea, as different cards have different
+        * valid slen ranges. Should fix in Config API. */
+       if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
+               handle->snapshot = MAX_DAG_SNAPLEN;
+       } else if (snaplen < MIN_DAG_SNAPLEN) {
+               handle->snapshot = MIN_DAG_SNAPLEN;
+       }
+       /* snap len has to be a multiple of 4 */
+       snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); 
+
+       if(dag_configure(handle->fd, conf) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
+               goto faildetach;
+       }
+#endif 
+       
+#ifdef HAVE_DAG_STREAMS_API
+       if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
+               goto faildetach;
+       }
+#else
+       if(dag_start(handle->fd) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
+               goto failclose;
+       }
+#endif /* HAVE_DAG_STREAMS_API */
+
+       /*
+        * Important! You have to ensure bottom is properly
+        * initialized to zero on startup, it won't give you
+        * a compiler warning if you make this mistake!
+        */
+       handle->md.dag_mem_bottom = 0;
+       handle->md.dag_mem_top = 0;
+
+       /*
+        * Find out how many FCS bits we should strip.
+        * First, query the card to see if it strips the FCS.
+        */
+       daginf = dag_info(handle->fd);
+       if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) {
+               /* DAG 4.2S and 4.23S already strip the FCS.  Stripping the final word again truncates the packet. */
+               handle->md.dag_fcs_bits = 0;
+
+               /* Note that no FCS will be supplied. */
+               handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
+       } else {
+               /*
+                * Start out assuming it's 32 bits.
+                */
+               handle->md.dag_fcs_bits = 32;
+
+               /* Allow an environment variable to override. */
+               if ((s = getenv("ERF_FCS_BITS")) != NULL) {
+                       if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
+                               handle->md.dag_fcs_bits = n;
+                       } else {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
+                               goto failstop;
+                       }
+               }
+
+               /*
+                * Did the user request that they not be stripped?
+                */
+               if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
+                       /* Yes.  Note the number of bytes that will be
+                          supplied. */
+                       handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16);
+
+                       /* And don't strip them. */
+                       handle->md.dag_fcs_bits = 0;
+               }
+       }
+
+       handle->md.dag_timeout  = handle->md.timeout;
+
+       handle->linktype = -1;
+       if (dag_get_datalink(handle) < 0)
+               goto failstop;
+       
+       handle->bufsize = 0;
+
+       if (new_pcap_dag(handle) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
+               goto failstop;
+       }
+
+       /*
+        * "select()" and "poll()" don't work on DAG device descriptors.
+        */
+       handle->selectable_fd = -1;
+
+       if (newDev != NULL) {
+               free((char *)newDev);
+       }
+
+       handle->read_op = dag_read;
+       handle->inject_op = dag_inject;
+       handle->setfilter_op = dag_setfilter;
+       handle->setdirection_op = NULL; /* Not implemented.*/
+       handle->set_datalink_op = dag_set_datalink;
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = dag_setnonblock;
+       handle->stats_op = dag_stats;
+       handle->cleanup_op = dag_platform_cleanup;
+       handle->md.stat.ps_drop = 0;
+       handle->md.stat.ps_recv = 0;
+       handle->md.stat.ps_ifdrop = 0;
+       return 0;
+
+#ifdef HAVE_DAG_STREAMS_API 
+failstop:
+       if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) {
+               fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+       }
+       
+faildetach:
+       if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0)
+               fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+#else
+failstop:
+       if (dag_stop(handle->fd) < 0)
+               fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+#endif /* HAVE_DAG_STREAMS_API */
+       
+failclose:
+       if (dag_close(handle->fd) < 0)
+               fprintf(stderr,"dag_close: %s\n", strerror(errno));
+       delete_pcap_dag(handle);
+
+fail:
+       pcap_cleanup_live_common(handle);
+       if (newDev != NULL) {
+               free((char *)newDev);
+       }
+
+       return PCAP_ERROR;
+}
+
+pcap_t *dag_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return NULL;
+
+       p->activate_op = dag_activate;
+       return p;
+}
+
+static int
+dag_stats(pcap_t *p, struct pcap_stat *ps) {
+       /* This needs to be filled out correctly.  Hopefully a dagapi call will
+                provide all necessary information.
+       */
+       /*p->md.stat.ps_recv = 0;*/
+       /*p->md.stat.ps_drop = 0;*/
+       
+       *ps = p->md.stat;
+       return 0;
+}
+
+/*
+ * Previously we just generated a list of all possible names and let
+ * pcap_add_if() attempt to open each one, but with streams this adds up
+ * to 81 possibilities which is inefficient.
+ *
+ * Since we know more about the devices we can prune the tree here.
+ * pcap_add_if() will still retest each device but the total number of
+ * open attempts will still be much less than the naive approach.
+ */
+int
+dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
+{
+       char name[12];  /* XXX - pick a size */
+       int ret = 0;
+       int c;
+       char dagname[DAGNAME_BUFSIZE];
+       int dagstream;
+       int dagfd;
+
+       /* Try all the DAGs 0-31 */
+       for (c = 0; c < 32; c++) {
+               snprintf(name, 12, "dag%d", c);
+               if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
+               {
+                       return -1;
+               }
+               if ( (dagfd = dag_open(dagname)) >= 0 ) {
+                       if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+                               /*
+                                * Failure.
+                                */
+                               ret = -1;
+                       }
+#ifdef HAVE_DAG_STREAMS_API
+                       {
+                               int stream, rxstreams;
+                               rxstreams = dag_rx_get_stream_count(dagfd);
+                               for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
+                                       if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
+                                               dag_detach_stream(dagfd, stream);
+
+                                               snprintf(name,  10, "dag%d:%d", c, stream);
+                                               if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+                                                       /*
+                                                        * Failure.
+                                                        */
+                                                       ret = -1;
+                                               }
+                                               
+                                               rxstreams--;
+                                               if(rxstreams <= 0) {
+                                                       break;
+                                               }
+                                       }
+                               }                               
+                       }
+#endif  /* HAVE_DAG_STREAMS_API */
+                       dag_close(dagfd);
+               }
+
+       }
+       return (ret);
+}
+
+/*
+ * Installs the given bpf filter program in the given pcap structure.  There is
+ * no attempt to store the filter in kernel memory as that is not supported
+ * with DAG cards.
+ */
+static int
+dag_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       if (!p)
+               return -1;
+       if (!fp) {
+               strncpy(p->errbuf, "setfilter: No filter specified",
+                       sizeof(p->errbuf));
+               return -1;
+       }
+
+       /* Make our private copy of the filter */
+
+       if (install_bpf_program(p, fp) < 0)
+               return -1;
+
+       p->md.use_bpf = 0;
+
+       return (0);
+}
+
+static int
+dag_set_datalink(pcap_t *p, int dlt)
+{
+       p->linktype = dlt;
+
+       return (0);
+}
+
+static int
+dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+       /*
+        * Set non-blocking mode on the FD.
+        * XXX - is that necessary?  If not, don't bother calling it,
+        * and have a "dag_getnonblock()" function that looks at
+        * "p->md.dag_offset_flags".
+        */
+       if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
+               return (-1);
+#ifdef HAVE_DAG_STREAMS_API
+       {
+               uint32_t mindata;
+               struct timeval maxwait;
+               struct timeval poll;
+               
+               if (dag_get_stream_poll(p->fd, p->md.dag_stream,
+                                       &mindata, &maxwait, &poll) < 0) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+                       return -1;
+               }
+               
+               /* Amount of data to collect in Bytes before calling callbacks.
+                * Important for efficiency, but can introduce latency
+                * at low packet rates if to_ms not set!
+                */
+               if(nonblock)
+                       mindata = 0;
+               else
+                       mindata = 65536;
+               
+               if (dag_set_stream_poll(p->fd, p->md.dag_stream,
+                                       mindata, &maxwait, &poll) < 0) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+                       return -1;
+               }
+       }
+#endif /* HAVE_DAG_STREAMS_API */
+       if (nonblock) {
+               p->md.dag_offset_flags |= DAGF_NONBLOCK;
+       } else {
+               p->md.dag_offset_flags &= ~DAGF_NONBLOCK;
+       }
+       return (0);
+}
+               
+static int
+dag_get_datalink(pcap_t *p)
+{
+       int index=0, dlt_index=0;
+       uint8_t types[255];
+
+       memset(types, 0, 255);
+
+       if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
+               (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       p->linktype = 0;
+
+#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
+       /* Get list of possible ERF types for this card */
+       if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) {
+               snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
+               return (-1);            
+       }
+       
+       while (types[index]) {
+
+#elif defined HAVE_DAG_GET_ERF_TYPES
+       /* Get list of possible ERF types for this card */
+       if (dag_get_erf_types(p->fd, types, 255) < 0) {
+               snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
+               return (-1);            
+       }
+       
+       while (types[index]) {
+#else
+       /* Check the type through a dagapi call. */
+       types[index] = dag_linktype(p->fd);
+
+       {
+#endif
+               switch((types[index] & 0x7f)) {
+
+               case TYPE_HDLC_POS:
+               case TYPE_COLOR_HDLC_POS:
+               case TYPE_DSM_COLOR_HDLC_POS:
+               case TYPE_COLOR_HASH_POS:
+
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_CHDLC;
+                               p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+                               p->dlt_list[dlt_index++] = DLT_FRELAY;
+                       }
+                       if(!p->linktype)
+                               p->linktype = DLT_CHDLC;
+                       break;
+
+               case TYPE_ETH:
+               case TYPE_COLOR_ETH:
+               case TYPE_DSM_COLOR_ETH:
+               case TYPE_COLOR_HASH_ETH:
+                       /*
+                        * This is (presumably) a real Ethernet capture; give it a
+                        * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                        * that an application can let you choose it, in case you're
+                        * capturing DOCSIS traffic that a Cisco Cable Modem
+                        * Termination System is putting out onto an Ethernet (it
+                        * doesn't put an Ethernet header onto the wire, it puts raw
+                        * DOCSIS frames out on the wire inside the low-level
+                        * Ethernet framing).
+                        */
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_EN10MB;
+                               p->dlt_list[dlt_index++] = DLT_DOCSIS;
+                       }
+                       if(!p->linktype)
+                               p->linktype = DLT_EN10MB;
+                       break;
+
+               case TYPE_ATM: 
+               case TYPE_AAL5:
+               case TYPE_MC_ATM:
+               case TYPE_MC_AAL5:
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
+                               p->dlt_list[dlt_index++] = DLT_SUNATM;
+                       }
+                       if(!p->linktype)
+                               p->linktype = DLT_ATM_RFC1483;
+                       break;
+
+               case TYPE_COLOR_MC_HDLC_POS:
+               case TYPE_MC_HDLC:
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_CHDLC;
+                               p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+                               p->dlt_list[dlt_index++] = DLT_FRELAY;
+                               p->dlt_list[dlt_index++] = DLT_MTP2;
+                               p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
+                               p->dlt_list[dlt_index++] = DLT_LAPD;
+                       }
+                       if(!p->linktype)
+                               p->linktype = DLT_CHDLC;
+                       break;
+
+               case TYPE_IPV4:
+               case TYPE_IPV6:
+                       if(!p->linktype)
+                               p->linktype = DLT_RAW;
+                       break;
+
+               case TYPE_LEGACY:
+               case TYPE_MC_RAW:
+               case TYPE_MC_RAW_CHANNEL:
+               case TYPE_IP_COUNTER:
+               case TYPE_TCP_FLOW_COUNTER:
+               case TYPE_INFINIBAND:
+               case TYPE_RAW_LINK:
+               case TYPE_INFINIBAND_LINK:
+               default:
+                       /* Libpcap cannot deal with these types yet */
+                       /* Add no 'native' DLTs, but still covered by DLT_ERF */
+                       break;
+
+               } /* switch */
+               index++;
+       }
+
+       p->dlt_list[dlt_index++] = DLT_ERF;
+
+       p->dlt_count = dlt_index;
+
+       if(!p->linktype)
+               p->linktype = DLT_ERF;
+
+       return p->linktype;
+}
diff --git a/pcap-dag.h b/pcap-dag.h
new file mode 100644 (file)
index 0000000..fcdef7b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * pcap-dag.c: Packet capture interface for Endace DAG card.
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible.  This code is only needed when compiling in the DAG card code
+ * at the same time as another type of device.
+ *
+ * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.7 2008-04-04 19:37:45 guy Exp $ (LBL)
+ */
+
+pcap_t *dag_create(const char *, char *);
+int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
+
+#ifndef TYPE_AAL5
+#define TYPE_AAL5               4
+#endif
+
+#ifndef TYPE_MC_HDLC
+#define TYPE_MC_HDLC            5
+#endif
+
+#ifndef TYPE_MC_RAW
+#define TYPE_MC_RAW             6
+#endif
+
+#ifndef TYPE_MC_ATM
+#define TYPE_MC_ATM             7
+#endif
+
+#ifndef TYPE_MC_RAW_CHANNEL
+#define TYPE_MC_RAW_CHANNEL     8
+#endif
+
+#ifndef TYPE_MC_AAL5
+#define TYPE_MC_AAL5            9
+#endif
+
+#ifndef TYPE_COLOR_HDLC_POS
+#define TYPE_COLOR_HDLC_POS     10
+#endif
+
+#ifndef TYPE_COLOR_ETH
+#define TYPE_COLOR_ETH          11
+#endif
+
+#ifndef TYPE_MC_AAL2
+#define TYPE_MC_AAL2            12
+#endif
+
+#ifndef TYPE_IP_COUNTER
+#define TYPE_IP_COUNTER         13
+#endif
+
+#ifndef TYPE_TCP_FLOW_COUNTER
+#define TYPE_TCP_FLOW_COUNTER   14
+#endif
+
+#ifndef TYPE_DSM_COLOR_HDLC_POS
+#define TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef TYPE_DSM_COLOR_ETH
+#define TYPE_DSM_COLOR_ETH      16
+#endif
+
+#ifndef TYPE_COLOR_MC_HDLC_POS
+#define TYPE_COLOR_MC_HDLC_POS  17
+#endif
+
+#ifndef TYPE_AAL2
+#define TYPE_AAL2               18
+#endif
+
+#ifndef TYPE_COLOR_HASH_POS
+#define TYPE_COLOR_HASH_POS     19
+#endif
+
+#ifndef TYPE_COLOR_HASH_ETH
+#define TYPE_COLOR_HASH_ETH     20
+#endif
+
+#ifndef TYPE_INFINIBAND
+#define TYPE_INFINIBAND         21
+#endif
+
+#ifndef TYPE_IPV4
+#define TYPE_IPV4               22
+#endif
+
+#ifndef TYPE_IPV6
+#define TYPE_IPV6               23
+#endif
+
+#ifndef TYPE_RAW_LINK
+#define TYPE_RAW_LINK           24
+#endif
+
+#ifndef TYPE_INFINIBAND_LINK
+#define TYPE_INFINIBAND_LINK    25
+#endif
+
+
+
+#ifndef TYPE_PAD
+#define TYPE_PAD                48
+#endif
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
new file mode 100644 (file)
index 0000000..78bb451
--- /dev/null
@@ -0,0 +1,1708 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
+ * University College London, and subsequently modified by
+ * Guy Harris (guy@alum.mit.edu), Mark Pizzolato
+ * <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
+ */
+
+/*
+ * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX.
+ *
+ * Notes:
+ *
+ *    - The DLIOCRAW ioctl() is specific to SunOS.
+ *
+ *    - There is a bug in bufmod(7) such that setting the snapshot
+ *      length results in data being left of the front of the packet.
+ *
+ *    - It might be desirable to use pfmod(7) to filter packets in the
+ *      kernel when possible.
+ *
+ *    - An older version of the HP-UX DLPI Programmer's Guide, which
+ *      I think was advertised as the 10.20 version, used to be available
+ *      at
+ *
+ *            http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
+ *
+ *      but is no longer available; it can still be found at
+ *
+ *            http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf
+ *
+ *      in PDF form.
+ *
+ *    - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI
+ *      Programmer's Guide, which I think was once advertised as the
+ *      11.00 version is available at
+ *
+ *            http://docs.hp.com/en/B2355-90139/index.html
+ *
+ *    - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide
+ *      is available at
+ *
+ *            http://docs.hp.com/en/B2355-90871/index.html
+ *
+ *    - All of the HP documents describe raw-mode services, which are
+ *      what we use if DL_HP_RAWDLS is defined.  XXX - we use __hpux
+ *      in some places to test for HP-UX, but use DL_HP_RAWDLS in
+ *      other places; do we support any versions of HP-UX without
+ *      DL_HP_RAWDLS?
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.128 2008-12-02 16:20:23 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#include <sys/dlpi.h>
+#ifdef HAVE_SYS_DLPI_EXT_H
+#include <sys/dlpi_ext.h>
+#endif
+#ifdef HAVE_HPUX9
+#include <sys/socket.h>
+#endif
+#ifdef DL_HP_PPA_REQ
+#include <sys/stat.h>
+#endif
+#include <sys/stream.h>
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+#include <sys/systeminfo.h>
+#endif
+
+#ifdef HAVE_HPUX9
+#include <net/if.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_HPUX9
+#include <nlist.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX                2147483647
+#endif
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef PCAP_DEV_PREFIX
+#ifdef _AIX
+#define PCAP_DEV_PREFIX "/dev/dlpi"
+#else
+#define PCAP_DEV_PREFIX "/dev"
+#endif
+#endif
+
+#define        MAXDLBUF        8192
+
+/* Forwards */
+static char *split_dname(char *, int *, char *);
+static int dl_doattach(int, int, char *);
+#ifdef DL_HP_RAWDLS
+static int dl_dohpuxbind(int, char *);
+#endif
+static int dlpromiscon(pcap_t *, bpf_u_int32);
+static int dlbindreq(int, bpf_u_int32, char *);
+static int dlbindack(int, char *, char *, int *);
+static int dlokack(int, const char *, char *, char *);
+static int dlinforeq(int, char *);
+static int dlinfoack(int, char *, char *);
+
+#ifdef HAVE_DLPI_PASSIVE
+static void dlpassive(int, char *);
+#endif
+
+#ifdef DL_HP_RAWDLS
+static int dlrawdatareq(int, const u_char *, int);
+#endif
+static int recv_ack(int, int, const char *, char *, char *, int *);
+static char *dlstrerror(bpf_u_int32);
+static char *dlprim(bpf_u_int32);
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
+#endif
+static int send_request(int, char *, int, char *, char *);
+#ifdef HAVE_HPUX9
+static int dlpi_kread(int, off_t, void *, u_int, char *);
+#endif
+#ifdef HAVE_DEV_DLPI
+static int get_dlpi_ppa(int, const char *, int, char *);
+#endif
+
+/* XXX Needed by HP-UX (at least) */
+static bpf_u_int32 ctlbuf[MAXDLBUF];
+static struct strbuf ctl = {
+       MAXDLBUF,
+       0,
+       (char *)ctlbuf
+};
+
+/*
+ * Cast a buffer to "union DL_primitives" without provoking warnings
+ * from the compiler.
+ */
+#define MAKE_DL_PRIMITIVES(ptr)        ((union DL_primitives *)(void *)(ptr))
+
+static int
+pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       u_char *bp;
+       int flags;
+       struct strbuf data;
+
+       flags = 0;
+       cc = p->cc;
+       if (cc == 0) {
+               data.buf = (char *)p->buffer + p->offset;
+               data.maxlen = p->bufsize;
+               data.len = 0;
+               do {
+                       /*
+                        * Has "pcap_breakloop()" been called?
+                        */
+                       if (p->break_loop) {
+                               /*
+                                * Yes - clear the flag that indicates
+                                * that it has, and return -2 to
+                                * indicate that we were told to
+                                * break out of the loop.
+                                */
+                               p->break_loop = 0;
+                               return (-2);
+                       }
+                       /*
+                        * XXX - check for the DLPI primitive, which
+                        * would be DL_HP_RAWDATA_IND on HP-UX
+                        * if we're in raw mode?
+                        */
+                       if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
+                               /* Don't choke when we get ptraced */
+                               switch (errno) {
+
+                               case EINTR:
+                                       cc = 0;
+                                       continue;
+
+                               case EAGAIN:
+                                       return (0);
+                               }
+                               strlcpy(p->errbuf, pcap_strerror(errno),
+                                   sizeof(p->errbuf));
+                               return (-1);
+                       }
+                       cc = data.len;
+               } while (cc == 0);
+               bp = p->buffer + p->offset;
+       } else
+               bp = p->bp;
+
+       return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
+}
+
+static int
+pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
+{
+       int ret;
+
+#if defined(DLIOCRAW)
+       ret = write(p->fd, buf, size);
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+#elif defined(DL_HP_RAWDLS)
+       if (p->send_fd < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "send: Output FD couldn't be opened");
+               return (-1);
+       }
+       ret = dlrawdatareq(p->send_fd, buf, size);
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       /*
+        * putmsg() returns either 0 or -1; it doesn't indicate how
+        * many bytes were written (presumably they were all written
+        * or none of them were written).  OpenBSD's pcap_inject()
+        * returns the number of bytes written, so, for API compatibility,
+        * we return the number of bytes we were told to write.
+        */
+       ret = size;
+#else /* no raw mode */
+       /*
+        * XXX - this is a pain, because you might have to extract
+        * the address from the packet and use it in a DL_UNITDATA_REQ
+        * request.  That would be dependent on the link-layer type.
+        *
+        * I also don't know what SAP you'd have to bind the descriptor
+        * to, or whether you'd need separate "receive" and "send" FDs,
+        * nor do I know whether you'd need different bindings for
+        * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus
+        * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.
+        *
+        * So, for now, we just return a "you can't send" indication,
+        * and leave it up to somebody with a DLPI-based system lacking
+        * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement
+        * packet transmission on that system.  If they do, they should
+        * send it to us - but should not send us code that assumes
+        * Ethernet; if the code doesn't work on non-Ethernet interfaces,
+        * it should check "p->linktype" and reject the send request if
+        * it's anything other than DLT_EN10MB.
+        */
+       strlcpy(p->errbuf, "send: Not supported on this version of this OS",
+           PCAP_ERRBUF_SIZE);
+       ret = -1;
+#endif /* raw mode */
+       return (ret);
+}   
+
+#ifndef DL_IPATM
+#define DL_IPATM       0x12    /* ATM Classical IP interface */
+#endif
+
+#ifdef HAVE_SOLARIS
+/*
+ * For SunATM.
+ */
+#ifndef A_GET_UNITS
+#define A_GET_UNITS    (('A'<<8)|118)
+#endif /* A_GET_UNITS */
+#ifndef A_PROMISCON_REQ
+#define A_PROMISCON_REQ        (('A'<<8)|121)
+#endif /* A_PROMISCON_REQ */
+#endif /* HAVE_SOLARIS */
+
+static void
+pcap_cleanup_dlpi(pcap_t *p)
+{
+       if (p->send_fd >= 0) {
+               close(p->send_fd);
+               p->send_fd = -1;
+       }
+       pcap_cleanup_live_common(p);
+}
+
+static int
+pcap_activate_dlpi(pcap_t *p)
+{
+       register char *cp;
+       int ppa;
+#ifdef HAVE_SOLARIS
+       int isatm = 0;
+#endif
+       register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+       bpf_u_int32 ss;
+#ifdef HAVE_SOLARIS
+       register char *release;
+       bpf_u_int32 osmajor, osminor, osmicro;
+#endif
+#endif
+       bpf_u_int32 buf[MAXDLBUF];
+       char dname[100];
+#ifndef HAVE_DEV_DLPI
+       char dname2[100];
+#endif
+       int status = PCAP_ERROR;
+
+#ifdef HAVE_DEV_DLPI
+       /*
+       ** Remove any "/dev/" on the front of the device.
+       */
+       cp = strrchr(p->opt.source, '/');
+       if (cp == NULL)
+               strlcpy(dname, p->opt.source, sizeof(dname));
+       else
+               strlcpy(dname, cp + 1, sizeof(dname));
+
+       /*
+        * Split the device name into a device type name and a unit number;
+        * chop off the unit number, so "dname" is just a device type name.
+        */
+       cp = split_dname(dname, &ppa, p->errbuf);
+       if (cp == NULL) {
+               status = PCAP_ERROR_NO_SUCH_DEVICE;
+               goto bad;
+       }
+       *cp = '\0';
+
+       /*
+        * Use "/dev/dlpi" as the device.
+        *
+        * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that
+        * the "dl_mjr_num" field is for the "major number of interface
+        * driver"; that's the major of "/dev/dlpi" on the system on
+        * which I tried this, but there may be DLPI devices that
+        * use a different driver, in which case we may need to
+        * search "/dev" for the appropriate device with that major
+        * device number, rather than hardwiring "/dev/dlpi".
+        */
+       cp = "/dev/dlpi";
+       if ((p->fd = open(cp, O_RDWR)) < 0) {
+               if (errno == EPERM || errno == EACCES)
+                       status = PCAP_ERROR_PERM_DENIED;
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: %s", cp, pcap_strerror(errno));
+               goto bad;
+       }
+
+#ifdef DL_HP_RAWDLS
+       /*
+        * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
+        * receiving packets on the same descriptor - you need separate
+        * descriptors for sending and receiving, bound to different SAPs.
+        *
+        * If the open fails, we just leave -1 in "p->send_fd" and reject
+        * attempts to send packets, just as if, in pcap-bpf.c, we fail
+        * to open the BPF device for reading and writing, we just try
+        * to open it for reading only and, if that succeeds, just let
+        * the send attempts fail.
+        */
+       p->send_fd = open(cp, O_RDWR);
+#endif
+
+       /*
+        * Get a table of all PPAs for that device, and search that
+        * table for the specified device type name and unit number.
+        */
+       ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
+       if (ppa < 0) {
+               status = ppa;
+               goto bad;
+       }
+#else
+       /*
+        * If the device name begins with "/", assume it begins with
+        * the pathname of the directory containing the device to open;
+        * otherwise, concatenate the device directory name and the
+        * device name.
+        */
+       if (*p->opt.source == '/')
+               strlcpy(dname, p->opt.source, sizeof(dname));
+       else
+               snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
+                   p->opt.source);
+
+       /*
+        * Get the unit number, and a pointer to the end of the device
+        * type name.
+        */
+       cp = split_dname(dname, &ppa, p->errbuf);
+       if (cp == NULL) {
+               status = PCAP_ERROR_NO_SUCH_DEVICE;
+               goto bad;
+       }
+
+       /*
+        * Make a copy of the device pathname, and then remove the unit
+        * number from the device pathname.
+        */
+       strlcpy(dname2, dname, sizeof(dname));
+       *cp = '\0';
+
+       /* Try device without unit number */
+       if ((p->fd = open(dname, O_RDWR)) < 0) {
+               if (errno != ENOENT) {
+                       if (errno == EPERM || errno == EACCES)
+                               status = PCAP_ERROR_PERM_DENIED;
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
+                           pcap_strerror(errno));
+                       goto bad;
+               }
+
+               /* Try again with unit number */
+               if ((p->fd = open(dname2, O_RDWR)) < 0) {
+                       if (errno == ENOENT) {
+                               status = PCAP_ERROR_NO_SUCH_DEVICE;
+
+                               /*
+                                * We provide an error message even
+                                * for this error, for diagnostic
+                                * purposes (so that, for example,
+                                * the app can show the message if the
+                                * user requests it).
+                                *
+                                * In it, we just report "No DLPI device
+                                * found" with the device name, so people
+                                * don't get confused and think, for example,
+                                * that if they can't capture on "lo0"
+                                * on Solaris the fix is to change libpcap
+                                * (or the application that uses it) to
+                                * look for something other than "/dev/lo0",
+                                * as the fix is to look for an operating
+                                * system other than Solaris - you just
+                                * *can't* capture on a loopback interface
+                                * on Solaris, the lack of a DLPI device
+                                * for the loopback interface is just a
+                                * symptom of that inability.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "%s: No DLPI device found", p->opt.source);
+                       } else {
+                               if (errno == EPERM || errno == EACCES)
+                                       status = PCAP_ERROR_PERM_DENIED;
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+                                   dname2, pcap_strerror(errno));
+                       }
+                       goto bad;
+               }
+               /* XXX Assume unit zero */
+               ppa = 0;
+       }
+#endif
+
+       /*
+       ** Attach if "style 2" provider
+       */
+       if (dlinforeq(p->fd, p->errbuf) < 0 ||
+           dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
+               goto bad;
+       infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
+#ifdef HAVE_SOLARIS
+       if (infop->dl_mac_type == DL_IPATM)
+               isatm = 1;
+#endif
+       if (infop->dl_provider_style == DL_STYLE2) {
+               status = dl_doattach(p->fd, ppa, p->errbuf);
+               if (status < 0)
+                       goto bad;
+#ifdef DL_HP_RAWDLS
+               if (p->send_fd >= 0) {
+                       if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0)
+                               goto bad;
+               }
+#endif
+       }
+
+       if (p->opt.rfmon) {
+               /*
+                * This device exists, but we don't support monitor mode
+                * any platforms that support DLPI.
+                */
+               status = PCAP_ERROR_RFMON_NOTSUP;
+               goto bad;
+       }
+
+#ifdef HAVE_DLPI_PASSIVE
+       /*
+        * Enable Passive mode to be able to capture on aggregated link.
+        * Not supported in all Solaris versions.
+        */
+       dlpassive(p->fd, p->errbuf);
+#endif
+       /*
+       ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
+       ** skip if using SINIX)
+       */
+#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)
+#ifdef _AIX
+       /*
+       ** AIX.
+       ** According to IBM's AIX Support Line, the dl_sap value
+       ** should not be less than 0x600 (1536) for standard Ethernet.
+       ** However, we seem to get DL_BADADDR - "DLSAP addr in improper
+       ** format or invalid" - errors if we use 1537 on the "tr0"
+       ** device, which, given that its name starts with "tr" and that
+       ** it's IBM, probably means a Token Ring device.  (Perhaps we
+       ** need to use 1537 on "/dev/dlpi/en" because that device is for
+       ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and
+       ** it rejects invalid Ethernet types.)
+       **
+       ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea
+       ** says that works on Token Ring (he says that 0 does *not*
+       ** work; perhaps that's considered an invalid LLC SAP value - I
+       ** assume the SAP value in a DLPI bind is an LLC SAP for network
+       ** types that use 802.2 LLC).
+       */
+       if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 &&
+            dlbindreq(p->fd, 2, p->errbuf) < 0) ||
+            dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
+               goto bad;
+#elif defined(DL_HP_RAWDLS)
+       /*
+       ** HP-UX 10.0x and 10.1x.
+       */
+       if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
+               goto bad;
+       if (p->send_fd >= 0) {
+               /*
+               ** XXX - if this fails, just close send_fd and
+               ** set it to -1, so that you can't send but can
+               ** still receive?
+               */
+               if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
+                       goto bad;
+       }
+#else /* neither AIX nor HP-UX */
+       /*
+       ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
+       ** OS using DLPI.
+       **/
+       if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
+           dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
+               goto bad;
+#endif /* AIX vs. HP-UX vs. other */
+#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
+
+#ifdef HAVE_SOLARIS
+       if (isatm) {
+               /*
+               ** Have to turn on some special ATM promiscuous mode
+               ** for SunATM.
+               ** Do *NOT* turn regular promiscuous mode on; it doesn't
+               ** help, and may break things.
+               */
+               if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "A_PROMISCON_REQ: %s", pcap_strerror(errno));
+                       goto bad;
+               }
+       } else
+#endif
+       if (p->opt.promisc) {
+               /*
+               ** Enable promiscuous (not necessary on send FD)
+               */
+               status = dlpromiscon(p, DL_PROMISC_PHYS);
+               if (status < 0) {
+                       if (status == PCAP_ERROR_PERM_DENIED)
+                               status = PCAP_ERROR_PROMISC_PERM_DENIED;
+                       goto bad;
+               }
+
+               /*
+               ** Try to enable multicast (you would have thought
+               ** promiscuous would be sufficient). (Skip if using
+               ** HP-UX or SINIX) (Not necessary on send FD)
+               */
+#if !defined(__hpux) && !defined(sinix)
+               status = dlpromiscon(p, DL_PROMISC_MULTI);
+               if (status < 0)
+                       status = PCAP_WARNING;
+#endif
+       }
+       /*
+       ** Try to enable SAP promiscuity (when not in promiscuous mode
+       ** when using HP-UX, when not doing SunATM on Solaris, and never
+       ** under SINIX) (Not necessary on send FD)
+       */
+#ifndef sinix
+#if defined(__hpux)
+       /* HP-UX - only do this when not in promiscuous mode */
+       if (!p->opt.promisc) {
+#elif defined(HAVE_SOLARIS)
+       /* Solaris - don't do this on SunATM devices */
+       if (!isatm) {
+#else
+       /* Everything else (except for SINIX) - always do this */
+       {
+#endif
+               status = dlpromiscon(p, DL_PROMISC_SAP);
+               if (status < 0) {
+                       /*
+                        * Not fatal, since the DL_PROMISC_PHYS mode worked.
+                        * Report it as a warning, however.
+                        */
+                       if (p->opt.promisc)
+                               status = PCAP_WARNING;
+                       else
+                               goto bad;
+               }
+       }
+#endif /* sinix */
+
+       /*
+       ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting
+       ** promiscuous options.
+       */
+#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
+       if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
+               goto bad;
+       /*
+       ** We don't set promiscuous mode on the send FD, but we'll defer
+       ** binding it anyway, just to keep the HP-UX 9/10.20 or later
+       ** code together.
+       */
+       if (p->send_fd >= 0) {
+               /*
+               ** XXX - if this fails, just close send_fd and
+               ** set it to -1, so that you can't send but can
+               ** still receive?
+               */
+               if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
+                       goto bad;
+       }
+#endif
+
+       /*
+       ** Determine link type
+       ** XXX - get SAP length and address length as well, for use
+       ** when sending packets.
+       */
+       if (dlinforeq(p->fd, p->errbuf) < 0 ||
+           dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
+               goto bad;
+
+       infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
+       if (pcap_process_mactype(p, infop->dl_mac_type) != 0)
+               goto bad;
+
+#ifdef DLIOCRAW
+       /*
+       ** This is a non standard SunOS hack to get the full raw link-layer
+       ** header.
+       */
+       if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+       ss = p->snapshot;
+
+       /*
+       ** There is a bug in bufmod(7). When dealing with messages of
+       ** less than snaplen size it strips data from the beginning not
+       ** the end.
+       **
+       ** This bug is fixed in 5.3.2. Also, there is a patch available.
+       ** Ask for bugid 1149065.
+       */
+#ifdef HAVE_SOLARIS
+       release = get_release(&osmajor, &osminor, &osmicro);
+       if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
+           getenv("BUFMOD_FIXED") == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+               "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
+                   release);
+               ss = 0;
+               status = PCAP_WARNING;
+       }
+#endif
+
+       /* Push and configure bufmod. */
+       if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0)
+               goto bad;
+#endif
+
+       /*
+       ** As the last operation flush the read side.
+       */
+       if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* Allocate data buffer. */
+       if (pcap_alloc_databuf(p) != 0)
+               goto bad;
+
+       /* Success - but perhaps with a warning */
+       if (status < 0)
+               status = 0;
+
+       /*
+        * "p->fd" is an FD for a STREAMS device, so "select()" and
+        * "poll()" should work on it.
+        */
+       p->selectable_fd = p->fd;
+
+       p->read_op = pcap_read_dlpi;
+       p->inject_op = pcap_inject_dlpi;
+       p->setfilter_op = install_bpf_program;  /* no kernel filtering */
+       p->setdirection_op = NULL;      /* Not implemented.*/
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_dlpi;
+       p->cleanup_op = pcap_cleanup_dlpi;
+
+       return (status);
+bad:
+       pcap_cleanup_dlpi(p);
+       return (status);
+}
+
+/*
+ * Split a device name into a device type name and a unit number;
+ * return the a pointer to the beginning of the unit number, which
+ * is the end of the device type name, and set "*unitp" to the unit
+ * number.
+ *
+ * Returns NULL on error, and fills "ebuf" with an error message.
+ */
+static char *
+split_dname(char *device, int *unitp, char *ebuf)
+{
+       char *cp;
+       char *eos;
+       long unit;
+
+       /*
+        * Look for a number at the end of the device name string.
+        */
+       cp = device + strlen(device) - 1;
+       if (*cp < '0' || *cp > '9') {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
+                   device);
+               return (NULL);
+       }
+
+       /* Digits at end of string are unit number */
+       while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
+               cp--;
+
+       errno = 0;
+       unit = strtol(cp, &eos, 10);
+       if (*eos != '\0') {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
+               return (NULL);
+       }
+       if (errno == ERANGE || unit > INT_MAX) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+                   device);
+               return (NULL);
+       }
+       if (unit < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+                   device);
+               return (NULL);
+       }
+       *unitp = (int)unit;
+       return (cp);
+}
+
+static int
+dl_doattach(int fd, int ppa, char *ebuf)
+{
+       dl_attach_req_t req;
+       bpf_u_int32 buf[MAXDLBUF];
+       int err;
+
+       req.dl_primitive = DL_ATTACH_REQ;
+       req.dl_ppa = ppa;
+       if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0)
+               return (PCAP_ERROR);
+
+       err = dlokack(fd, "attach", (char *)buf, ebuf);
+       if (err < 0)
+               return (err);
+       return (0);
+}
+
+#ifdef DL_HP_RAWDLS
+static int
+dl_dohpuxbind(int fd, char *ebuf)
+{
+       int hpsap;
+       int uerror;
+       bpf_u_int32 buf[MAXDLBUF];
+
+       /*
+        * XXX - we start at 22 because we used to use only 22, but
+        * that was just because that was the value used in some
+        * sample code from HP.  With what value *should* we start?
+        * Does it matter, given that we're enabling SAP promiscuity
+        * on the input FD?
+        */
+       hpsap = 22;
+       for (;;) {
+               if (dlbindreq(fd, hpsap, ebuf) < 0)
+                       return (-1);
+               if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0)
+                       break;
+               /*
+                * For any error other than a UNIX EBUSY, give up.
+                */
+               if (uerror != EBUSY) {
+                       /*
+                        * dlbindack() has already filled in ebuf for
+                        * this error.
+                        */
+                       return (-1);
+               }
+
+               /*
+                * For EBUSY, try the next SAP value; that means that
+                * somebody else is using that SAP.  Clear ebuf so
+                * that application doesn't report the "Device busy"
+                * error as a warning.
+                */
+               *ebuf = '\0';
+               hpsap++;
+               if (hpsap > 100) {
+                       strlcpy(ebuf,
+                           "All SAPs from 22 through 100 are in use",
+                           PCAP_ERRBUF_SIZE);
+                       return (-1);
+               }
+       }
+       return (0);
+}
+#endif
+
+#define STRINGIFY(n)   #n
+
+static int
+dlpromiscon(pcap_t *p, bpf_u_int32 level)
+{
+       dl_promiscon_req_t req;
+       bpf_u_int32 buf[MAXDLBUF];
+       int err;
+
+       req.dl_primitive = DL_PROMISCON_REQ;
+       req.dl_level = level;
+       if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon",
+           p->errbuf) < 0)
+               return (PCAP_ERROR);
+       err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf,
+           p->errbuf);
+       if (err < 0)
+               return (err);
+       return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+#ifdef HAVE_SOLARIS
+       int fd;
+       union {
+               u_int nunits;
+               char pad[516];  /* XXX - must be at least 513; is 516
+                                  in "atmgetunits" */
+       } buf;
+       char baname[2+1+1];
+       u_int i;
+
+       /*
+        * We may have to do special magic to get ATM devices.
+        */
+       if ((fd = open("/dev/ba", O_RDWR)) < 0) {
+               /*
+                * We couldn't open the "ba" device.
+                * For now, just give up; perhaps we should
+                * return an error if the problem is neither
+                * a "that device doesn't exist" error (ENOENT,
+                * ENXIO, etc.) or a "you're not allowed to do
+                * that" error (EPERM, EACCES).
+                */
+               return (0);
+       }
+
+       if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       for (i = 0; i < buf.nunits; i++) {
+               snprintf(baname, sizeof baname, "ba%u", i);
+               if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
+                       return (-1);
+       }
+#endif
+
+       return (0);
+}
+
+static int
+send_request(int fd, char *ptr, int len, char *what, char *ebuf)
+{
+       struct  strbuf  ctl;
+       int     flags;
+
+       ctl.maxlen = 0;
+       ctl.len = len;
+       ctl.buf = ptr;
+
+       flags = 0;
+       if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "send_request: putmsg \"%s\": %s",
+                   what, pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+static int
+recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror)
+{
+       union   DL_primitives   *dlp;
+       struct  strbuf  ctl;
+       int     flags;
+
+       /*
+        * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
+        * making that the only place where EBUSY is treated specially.
+        */
+       if (uerror != NULL)
+               *uerror = 0;
+
+       ctl.maxlen = MAXDLBUF;
+       ctl.len = 0;
+       ctl.buf = bufp;
+
+       flags = 0;
+       if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
+                   what, pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+
+       dlp = MAKE_DL_PRIMITIVES(ctl.buf);
+       switch (dlp->dl_primitive) {
+
+       case DL_INFO_ACK:
+       case DL_BIND_ACK:
+       case DL_OK_ACK:
+#ifdef DL_HP_PPA_ACK
+       case DL_HP_PPA_ACK:
+#endif
+               /* These are OK */
+               break;
+
+       case DL_ERROR_ACK:
+               switch (dlp->error_ack.dl_errno) {
+
+               case DL_SYSERR:
+                       if (uerror != NULL)
+                               *uerror = dlp->error_ack.dl_unix_errno;
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "recv_ack: %s: UNIX error - %s",
+                           what, pcap_strerror(dlp->error_ack.dl_unix_errno));
+                       if (dlp->error_ack.dl_unix_errno == EPERM ||
+                           dlp->error_ack.dl_unix_errno == EACCES)
+                               return (PCAP_ERROR_PERM_DENIED);
+                       break;
+
+               default:
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
+                           what, dlstrerror(dlp->error_ack.dl_errno));
+                       if (dlp->error_ack.dl_errno == DL_BADPPA)
+                               return (PCAP_ERROR_NO_SUCH_DEVICE);
+                       else if (dlp->error_ack.dl_errno == DL_ACCESS)
+                               return (PCAP_ERROR_PERM_DENIED);
+                       break;
+               }
+               return (PCAP_ERROR);
+
+       default:
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "recv_ack: %s: Unexpected primitive ack %s",
+                   what, dlprim(dlp->dl_primitive));
+               return (PCAP_ERROR);
+       }
+
+       if (ctl.len < size) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "recv_ack: %s: Ack too small (%d < %d)",
+                   what, ctl.len, size);
+               return (PCAP_ERROR);
+       }
+       return (ctl.len);
+}
+
+static char *
+dlstrerror(bpf_u_int32 dl_errno)
+{
+       static char errstring[6+2+8+1];
+
+       switch (dl_errno) {
+
+       case DL_ACCESS:
+               return ("Improper permissions for request");
+
+       case DL_BADADDR:
+               return ("DLSAP addr in improper format or invalid");
+
+       case DL_BADCORR:
+               return ("Seq number not from outstand DL_CONN_IND");
+
+       case DL_BADDATA:
+               return ("User data exceeded provider limit");
+
+       case DL_BADPPA:
+#ifdef HAVE_DEV_DLPI
+               /*
+                * With a single "/dev/dlpi" device used for all
+                * DLPI providers, PPAs have nothing to do with
+                * unit numbers.
+                */
+               return ("Specified PPA was invalid");
+#else
+               /*
+                * We have separate devices for separate devices;
+                * the PPA is just the unit number.
+                */
+               return ("Specified PPA (device unit) was invalid");
+#endif
+
+       case DL_BADPRIM:
+               return ("Primitive received not known by provider");
+
+       case DL_BADQOSPARAM:
+               return ("QOS parameters contained invalid values");
+
+       case DL_BADQOSTYPE:
+               return ("QOS structure type is unknown/unsupported");
+
+       case DL_BADSAP:
+               return ("Bad LSAP selector");
+
+       case DL_BADTOKEN:
+               return ("Token used not an active stream");
+
+       case DL_BOUND:
+               return ("Attempted second bind with dl_max_conind");
+
+       case DL_INITFAILED:
+               return ("Physical link initialization failed");
+
+       case DL_NOADDR:
+               return ("Provider couldn't allocate alternate address");
+
+       case DL_NOTINIT:
+               return ("Physical link not initialized");
+
+       case DL_OUTSTATE:
+               return ("Primitive issued in improper state");
+
+       case DL_SYSERR:
+               return ("UNIX system error occurred");
+
+       case DL_UNSUPPORTED:
+               return ("Requested service not supplied by provider");
+
+       case DL_UNDELIVERABLE:
+               return ("Previous data unit could not be delivered");
+
+       case DL_NOTSUPPORTED:
+               return ("Primitive is known but not supported");
+
+       case DL_TOOMANY:
+               return ("Limit exceeded");
+
+       case DL_NOTENAB:
+               return ("Promiscuous mode not enabled");
+
+       case DL_BUSY:
+               return ("Other streams for PPA in post-attached");
+
+       case DL_NOAUTO:
+               return ("Automatic handling XID&TEST not supported");
+
+       case DL_NOXIDAUTO:
+               return ("Automatic handling of XID not supported");
+
+       case DL_NOTESTAUTO:
+               return ("Automatic handling of TEST not supported");
+
+       case DL_XIDAUTO:
+               return ("Automatic handling of XID response");
+
+       case DL_TESTAUTO:
+               return ("Automatic handling of TEST response");
+
+       case DL_PENDING:
+               return ("Pending outstanding connect indications");
+
+       default:
+               sprintf(errstring, "Error %02x", dl_errno);
+               return (errstring);
+       }
+}
+
+static char *
+dlprim(bpf_u_int32 prim)
+{
+       static char primbuf[80];
+
+       switch (prim) {
+
+       case DL_INFO_REQ:
+               return ("DL_INFO_REQ");
+
+       case DL_INFO_ACK:
+               return ("DL_INFO_ACK");
+
+       case DL_ATTACH_REQ:
+               return ("DL_ATTACH_REQ");
+
+       case DL_DETACH_REQ:
+               return ("DL_DETACH_REQ");
+
+       case DL_BIND_REQ:
+               return ("DL_BIND_REQ");
+
+       case DL_BIND_ACK:
+               return ("DL_BIND_ACK");
+
+       case DL_UNBIND_REQ:
+               return ("DL_UNBIND_REQ");
+
+       case DL_OK_ACK:
+               return ("DL_OK_ACK");
+
+       case DL_ERROR_ACK:
+               return ("DL_ERROR_ACK");
+
+       case DL_SUBS_BIND_REQ:
+               return ("DL_SUBS_BIND_REQ");
+
+       case DL_SUBS_BIND_ACK:
+               return ("DL_SUBS_BIND_ACK");
+
+       case DL_UNITDATA_REQ:
+               return ("DL_UNITDATA_REQ");
+
+       case DL_UNITDATA_IND:
+               return ("DL_UNITDATA_IND");
+
+       case DL_UDERROR_IND:
+               return ("DL_UDERROR_IND");
+
+       case DL_UDQOS_REQ:
+               return ("DL_UDQOS_REQ");
+
+       case DL_CONNECT_REQ:
+               return ("DL_CONNECT_REQ");
+
+       case DL_CONNECT_IND:
+               return ("DL_CONNECT_IND");
+
+       case DL_CONNECT_RES:
+               return ("DL_CONNECT_RES");
+
+       case DL_CONNECT_CON:
+               return ("DL_CONNECT_CON");
+
+       case DL_TOKEN_REQ:
+               return ("DL_TOKEN_REQ");
+
+       case DL_TOKEN_ACK:
+               return ("DL_TOKEN_ACK");
+
+       case DL_DISCONNECT_REQ:
+               return ("DL_DISCONNECT_REQ");
+
+       case DL_DISCONNECT_IND:
+               return ("DL_DISCONNECT_IND");
+
+       case DL_RESET_REQ:
+               return ("DL_RESET_REQ");
+
+       case DL_RESET_IND:
+               return ("DL_RESET_IND");
+
+       case DL_RESET_RES:
+               return ("DL_RESET_RES");
+
+       case DL_RESET_CON:
+               return ("DL_RESET_CON");
+
+       default:
+               (void) sprintf(primbuf, "unknown primitive 0x%x", prim);
+               return (primbuf);
+       }
+}
+
+static int
+dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
+{
+
+       dl_bind_req_t   req;
+
+       memset((char *)&req, 0, sizeof(req));
+       req.dl_primitive = DL_BIND_REQ;
+       /* XXX - what if neither of these are defined? */
+#if defined(DL_HP_RAWDLS)
+       req.dl_max_conind = 1;                  /* XXX magic number */
+       req.dl_service_mode = DL_HP_RAWDLS;
+#elif defined(DL_CLDLS)
+       req.dl_service_mode = DL_CLDLS;
+#endif
+       req.dl_sap = sap;
+
+       return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
+}
+
+static int
+dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
+{
+
+       return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
+}
+
+static int
+dlokack(int fd, const char *what, char *bufp, char *ebuf)
+{
+
+       return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));
+}
+
+
+static int
+dlinforeq(int fd, char *ebuf)
+{
+       dl_info_req_t req;
+
+       req.dl_primitive = DL_INFO_REQ;
+
+       return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
+}
+
+static int
+dlinfoack(int fd, char *bufp, char *ebuf)
+{
+
+       return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
+}
+
+#ifdef HAVE_DLPI_PASSIVE
+/*
+ * Enable DLPI passive mode. We do not care if this request fails, as this
+ * indicates the underlying DLPI device does not support link aggregation.
+ */
+static void
+dlpassive(int fd, char *ebuf)
+{
+       dl_passive_req_t req;
+       bpf_u_int32 buf[MAXDLBUF];
+
+       req.dl_primitive = DL_PASSIVE_REQ;
+
+       if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
+           (void) dlokack(fd, "dlpassive", (char *)buf, ebuf);
+}
+#endif
+
+#ifdef DL_HP_RAWDLS
+/*
+ * There's an ack *if* there's an error.
+ */
+static int
+dlrawdatareq(int fd, const u_char *datap, int datalen)
+{
+       struct strbuf ctl, data;
+       long buf[MAXDLBUF];     /* XXX - char? */
+       union DL_primitives *dlp;
+       int dlen;
+
+       dlp = MAKE_DL_PRIMITIVES(buf);
+
+       dlp->dl_primitive = DL_HP_RAWDATA_REQ;
+       dlen = DL_HP_RAWDATA_REQ_SIZE;
+
+       /*
+        * HP's documentation doesn't appear to show us supplying any
+        * address pointed to by the control part of the message.
+        * I think that's what raw mode means - you just send the raw
+        * packet, you don't specify where to send it to, as that's
+        * implied by the destination address.
+        */
+       ctl.maxlen = 0;
+       ctl.len = dlen;
+       ctl.buf = (void *)buf;
+
+       data.maxlen = 0;
+       data.len = datalen;
+       data.buf = (void *)datap;
+
+       return (putmsg(fd, &ctl, &data, 0));
+}
+#endif /* DL_HP_RAWDLS */
+
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+static char *
+get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
+{
+       char *cp;
+       static char buf[32];
+
+       *majorp = 0;
+       *minorp = 0;
+       *microp = 0;
+       if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
+               return ("?");
+       cp = buf;
+       if (!isdigit((unsigned char)*cp))
+               return (buf);
+       *majorp = strtol(cp, &cp, 10);
+       if (*cp++ != '.')
+               return (buf);
+       *minorp =  strtol(cp, &cp, 10);
+       if (*cp++ != '.')
+               return (buf);
+       *microp =  strtol(cp, &cp, 10);
+       return (buf);
+}
+#endif
+
+#ifdef DL_HP_PPA_REQ
+/*
+ * Under HP-UX 10 and HP-UX 11, we can ask for the ppa
+ */
+
+
+/*
+ * Determine ppa number that specifies ifname.
+ *
+ * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member,
+ * the code that's used here is the old code for HP-UX 10.x.
+ *
+ * However, HP-UX 10.20, at least, appears to have such a member
+ * in its "dl_hp_ppa_info_t" structure, so the new code is used.
+ * The new code didn't work on an old 10.20 system on which Rick
+ * Jones of HP tried it, but with later patches installed, it
+ * worked - it appears that the older system had those members but
+ * didn't put anything in them, so, if the search by name fails, we
+ * do the old search.
+ *
+ * Rick suggests that making sure your system is "up on the latest
+ * lancommon/DLPI/driver patches" is probably a good idea; it'd fix
+ * that problem, as well as allowing libpcap to see packets sent
+ * from the system on which the libpcap application is being run.
+ * (On 10.20, in addition to getting the latest patches, you need
+ * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB;
+ * a posting to "comp.sys.hp.hpux" at
+ *
+ *     http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266
+ *
+ * says that, to see the machine's outgoing traffic, you'd need to
+ * apply the right patches to your system, and also set that variable
+ * with:
+
+echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
+
+ * which could be put in, for example, "/sbin/init.d/lan".
+ *
+ * Setting the variable is not necessary on HP-UX 11.x.
+ */
+static int
+get_dlpi_ppa(register int fd, register const char *device, register int unit,
+    register char *ebuf)
+{
+       register dl_hp_ppa_ack_t *ap;
+       register dl_hp_ppa_info_t *ipstart, *ip;
+       register int i;
+       char dname[100];
+       register u_long majdev;
+       struct stat statbuf;
+       dl_hp_ppa_req_t req;
+       char buf[MAXDLBUF];
+       char *ppa_data_buf;
+       dl_hp_ppa_ack_t *dlp;
+       struct strbuf ctl;
+       int flags;
+       int ppa;
+
+       memset((char *)&req, 0, sizeof(req));
+       req.dl_primitive = DL_HP_PPA_REQ;
+
+       memset((char *)buf, 0, sizeof(buf));
+       if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
+               return (PCAP_ERROR);
+
+       ctl.maxlen = DL_HP_PPA_ACK_SIZE;
+       ctl.len = 0;
+       ctl.buf = (char *)buf;
+
+       flags = 0;
+       /*
+        * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal
+        * recv_ack will fail because it set the maxlen to MAXDLBUF (8192)
+        * which is NOT big enough for a DL_HP_PPA_REQ.
+        *
+        * This causes libpcap applications to fail on a system with HP-APA
+        * installed.
+        *
+        * To figure out how big the returned data is, we first call getmsg
+        * to get the small head and peek at the head to get the actual data
+        * length, and  then issue another getmsg to get the actual PPA data.
+        */
+       /* get the head first */
+       if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+
+       dlp = (dl_hp_ppa_ack_t *)ctl.buf;
+       if (dlp->dl_primitive != DL_HP_PPA_ACK) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
+                   (bpf_u_int32)dlp->dl_primitive);
+               return (PCAP_ERROR);
+       }
+
+       if (ctl.len < DL_HP_PPA_ACK_SIZE) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
+                    ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
+               return (PCAP_ERROR);
+       }
+
+       /* allocate buffer */
+       if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
+               return (PCAP_ERROR);
+       }
+       ctl.maxlen = dlp->dl_length;
+       ctl.len = 0;
+       ctl.buf = (char *)ppa_data_buf;
+       /* get the data */
+       if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
+               free(ppa_data_buf);
+               return (PCAP_ERROR);
+       }
+       if (ctl.len < dlp->dl_length) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
+                   ctl.len, (unsigned long)dlp->dl_length);
+               free(ppa_data_buf);
+               return (PCAP_ERROR);
+       }
+
+       ap = (dl_hp_ppa_ack_t *)buf;
+       ipstart = (dl_hp_ppa_info_t *)ppa_data_buf;
+       ip = ipstart;
+
+#ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
+       /*
+        * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1"
+        * member that should, in theory, contain the part of the
+        * name for the device that comes before the unit number,
+        * and should also have a "dl_module_id_2" member that may
+        * contain an alternate name (e.g., I think Ethernet devices
+        * have both "lan", for "lanN", and "snap", for "snapN", with
+        * the former being for Ethernet packets and the latter being
+        * for 802.3/802.2 packets).
+        *
+        * Search for the device that has the specified name and
+        * instance number.
+        */
+       for (i = 0; i < ap->dl_count; i++) {
+               if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 ||
+                    strcmp((const char *)ip->dl_module_id_2, device) == 0) &&
+                   ip->dl_instance_num == unit)
+                       break;
+
+               ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
+       }
+#else
+       /*
+        * We don't have that member, so the search is impossible; make it
+        * look as if the search failed.
+        */
+       i = ap->dl_count;
+#endif
+
+       if (i == ap->dl_count) {
+               /*
+                * Well, we didn't, or can't, find the device by name.
+                *
+                * HP-UX 10.20, whilst it has "dl_module_id_1" and
+                * "dl_module_id_2" fields in the "dl_hp_ppa_info_t",
+                * doesn't seem to fill them in unless the system is
+                * at a reasonably up-to-date patch level.
+                *
+                * Older HP-UX 10.x systems might not have those fields
+                * at all.
+                *
+                * Therefore, we'll search for the entry with the major
+                * device number of a device with the name "/dev/<dev><unit>",
+                * if such a device exists, as the old code did.
+                */
+               snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
+               if (stat(dname, &statbuf) < 0) {
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
+                           dname, pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+               majdev = major(statbuf.st_rdev);
+
+               ip = ipstart;
+
+               for (i = 0; i < ap->dl_count; i++) {
+                       if (ip->dl_mjr_num == majdev &&
+                           ip->dl_instance_num == unit)
+                               break;
+
+                       ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
+               }
+       }
+       if (i == ap->dl_count) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "can't find /dev/dlpi PPA for %s%d", device, unit);
+               return (PCAP_ERROR_NO_SUCH_DEVICE);
+       }
+       if (ip->dl_hdw_state == HDW_DEAD) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "%s%d: hardware state: DOWN\n", device, unit);
+               free(ppa_data_buf);
+               return (PCAP_ERROR);
+       }
+       ppa = ip->dl_ppa;
+       free(ppa_data_buf);
+       return (ppa);
+}
+#endif
+
+#ifdef HAVE_HPUX9
+/*
+ * Under HP-UX 9, there is no good way to determine the ppa.
+ * So punt and read it from /dev/kmem.
+ */
+static struct nlist nl[] = {
+#define NL_IFNET 0
+       { "ifnet" },
+       { "" }
+};
+
+static char path_vmunix[] = "/hp-ux";
+
+/* Determine ppa number that specifies ifname */
+static int
+get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
+    register char *ebuf)
+{
+       register const char *cp;
+       register int kd;
+       void *addr;
+       struct ifnet ifnet;
+       char if_name[sizeof(ifnet.if_name) + 1];
+
+       cp = strrchr(ifname, '/');
+       if (cp != NULL)
+               ifname = cp + 1;
+       if (nlist(path_vmunix, &nl) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
+                   path_vmunix);
+               return (-1);
+       }
+       if (nl[NL_IFNET].n_value == 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "could't find %s kernel symbol",
+                   nl[NL_IFNET].n_name);
+               return (-1);
+       }
+       kd = open("/dev/kmem", O_RDONLY);
+       if (kd < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       if (dlpi_kread(kd, nl[NL_IFNET].n_value,
+           &addr, sizeof(addr), ebuf) < 0) {
+               close(kd);
+               return (-1);
+       }
+       for (; addr != NULL; addr = ifnet.if_next) {
+               if (dlpi_kread(kd, (off_t)addr,
+                   &ifnet, sizeof(ifnet), ebuf) < 0 ||
+                   dlpi_kread(kd, (off_t)ifnet.if_name,
+                   if_name, sizeof(ifnet.if_name), ebuf) < 0) {
+                       (void)close(kd);
+                       return (-1);
+               }
+               if_name[sizeof(ifnet.if_name)] = '\0';
+               if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit)
+                       return (ifnet.if_index);
+       }
+
+       snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+       return (-1);
+}
+
+static int
+dlpi_kread(register int fd, register off_t addr,
+    register void *buf, register u_int len, register char *ebuf)
+{
+       register int cc;
+
+       if (lseek(fd, addr, SEEK_SET) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       cc = read(fd, buf, len);
+       if (cc < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       } else if (cc != len) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
+                   len);
+               return (-1);
+       }
+       return (cc);
+}
+#endif
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->send_fd = -1;        /* it hasn't been opened yet */
+
+       p->activate_op = pcap_activate_dlpi;
+       return (p);
+}
diff --git a/pcap-dos.c b/pcap-dos.c
new file mode 100644 (file)
index 0000000..bcd277f
--- /dev/null
@@ -0,0 +1,1479 @@
+/*
+ *  This file is part of DOS-libpcap
+ *  Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
+ *
+ *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
+ *              network drivers.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.7 2008-04-22 17:16:30 guy Exp $ (LBL)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <float.h>
+#include <fcntl.h>
+#include <io.h>
+
+#if defined(USE_32BIT_DRIVERS)
+  #include "msdos/pm_drvr/pmdrvr.h"
+  #include "msdos/pm_drvr/pci.h"
+  #include "msdos/pm_drvr/bios32.h"
+  #include "msdos/pm_drvr/module.h"
+  #include "msdos/pm_drvr/3c501.h"
+  #include "msdos/pm_drvr/3c503.h"
+  #include "msdos/pm_drvr/3c509.h"
+  #include "msdos/pm_drvr/3c59x.h"
+  #include "msdos/pm_drvr/3c515.h"
+  #include "msdos/pm_drvr/3c90x.h"
+  #include "msdos/pm_drvr/3c575_cb.h"
+  #include "msdos/pm_drvr/ne.h"
+  #include "msdos/pm_drvr/wd.h"
+  #include "msdos/pm_drvr/accton.h"
+  #include "msdos/pm_drvr/cs89x0.h"
+  #include "msdos/pm_drvr/rtl8139.h"
+  #include "msdos/pm_drvr/ne2k-pci.h"
+#endif
+
+#include "pcap.h"
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#ifdef USE_NDIS2
+#include "msdos/ndis2.h"
+#endif
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_ether.h>
+#include <net/if_packe.h>
+#include <tcp.h>
+
+#if defined(USE_32BIT_DRIVERS)
+  #define FLUSHK()       do { _printk_safe = 1; _printk_flush(); } while (0)
+  #define NDIS_NEXT_DEV  &rtl8139_dev
+
+  static char *rx_pool = NULL;
+  static void init_32bit (void);
+
+  static int  pktq_init     (struct rx_ringbuf *q, int size, int num, char *pool);
+  static int  pktq_check    (struct rx_ringbuf *q);
+  static int  pktq_inc_out  (struct rx_ringbuf *q);
+  static int  pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
+  static void pktq_clear    (struct rx_ringbuf *q) LOCKED_FUNC;
+
+  static struct rx_elem *pktq_in_elem  (struct rx_ringbuf *q) LOCKED_FUNC;
+  static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
+
+#else
+  #define FLUSHK()      ((void)0)
+  #define NDIS_NEXT_DEV  NULL
+#endif
+
+/*
+ * Internal variables/functions in Watt-32
+ */
+extern WORD  _pktdevclass;
+extern BOOL  _eth_is_init;
+extern int   _w32_dynamic_host;
+extern int   _watt_do_exit;
+extern int   _watt_is_init;
+extern int   _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
+extern void (*_w32_usr_post_init) (void);
+extern void (*_w32_print_hook)();
+
+extern void dbug_write (const char *);  /* Watt-32 lib, pcdbug.c */
+extern int  pkt_get_mtu (void);
+
+static int ref_count = 0;
+
+static u_long mac_count    = 0;
+static u_long filter_count = 0;
+
+static volatile BOOL exc_occured = 0;
+
+static struct device *handle_to_device [20];
+
+static int  pcap_activate_dos (pcap_t *p);
+static int  pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
+                           u_char *data);
+static void pcap_cleanup_dos (pcap_t *p);
+static int  pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
+static int  pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
+static int  pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
+
+static int  ndis_probe (struct device *dev);
+static int  pkt_probe  (struct device *dev);
+
+static void close_driver (void);
+static int  init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
+static int  first_init (const char *name, char *ebuf, int promisc);
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+                              const u_char *buf);
+
+/*
+ * These are the device we always support
+ */
+static struct device ndis_dev = {
+              "ndis",
+              "NDIS2 LanManager",
+              0,
+              0,0,0,0,0,0,
+              NDIS_NEXT_DEV,  /* NULL or a 32-bit device */
+              ndis_probe
+            };
+
+static struct device pkt_dev = {
+              "pkt",
+              "Packet-Driver",
+              0,
+              0,0,0,0,0,0,
+              &ndis_dev,
+              pkt_probe
+            };
+
+static struct device *get_device (int fd)
+{
+  if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
+     return (NULL);
+  return handle_to_device [fd-1];
+}
+
+pcap_t *pcap_create (const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_dos;
+       return (p);
+}
+
+/*
+ * Open MAC-driver with name 'device_name' for live capture of
+ * network packets.
+ */
+static int pcap_activate_dos (pcap_t *pcap)
+{ 
+  if (pcap->opt.rfmon) {
+    /*
+     * No monitor mode on DOS.
+     */
+    return (PCAP_ERROR_RFMON_NOTSUP);
+  }
+
+  if (pcap->snapshot < ETH_MIN+8)
+      pcap->snapshot = ETH_MIN+8;
+
+  if (pcap->snapshot > ETH_MAX)   /* silently accept and truncate large MTUs */
+      pcap->snapshot = ETH_MAX;
+
+  pcap->linktype          = DLT_EN10MB;  /* !! */
+  pcap->cleanup_op        = pcap_cleanup_dos;
+  pcap->read_op           = pcap_read_dos;
+  pcap->stats_op          = pcap_stats_dos;
+  pcap->inject_op         = pcap_sendpacket_dos;
+  pcap->setfilter_op      = pcap_setfilter_dos;
+  pcap->setdirection_op   = NULL; /* Not implemented.*/
+  pcap->fd                = ++ref_count;
+
+  if (pcap->fd == 1)  /* first time we're called */
+  {
+    if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
+        !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
+    {
+      return (PCAP_ERROR);
+    } 
+    atexit (close_driver);
+  }
+  else if (stricmp(active_dev->name,pcap->opt.source))
+  {
+    snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+              "Cannot use different devices simultaneously "
+              "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
+    return (PCAP_ERROR);
+  }
+  handle_to_device [pcap->fd-1] = active_dev;
+  return (0);
+}
+
+/*
+ * Poll the receiver queue and call the pcap callback-handler
+ * with the packet.
+ */
+static int
+pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
+{
+  struct pcap_pkthdr pcap;
+  struct timeval     now, expiry;
+  BYTE  *rx_buf;
+  int    rx_len = 0;
+
+  if (p->md.timeout > 0)
+  {
+    gettimeofday2 (&now, NULL);
+    expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout;
+    expiry.tv_sec  = now.tv_sec;
+    while (expiry.tv_usec >= 1000000L)
+    {
+      expiry.tv_usec -= 1000000L;
+      expiry.tv_sec++;
+    }
+  }
+
+  while (!exc_occured)
+  {
+    volatile struct device *dev; /* might be reset by sig_handler */
+
+    dev = get_device (p->fd);
+    if (!dev)
+       break;
+
+    PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
+    FLUSHK();
+
+    /* If driver has a zero-copy receive facility, peek at the queue,
+     * filter it, do the callback and release the buffer.
+     */
+    if (dev->peek_rx_buf)
+    {
+      PCAP_ASSERT (dev->release_rx_buf);
+      rx_len = (*dev->peek_rx_buf) (&rx_buf);
+    }
+    else
+    {
+      BYTE buf [ETH_MAX+100]; /* add some margin */
+      rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
+      rx_buf = buf;
+    }
+
+    if (rx_len > 0)  /* got a packet */
+    {
+      mac_count++;
+
+      FLUSHK();
+
+      pcap.caplen = min (rx_len, p->snapshot);
+      pcap.len    = rx_len;
+
+      if (callback &&
+          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
+      {
+        filter_count++;
+
+        /* Fix-me!! Should be time of arrival. Not time of
+         * capture.
+         */
+        gettimeofday2 (&pcap.ts, NULL);
+        (*callback) (data, &pcap, rx_buf);
+      }
+
+      if (dev->release_rx_buf)
+        (*dev->release_rx_buf) (rx_buf);
+
+      if (pcap_pkt_debug > 0)
+      {
+        if (callback == watt32_recv_hook)
+             dbug_write ("pcap_recv_hook\n");
+        else dbug_write ("pcap_read_op\n");
+      }
+      FLUSHK();
+      return (1);
+    }
+
+    /* If not to wait for a packet or pcap_close() called from
+     * e.g. SIGINT handler, exit loop now.
+     */
+    if (p->md.timeout <= 0 || (volatile int)p->fd <= 0)
+       break;
+
+    gettimeofday2 (&now, NULL);
+
+    if (timercmp(&now, &expiry, >))
+       break;
+
+#ifndef DJGPP
+    kbhit();    /* a real CPU hog */
+#endif
+
+    if (p->wait_proc)
+      (*p->wait_proc)();     /* call yield func */
+  }
+
+  if (rx_len < 0)            /* receive error */
+  {
+    p->md.stat.ps_drop++;
+#ifdef USE_32BIT_DRIVERS
+    if (pcap_pkt_debug > 1)
+       printk ("pkt-err %s\n", pktInfo.error);
+#endif
+    return (-1);
+  }
+  return (0);
+}
+
+static int
+pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
+{
+  int rc, num = 0;
+
+  while (num <= cnt || (cnt < 0))
+  {
+    if (p->fd <= 0)
+       return (-1);
+    rc = pcap_read_one (p, callback, data);
+    if (rc > 0)
+       num++;
+    if (rc < 0)
+       break;
+    _w32_os_yield();  /* allow SIGINT generation, yield to Win95/NT */
+  }
+  return (num);
+}
+
+/*
+ * Return network statistics
+ */
+static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
+{
+  struct net_device_stats *stats;
+  struct device           *dev = p ? get_device(p->fd) : NULL;
+
+  if (!dev)
+  {
+    strcpy (p->errbuf, "illegal pcap handle");
+    return (-1);
+  }
+
+  if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
+  {
+    strcpy (p->errbuf, "device statistics not available");
+    return (-1);
+  }
+
+  FLUSHK();
+
+  p->md.stat.ps_recv   = stats->rx_packets;
+  p->md.stat.ps_drop  += stats->rx_missed_errors;
+  p->md.stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
+                         stats->rx_errors;    /* HW errors */
+  if (ps)
+     *ps = p->md.stat;
+
+  return (0);
+}
+
+/*
+ * Return detailed network/device statistics.
+ * May be called after 'dev->close' is called.
+ */
+int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
+{
+  struct device *dev = p ? get_device (p->fd) : NULL;
+
+  if (!dev || !dev->get_stats)
+  {
+    strlcpy (p->errbuf, "detailed device statistics not available",
+             PCAP_ERRBUF_SIZE);
+    return (-1);
+  }
+
+  if (!strnicmp(dev->name,"pkt",3))
+  {
+    strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
+             PCAP_ERRBUF_SIZE);
+    return (-1);
+  }             
+  memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
+  return (0);
+}
+
+/*
+ * Simply store the filter-code for the pcap_read_dos() callback
+ * Some day the filter-code could be handed down to the active
+ * device (pkt_rx1.s or 32-bit device interrupt handler).
+ */
+static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
+{
+  if (!p)
+     return (-1);
+  p->fcode = *fp;
+  return (0);
+}
+
+/*
+ * Return # of packets received in pcap_read_dos()
+ */
+u_long pcap_mac_packets (void)
+{
+  return (mac_count);
+}
+
+/*
+ * Return # of packets passed through filter in pcap_read_dos()
+ */
+u_long pcap_filter_packets (void)
+{
+  return (filter_count);
+}
+
+/*
+ * Close pcap device. Not called for offline captures.
+ */
+static void pcap_cleanup_dos (pcap_t *p)
+{
+  if (p && !exc_occured)
+  {
+    if (pcap_stats(p,NULL) < 0)
+       p->md.stat.ps_drop = 0;
+    if (!get_device(p->fd))
+       return;
+
+    handle_to_device [p->fd-1] = NULL;
+    p->fd = 0;
+    if (ref_count > 0)
+        ref_count--;
+    if (ref_count > 0)
+       return;
+  }
+  close_driver();
+}
+
+/*
+ * Return the name of the 1st network interface,
+ * or NULL if none can be found.
+ */
+char *pcap_lookupdev (char *ebuf)
+{
+  struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+  init_32bit();
+#endif
+
+  for (dev = (struct device*)dev_base; dev; dev = dev->next)
+  {
+    PCAP_ASSERT (dev->probe);
+
+    if ((*dev->probe)(dev))
+    {
+      FLUSHK();
+      probed_dev = (struct device*) dev; /* remember last probed device */
+      return (char*) dev->name;
+    }
+  }
+
+  if (ebuf)
+     strcpy (ebuf, "No driver found");
+  return (NULL);
+}
+
+/*
+ * Gets localnet & netmask from Watt-32.
+ */
+int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
+                    bpf_u_int32 *netmask, char *errbuf)
+{
+  if (!_watt_is_init)
+  {
+    strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
+                    "called first");
+    return (-1);
+  }
+
+  *netmask  = _w32_sin_mask;
+  *localnet = my_ip_addr & *netmask;
+  if (*localnet == 0)
+  {
+    if (IN_CLASSA(*netmask))
+       *localnet = IN_CLASSA_NET;
+    else if (IN_CLASSB(*netmask))
+       *localnet = IN_CLASSB_NET;
+    else if (IN_CLASSC(*netmask))
+       *localnet = IN_CLASSC_NET;
+    else
+    {
+      sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
+      return (-1);
+    }
+  }
+  ARGSUSED (device);
+  return (0);
+}      
+
+/*
+ * Get a list of all interfaces that are present and that we probe okay.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ */
+int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+{
+  struct device     *dev;
+  struct sockaddr_ll sa_ll_1, sa_ll_2;
+  struct sockaddr   *addr, *netmask, *broadaddr, *dstaddr;
+  pcap_if_t *devlist = NULL;
+  int       ret = 0;
+  size_t    addr_size = sizeof(struct sockaddr_ll);
+
+  for (dev = (struct device*)dev_base; dev; dev = dev->next)
+  {
+    PCAP_ASSERT (dev->probe);
+
+    if (!(*dev->probe)(dev))
+       continue;
+
+    PCAP_ASSERT (dev->close);  /* set by probe routine */
+    FLUSHK();
+    (*dev->close) (dev);
+
+    memset (&sa_ll_1, 0, sizeof(sa_ll_1));
+    memset (&sa_ll_2, 0, sizeof(sa_ll_2));
+    sa_ll_1.sll_family = AF_PACKET;
+    sa_ll_2.sll_family = AF_PACKET;
+
+    addr      = (struct sockaddr*) &sa_ll_1;
+    netmask   = (struct sockaddr*) &sa_ll_1;
+    dstaddr   = (struct sockaddr*) &sa_ll_1;
+    broadaddr = (struct sockaddr*) &sa_ll_2;
+    memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
+
+    if (pcap_add_if(&devlist, dev->name, dev->flags,
+                    dev->long_name, errbuf) < 0)
+    {
+      ret = -1;
+      break;
+    }
+    if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
+                           netmask, addr_size, broadaddr, addr_size,
+                           dstaddr, addr_size, errbuf) < 0)
+    {
+      ret = -1;
+      break;
+    }
+  }
+
+  if (devlist && ret < 0)
+  {
+    pcap_freealldevs (devlist);
+    devlist = NULL;
+  }
+  else
+  if (!devlist)
+     strcpy (errbuf, "No drivers found");
+
+  *alldevsp = devlist;
+  return (ret);
+}
+
+/*
+ * pcap_assert() is mainly used for debugging
+ */
+void pcap_assert (const char *what, const char *file, unsigned line)
+{
+  FLUSHK();
+  fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
+           file, line, what);
+  close_driver();
+  _exit (-1);
+}
+
+/*
+ * For pcap_offline_read(): wait and yield between printing packets
+ * to simulate the pace packets where actually recorded.
+ */
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
+{
+  if (p)
+  {
+    p->wait_proc         = yield;
+    p->md.timeout        = wait;
+  }
+}
+
+/*
+ * Initialise a named network device.
+ */
+static struct device *
+open_driver (const char *dev_name, char *ebuf, int promisc)
+{
+  struct device *dev;
+
+  for (dev = (struct device*)dev_base; dev; dev = dev->next)
+  {
+    PCAP_ASSERT (dev->name);
+
+    if (strcmp (dev_name,dev->name))
+       continue;
+
+    if (!probed_dev)   /* user didn't call pcap_lookupdev() first */
+    {
+      PCAP_ASSERT (dev->probe);
+
+      if (!(*dev->probe)(dev))    /* call the xx_probe() function */
+      {
+        sprintf (ebuf, "failed to detect device `%s'", dev_name);
+        return (NULL);
+      }
+      probed_dev = dev;  /* device is probed okay and may be used */
+    }
+    else if (dev != probed_dev)
+    {
+      goto not_probed;
+    }
+
+    FLUSHK();
+
+    /* Select what traffic to receive
+     */
+    if (promisc)
+         dev->flags |=  (IFF_ALLMULTI | IFF_PROMISC);
+    else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
+
+    PCAP_ASSERT (dev->open);
+
+    if (!(*dev->open)(dev))
+    {
+      sprintf (ebuf, "failed to activate device `%s'", dev_name);
+      if (pktInfo.error && !strncmp(dev->name,"pkt",3))
+      {
+        strcat (ebuf, ": ");
+        strcat (ebuf, pktInfo.error);
+      }
+      return (NULL);
+    }
+
+    /* Some devices need this to operate in promiscous mode
+     */
+    if (promisc && dev->set_multicast_list)
+       (*dev->set_multicast_list) (dev);
+
+    active_dev = dev;   /* remember our active device */
+    break;
+  }
+
+  /* 'dev_name' not matched in 'dev_base' list.
+   */
+  if (!dev)
+  {
+    sprintf (ebuf, "device `%s' not supported", dev_name);
+    return (NULL);
+  }
+
+not_probed:
+  if (!probed_dev)
+  {
+    sprintf (ebuf, "device `%s' not probed", dev_name);
+    return (NULL);
+  }
+  return (dev);
+}
+
+/*
+ * Deinitialise MAC driver.
+ * Set receive mode back to default mode.
+ */
+static void close_driver (void)
+{
+  /* !!todo: loop over all 'handle_to_device[]' ? */
+  struct device *dev = active_dev;
+
+  if (dev && dev->close)
+  {
+    (*dev->close) (dev);
+    FLUSHK();
+  }
+
+  active_dev = NULL;
+
+#ifdef USE_32BIT_DRIVERS
+  if (rx_pool)
+  {
+    k_free (rx_pool);
+    rx_pool = NULL;
+  }
+  if (dev)
+     pcibios_exit();
+#endif
+}
+
+
+#ifdef __DJGPP__
+static void setup_signals (void (*handler)(int))
+{
+  signal (SIGSEGV,handler);
+  signal (SIGILL, handler);
+  signal (SIGFPE, handler);
+}
+
+static void exc_handler (int sig)
+{
+#ifdef USE_32BIT_DRIVERS
+  if (active_dev->irq > 0)    /* excludes IRQ 0 */
+  {
+    disable_irq (active_dev->irq);
+    irq_eoi_cmd (active_dev->irq);
+    _printk_safe = 1;
+  }
+#endif
+
+  switch (sig)
+  {
+    case SIGSEGV:
+         fputs ("Catching SIGSEGV.\n", stderr);
+         break;
+    case SIGILL:
+         fputs ("Catching SIGILL.\n", stderr);
+         break;
+    case SIGFPE:
+         _fpreset();
+         fputs ("Catching SIGFPE.\n", stderr);
+         break;
+    default:
+         fprintf (stderr, "Catching signal %d.\n", sig);
+  }
+  exc_occured = 1;
+  pcap_cleanup_dos (NULL);
+}
+#endif  /* __DJGPP__ */
+
+
+/*
+ * Open the pcap device for the first client calling pcap_activate()
+ */
+static int first_init (const char *name, char *ebuf, int promisc)
+{
+  struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+  rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
+  if (!rx_pool)
+  {
+    strcpy (ebuf, "Not enough memory (Rx pool)");
+    return (0);
+  }
+#endif
+
+#ifdef __DJGPP__
+  setup_signals (exc_handler);
+#endif
+
+#ifdef USE_32BIT_DRIVERS
+  init_32bit();
+#endif
+
+  dev = open_driver (name, ebuf, promisc);
+  if (!dev)
+  {
+#ifdef USE_32BIT_DRIVERS
+    k_free (rx_pool);
+    rx_pool = NULL;
+#endif
+
+#ifdef __DJGPP__
+    setup_signals (SIG_DFL);
+#endif
+    return (0);
+  }
+
+#ifdef USE_32BIT_DRIVERS
+  /*
+   * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
+   * set in it's probe handler), initialise near-memory ring-buffer for
+   * the 32-bit device.
+   */
+  if (dev->copy_rx_buf == NULL)
+  {
+    dev->get_rx_buf     = get_rxbuf;
+    dev->peek_rx_buf    = peek_rxbuf;
+    dev->release_rx_buf = release_rxbuf;
+    pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
+  }
+#endif
+  return (1);
+}
+
+#ifdef USE_32BIT_DRIVERS
+static void init_32bit (void)
+{
+  static int init_pci = 0;
+
+  if (!_printk_file)
+     _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
+
+  if (!init_pci)
+     (void)pci_init();             /* init BIOS32+PCI interface */
+  init_pci = 1;
+}
+#endif
+
+
+/*
+ * Hook functions for using Watt-32 together with pcap
+ */
+static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
+static WORD etype;
+static pcap_t pcap_save;
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+                              const u_char *buf)
+{
+  /* Fix me: assumes Ethernet II only */
+  struct ether_header *ep = (struct ether_header*) buf;
+
+  memcpy (rxbuf, buf, pcap->caplen);
+  etype = ep->ether_type;
+  ARGSUSED (dummy);
+}
+
+#if (WATTCP_VER >= 0x0224)
+/*
+ * This function is used by Watt-32 to poll for a packet.
+ * i.e. it's set to bypass _eth_arrived()
+ */
+static void *pcap_recv_hook (WORD *type)
+{
+  int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
+
+  if (len < 0)
+     return (NULL);
+
+  *type = etype;
+  return (void*) &rxbuf;
+}
+
+/*
+ * This function is called by Watt-32 (via _eth_xmit_hook).
+ * If dbug_init() was called, we should trace packets sent.
+ */
+static int pcap_xmit_hook (const void *buf, unsigned len)
+{
+  int rc = 0;
+
+  if (pcap_pkt_debug > 0)
+     dbug_write ("pcap_xmit_hook: ");
+
+  if (active_dev && active_dev->xmit)
+     if ((*active_dev->xmit) (active_dev, buf, len) > 0)
+        rc = len;
+
+  if (pcap_pkt_debug > 0)
+     dbug_write (rc ? "ok\n" : "fail\n");
+  return (rc);
+}
+#endif
+
+static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
+{
+  struct device *dev = p ? get_device(p->fd) : NULL;
+
+  if (!dev || !dev->xmit)
+     return (-1);
+  return (*dev->xmit) (dev, buf, len);
+}
+
+/*
+ * This function is called by Watt-32 in tcp_post_init().
+ * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
+ */
+static void (*prev_post_hook) (void);
+
+static void pcap_init_hook (void)
+{
+  _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
+  _w32__do_mask_req = 0;
+  _w32_dynamic_host = 0;
+  if (prev_post_hook)
+    (*prev_post_hook)();
+}
+
+/*
+ * Supress PRINT message from Watt-32's sock_init()
+ */
+static void null_print (void) {}
+
+/*
+ * To use features of Watt-32 (netdb functions and socket etc.)
+ * we must call sock_init(). But we set various hooks to prevent
+ * using normal PKTDRVR functions in pcpkt.c. This should hopefully
+ * make Watt-32 and pcap co-operate.
+ */
+static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
+{
+  char *env;
+  int   rc, MTU, has_ip_addr;
+  int   using_pktdrv = 1;
+
+  /* If user called sock_init() first, we need to reinit in
+   * order to open debug/trace-file properly
+   */
+  if (_watt_is_init)
+     sock_exit();
+
+  env = getenv ("PCAP_DEBUG");
+  if (env && atoi(env) > 0 &&
+      pcap_pkt_debug < 0)   /* if not already set */
+  {
+    dbug_init();
+    pcap_pkt_debug = atoi (env);
+  }
+
+  _watt_do_exit      = 0;    /* prevent sock_init() calling exit() */
+  prev_post_hook     = _w32_usr_post_init;
+  _w32_usr_post_init = pcap_init_hook;
+  _w32_print_hook    = null_print;
+
+  if (dev_name && strncmp(dev_name,"pkt",3))
+     using_pktdrv = FALSE;
+
+  rc = sock_init();
+  has_ip_addr = (rc != 8);  /* IP-address assignment failed */
+
+  /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
+   * just pretend Watt-32 is initialised okay.
+   *
+   * !! fix-me: The Watt-32 config isn't done if no pktdrvr
+   *            was found. In that case my_ip_addr + sin_mask
+   *            have default values. Should be taken from another
+   *            ini-file/environment in any case (ref. tcpdump.ini)
+   */
+  _watt_is_init = 1;  
+
+  if (!using_pktdrv || !has_ip_addr)  /* for now .... */
+  {
+    static const char myip[] = "192.168.0.1";
+    static const char mask[] = "255.255.255.0";
+
+    printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
+    my_ip_addr    = aton (myip);
+    _w32_sin_mask = aton (mask);
+  }
+  else if (rc && using_pktdrv)
+  {
+    sprintf (err_buf, "sock_init() failed, code %d", rc);
+    return (0);
+  }
+
+  /* Set recv-hook for peeking in _eth_arrived().
+   */
+#if (WATTCP_VER >= 0x0224)
+  _eth_recv_hook = pcap_recv_hook;
+  _eth_xmit_hook = pcap_xmit_hook;
+#endif
+
+  /* Free the pkt-drvr handle allocated in pkt_init().
+   * The above hooks should thus use the handle reopened in open_driver()
+   */
+  if (using_pktdrv)
+  {
+    _eth_release();
+/*  _eth_is_init = 1; */  /* hack to get Rx/Tx-hooks in Watt-32 working */
+  }
+
+  memcpy (&pcap_save, pcap, sizeof(pcap_save));
+  MTU = pkt_get_mtu();
+  pcap_save.fcode.bf_insns = NULL;
+  pcap_save.linktype       = _eth_get_hwtype (NULL, NULL);
+  pcap_save.snapshot       = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
+
+#if 1
+  /* prevent use of resolve() and resolve_ip()
+   */
+  last_nameserver = 0;
+#endif
+  return (1);
+}
+
+int EISA_bus = 0;  /* Where is natural place for this? */
+
+/*
+ * Application config hooks to set various driver parameters.
+ */
+
+static const struct config_table debug_tab[] = {
+            { "PKT.DEBUG",       ARG_ATOI,   &pcap_pkt_debug    },
+            { "PKT.VECTOR",      ARG_ATOX_W, NULL               },
+            { "NDIS.DEBUG",      ARG_ATOI,   NULL               },
+#ifdef USE_32BIT_DRIVERS
+            { "3C503.DEBUG",     ARG_ATOI,   &ei_debug          },
+            { "3C503.IO_BASE",   ARG_ATOX_W, &el2_dev.base_addr },
+            { "3C503.MEMORY",    ARG_ATOX_W, &el2_dev.mem_start },
+            { "3C503.IRQ",       ARG_ATOI,   &el2_dev.irq       },
+            { "3C505.DEBUG",     ARG_ATOI,   NULL               },
+            { "3C505.BASE",      ARG_ATOX_W, NULL               },
+            { "3C507.DEBUG",     ARG_ATOI,   NULL               },
+            { "3C509.DEBUG",     ARG_ATOI,   &el3_debug         },
+            { "3C509.ILOOP",     ARG_ATOI,   &el3_max_loop      },
+            { "3C529.DEBUG",     ARG_ATOI,   NULL               },
+            { "3C575.DEBUG",     ARG_ATOI,   &debug_3c575       },
+            { "3C59X.DEBUG",     ARG_ATOI,   &vortex_debug      },
+            { "3C59X.IFACE0",    ARG_ATOI,   &vortex_options[0] },
+            { "3C59X.IFACE1",    ARG_ATOI,   &vortex_options[1] },
+            { "3C59X.IFACE2",    ARG_ATOI,   &vortex_options[2] },
+            { "3C59X.IFACE3",    ARG_ATOI,   &vortex_options[3] },
+            { "3C90X.DEBUG",     ARG_ATOX_W, &tc90xbc_debug     },
+            { "ACCT.DEBUG",      ARG_ATOI,   &ethpk_debug       },
+            { "CS89.DEBUG",      ARG_ATOI,   &cs89_debug        },
+            { "RTL8139.DEBUG",   ARG_ATOI,   &rtl8139_debug     },
+        /*  { "RTL8139.FDUPLEX", ARG_ATOI,   &rtl8139_options   }, */
+            { "SMC.DEBUG",       ARG_ATOI,   &ei_debug          },
+        /*  { "E100.DEBUG",      ARG_ATOI,   &e100_debug        }, */
+            { "PCI.DEBUG",       ARG_ATOI,   &pci_debug         },
+            { "BIOS32.DEBUG",    ARG_ATOI,   &bios32_debug      },
+            { "IRQ.DEBUG",       ARG_ATOI,   &irq_debug         },
+            { "TIMER.IRQ",       ARG_ATOI,   &timer_irq         },
+#endif
+            { NULL }
+          };
+
+/*
+ * pcap_config_hook() is an extension to application's config
+ * handling. Uses Watt-32's config-table function.
+ */
+int pcap_config_hook (const char *name, const char *value)
+{
+  return parse_config_table (debug_tab, NULL, name, value);
+}
+
+/*
+ * Linked list of supported devices
+ */
+struct device       *active_dev = NULL;      /* the device we have opened */
+struct device       *probed_dev = NULL;      /* the device we have probed */
+const struct device *dev_base   = &pkt_dev;  /* list of network devices */
+
+/*
+ * PKTDRVR device functions
+ */
+int pcap_pkt_debug = -1;
+
+static void pkt_close (struct device *dev)
+{
+  BOOL okay = PktExitDriver();
+
+  if (pcap_pkt_debug > 1)
+     fprintf (stderr, "pkt_close(): %d\n", okay);
+
+  if (dev->priv)
+     free (dev->priv);
+  dev->priv = NULL;
+}
+
+static int pkt_open (struct device *dev)
+{
+  PKT_RX_MODE mode;
+
+  if (dev->flags & IFF_PROMISC)
+       mode = PDRX_ALL_PACKETS;
+  else mode = PDRX_BROADCAST;
+
+  if (!PktInitDriver(mode))
+     return (0);
+  PktResetStatistics (pktInfo.handle);
+  PktQueueBusy (FALSE);
+  return (1);
+}
+
+static int pkt_xmit (struct device *dev, const void *buf, int len)
+{
+  struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+  if (pcap_pkt_debug > 0)
+     dbug_write ("pcap_xmit\n");
+
+  if (!PktTransmit(buf,len))
+  {
+    stats->tx_errors++;
+    return (0);
+  }
+  return (len);
+}
+
+static void *pkt_stats (struct device *dev)
+{
+  struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+  if (!stats || !PktSessStatistics(pktInfo.handle))
+     return (NULL);
+
+  stats->rx_packets       = pktStat.inPackets;
+  stats->rx_errors        = pktStat.lost;
+  stats->rx_missed_errors = PktRxDropped();
+  return (stats);
+}
+
+static int pkt_probe (struct device *dev)
+{
+  if (!PktSearchDriver())
+     return (0);
+
+  dev->open           = pkt_open;
+  dev->xmit           = pkt_xmit;
+  dev->close          = pkt_close;
+  dev->get_stats      = pkt_stats;
+  dev->copy_rx_buf    = PktReceive;  /* farmem peek and copy routine */
+  dev->get_rx_buf     = NULL;
+  dev->peek_rx_buf    = NULL;
+  dev->release_rx_buf = NULL;
+  dev->priv           = calloc (sizeof(struct net_device_stats), 1);
+  if (!dev->priv)
+     return (0);
+  return (1);
+}
+
+/*
+ * NDIS device functions
+ */
+static void ndis_close (struct device *dev)
+{
+#ifdef USE_NDIS2
+  NdisShutdown();
+#endif
+  ARGSUSED (dev);
+}
+
+static int ndis_open (struct device *dev)
+{
+  int promis = (dev->flags & IFF_PROMISC);
+
+#ifdef USE_NDIS2
+  if (!NdisInit(promis))
+     return (0);
+  return (1);
+#else
+  ARGSUSED (promis);
+  return (0);
+#endif
+}
+
+static void *ndis_stats (struct device *dev)
+{
+  static struct net_device_stats stats;
+
+  /* to-do */
+  ARGSUSED (dev);
+  return (&stats);
+}
+
+static int ndis_probe (struct device *dev)
+{
+#ifdef USE_NDIS2
+  if (!NdisOpen())
+     return (0);
+#endif
+
+  dev->open           = ndis_open;
+  dev->xmit           = NULL;
+  dev->close          = ndis_close;
+  dev->get_stats      = ndis_stats;
+  dev->copy_rx_buf    = NULL;       /* to-do */
+  dev->get_rx_buf     = NULL;       /* upcall is from rmode driver */
+  dev->peek_rx_buf    = NULL;
+  dev->release_rx_buf = NULL;
+  return (0);
+}
+
+/*
+ * Search & probe for supported 32-bit (pmode) pcap devices
+ */
+#if defined(USE_32BIT_DRIVERS)
+
+struct device el2_dev LOCKED_VAR = {
+              "3c503",
+              "EtherLink II",
+              0,
+              0,0,0,0,0,0,
+              NULL,
+              el2_probe
+            };
+
+struct device el3_dev LOCKED_VAR = {
+              "3c509",
+              "EtherLink III",
+              0,
+              0,0,0,0,0,0,
+              &el2_dev,
+              el3_probe
+            };
+
+struct device tc515_dev LOCKED_VAR = {
+              "3c515",
+              "EtherLink PCI",
+              0,
+              0,0,0,0,0,0,
+              &el3_dev,
+              tc515_probe
+            };
+
+struct device tc59_dev LOCKED_VAR = {
+              "3c59x",
+              "EtherLink PCI",
+              0,
+              0,0,0,0,0,0,
+              &tc515_dev,
+              tc59x_probe
+            };
+
+struct device tc90xbc_dev LOCKED_VAR = {
+              "3c90x",
+              "EtherLink 90X",
+              0,
+              0,0,0,0,0,0,
+              &tc59_dev,
+              tc90xbc_probe
+            };
+
+struct device wd_dev LOCKED_VAR = {
+              "wd",
+              "Westen Digital",
+              0,
+              0,0,0,0,0,0,
+              &tc90xbc_dev,
+              wd_probe
+            };
+
+struct device ne_dev LOCKED_VAR = {
+              "ne",
+              "NEx000",
+              0,
+              0,0,0,0,0,0,
+              &wd_dev,
+              ne_probe
+            };
+
+struct device acct_dev LOCKED_VAR = {
+              "acct",
+              "Accton EtherPocket",
+              0,
+              0,0,0,0,0,0,
+              &ne_dev,
+              ethpk_probe
+            };
+
+struct device cs89_dev LOCKED_VAR = {
+              "cs89",
+              "Crystal Semiconductor",
+              0,
+              0,0,0,0,0,0,
+              &acct_dev,
+              cs89x0_probe
+            };
+
+struct device rtl8139_dev LOCKED_VAR = {
+              "rtl8139",
+              "RealTek PCI",
+              0,
+              0,0,0,0,0,0,
+              &cs89_dev,
+              rtl8139_probe     /* dev->probe routine */
+            };            
+
+/*
+ * Dequeue routine is called by polling.
+ * NOTE: the queue-element is not copied, only a pointer is
+ * returned at '*buf'
+ */
+int peek_rxbuf (BYTE **buf)
+{
+  struct rx_elem *tail, *head;
+
+  PCAP_ASSERT (pktq_check (&active_dev->queue));
+
+  DISABLE();
+  tail = pktq_out_elem (&active_dev->queue);
+  head = pktq_in_elem (&active_dev->queue);
+  ENABLE();
+
+  if (head != tail)
+  {
+    PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
+
+    *buf = &tail->data[0];
+    return (tail->size);
+  }
+  *buf = NULL;
+  return (0);
+}
+
+/*
+ * Release buffer we peeked at above.
+ */
+int release_rxbuf (BYTE *buf)
+{
+#ifndef NDEBUG
+  struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
+
+  PCAP_ASSERT (&tail->data[0] == buf);
+#else
+  ARGSUSED (buf);
+#endif
+  pktq_inc_out (&active_dev->queue);
+  return (1);
+}
+
+/*
+ * get_rxbuf() routine (in locked code) is called from IRQ handler
+ * to request a buffer. Interrupts are disabled and we have a 32kB stack.
+ */
+BYTE *get_rxbuf (int len)
+{
+  int idx;
+
+  if (len < ETH_MIN || len > ETH_MAX)
+     return (NULL);
+
+  idx = pktq_in_index (&active_dev->queue);
+
+#ifdef DEBUG
+  {
+    static int fan_idx LOCKED_VAR = 0;
+    writew ("-\\|/"[fan_idx++] | (15 << 8),      /* white on black colour */
+            0xB8000 + 2*79);  /* upper-right corner, 80-col colour screen */
+    fan_idx &= 3;
+  }
+/* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
+#endif
+
+  if (idx != active_dev->queue.out_index)
+  {
+    struct rx_elem *head = pktq_in_elem (&active_dev->queue);
+
+    head->size = len;
+    active_dev->queue.in_index = idx;
+    return (&head->data[0]);
+  }
+
+  /* !!to-do: drop 25% of the oldest element
+   */
+  pktq_clear (&active_dev->queue);
+  return (NULL);
+}
+
+/*
+ *  Simple ring-buffer queue handler for reception of packets
+ *  from network driver.
+ */
+#define PKTQ_MARKER  0xDEADBEEF
+
+static int pktq_check (struct rx_ringbuf *q)
+{
+#ifndef NDEBUG
+  int   i;
+  char *buf;
+#endif
+
+  if (!q || !q->num_elem || !q->buf_start)
+     return (0);
+
+#ifndef NDEBUG
+  buf = q->buf_start;
+
+  for (i = 0; i < q->num_elem; i++)
+  {
+    buf += q->elem_size;
+    if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
+       return (0);
+  }
+#endif
+  return (1);
+}
+
+static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
+{
+  int i;
+
+  q->elem_size = size;
+  q->num_elem  = num;
+  q->buf_start = pool;
+  q->in_index  = 0;
+  q->out_index = 0;
+
+  PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
+  PCAP_ASSERT (num);
+  PCAP_ASSERT (pool);
+
+  for (i = 0; i < num; i++)
+  {
+#if 0
+    struct rx_elem *elem = (struct rx_elem*) pool;
+
+    /* assert dword aligned elements
+     */
+    PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
+#endif
+    pool += size;
+    *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
+  }
+  return (1);
+}
+
+/*
+ * Increment the queue 'out_index' (tail).
+ * Check for wraps.
+ */
+static int pktq_inc_out (struct rx_ringbuf *q)
+{
+  q->out_index++;
+  if (q->out_index >= q->num_elem)
+      q->out_index = 0;
+  return (q->out_index);
+}
+
+/*
+ * Return the queue's next 'in_index' (head).
+ * Check for wraps.
+ */
+static int pktq_in_index (struct rx_ringbuf *q)
+{
+  volatile int index = q->in_index + 1;
+
+  if (index >= q->num_elem)
+      index = 0;
+  return (index);
+}
+
+/*
+ * Return the queue's head-buffer.
+ */
+static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
+{
+  return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
+}
+
+/*
+ * Return the queue's tail-buffer.
+ */
+static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
+{
+  return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
+}
+
+/*
+ * Clear the queue ring-buffer by setting head=tail.
+ */
+static void pktq_clear (struct rx_ringbuf *q)
+{
+  q->in_index = q->out_index;
+}
+
+/*
+ * Symbols that must be linkable for "gcc -O0"
+ */
+#undef __IOPORT_H
+#undef __DMA_H
+
+#define extern
+#define __inline__
+
+#include "msdos/pm_drvr/ioport.h"
+#include "msdos/pm_drvr/dma.h"
+
+#endif /* USE_32BIT_DRIVERS */
+
diff --git a/pcap-dos.h b/pcap-dos.h
new file mode 100644 (file)
index 0000000..f474437
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Internal details for libpcap on DOS.
+ * 32-bit targets: djgpp, Pharlap or DOS4GW.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.h,v 1.1 2004-12-18 08:52:10 guy Exp $ (LBL)
+ */
+
+#ifndef __PCAP_DOS_H
+#define __PCAP_DOS_H
+
+#ifdef __DJGPP__
+#include <pc.h>    /* simple non-conio kbhit */
+#else
+#include <conio.h>
+#endif
+
+typedef int            BOOL;
+typedef unsigned char  BYTE;
+typedef unsigned short WORD;
+typedef unsigned long  DWORD;
+typedef BYTE           ETHER[6];
+
+#define ETH_ALEN       sizeof(ETHER)   /* Ether address length */
+#define ETH_HLEN       (2*ETH_ALEN+2)  /* Ether header length  */
+#define ETH_MTU        1500
+#define ETH_MIN        60
+#define ETH_MAX        (ETH_MTU+ETH_HLEN)
+
+#ifndef TRUE
+  #define TRUE   1
+  #define FALSE  0
+#endif
+
+#define PHARLAP  1
+#define DJGPP    2
+#define DOS4GW   4
+
+#ifdef __DJGPP__
+  #undef  DOSX
+  #define DOSX DJGPP
+#endif
+
+#ifdef __WATCOMC__
+  #undef  DOSX
+  #define DOSX DOS4GW
+#endif
+
+#ifdef __HIGHC__
+  #include <pharlap.h>
+  #undef  DOSX
+  #define DOSX PHARLAP
+  #define inline
+#else
+  typedef unsigned int UINT;
+#endif
+
+
+#if defined(__GNUC__) || defined(__HIGHC__)
+  typedef unsigned long long  uint64;
+  typedef unsigned long long  QWORD;
+#endif
+
+#if defined(__WATCOMC__)
+  typedef unsigned __int64  uint64;
+  typedef unsigned __int64  QWORD;
+#endif
+
+#define ARGSUSED(x)  (void) x
+
+#if defined (__SMALL__) || defined(__LARGE__)
+  #define DOSX 0
+
+#elif !defined(DOSX)
+  #error DOSX not defined; 1 = PharLap, 2 = djgpp, 4 = DOS4GW
+#endif
+
+#ifdef __HIGHC__
+#define min(a,b) _min(a,b)
+#define max(a,b) _max(a,b)
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+#if !defined(_U_) && defined(__GNUC__)
+#define _U_  __attribute__((unused))
+#endif
+
+#ifndef _U_
+#define _U_
+#endif
+
+#if defined(USE_32BIT_DRIVERS)
+  #include "msdos/pm_drvr/lock.h"
+
+  #ifndef RECEIVE_QUEUE_SIZE
+  #define RECEIVE_QUEUE_SIZE  60
+  #endif
+
+  #ifndef RECEIVE_BUF_SIZE
+  #define RECEIVE_BUF_SIZE   (ETH_MAX+20)
+  #endif
+
+  extern struct device el2_dev     LOCKED_VAR;  /* 3Com EtherLink II */
+  extern struct device el3_dev     LOCKED_VAR;  /*      EtherLink III */
+  extern struct device tc59_dev    LOCKED_VAR;  /* 3Com Vortex Card (?) */
+  extern struct device tc515_dev   LOCKED_VAR;
+  extern struct device tc90x_dev   LOCKED_VAR;
+  extern struct device tc90bcx_dev LOCKED_VAR;
+  extern struct device wd_dev      LOCKED_VAR;
+  extern struct device ne_dev      LOCKED_VAR;
+  extern struct device acct_dev    LOCKED_VAR;
+  extern struct device cs89_dev    LOCKED_VAR;
+  extern struct device rtl8139_dev LOCKED_VAR;
+
+  struct rx_ringbuf {
+         volatile int in_index;   /* queue index head */
+         int          out_index;  /* queue index tail */
+         int          elem_size;  /* size of each element */
+         int          num_elem;   /* number of elements */
+         char        *buf_start;  /* start of buffer pool */
+       };
+
+  struct rx_elem {
+         DWORD size;              /* size copied to this element */
+         BYTE  data[ETH_MAX+10];  /* add some margin. data[0] should be */
+       };                         /* dword aligned */
+
+  extern BYTE *get_rxbuf     (int len) LOCKED_FUNC;
+  extern int   peek_rxbuf    (BYTE **buf);
+  extern int   release_rxbuf (BYTE  *buf);
+
+#else
+  #define LOCKED_VAR
+  #define LOCKED_FUNC
+
+  struct device {
+         const char *name;
+         const char *long_name;
+         DWORD  base_addr;      /* device I/O address       */
+         int    irq;            /* device IRQ number        */
+         int    dma;            /* DMA channel              */
+         DWORD  mem_start;      /* shared mem start         */
+         DWORD  mem_end;        /* shared mem end           */
+         DWORD  rmem_start;     /* shmem "recv" start       */
+         DWORD  rmem_end;       /* shared "recv" end        */
+
+         struct device *next;   /* next device in list      */
+
+         /* interface service routines */
+         int   (*probe)(struct device *dev);
+         int   (*open) (struct device *dev);
+         void  (*close)(struct device *dev);
+         int   (*xmit) (struct device *dev, const void *buf, int len);
+         void *(*get_stats)(struct device *dev);
+         void  (*set_multicast_list)(struct device *dev);
+
+         /* driver-to-pcap receive buffer routines */
+         int   (*copy_rx_buf) (BYTE *buf, int max); /* rx-copy (pktdrvr only) */
+         BYTE *(*get_rx_buf) (int len);             /* rx-buf fetch/enqueue */
+         int   (*peek_rx_buf) (BYTE **buf);         /* rx-non-copy at queue */
+         int   (*release_rx_buf) (BYTE *buf);       /* release after peek */
+
+         WORD   flags;          /* Low-level status flags. */
+         void  *priv;           /* private data */
+       };
+
+  /*
+   * Network device statistics
+   */
+  typedef struct net_device_stats {
+          DWORD  rx_packets;            /* total packets received       */
+          DWORD  tx_packets;            /* total packets transmitted    */
+          DWORD  rx_bytes;              /* total bytes received         */
+          DWORD  tx_bytes;              /* total bytes transmitted      */
+          DWORD  rx_errors;             /* bad packets received         */
+          DWORD  tx_errors;             /* packet transmit problems     */
+          DWORD  rx_dropped;            /* no space in Rx buffers       */
+          DWORD  tx_dropped;            /* no space available for Tx    */
+          DWORD  multicast;             /* multicast packets received   */
+
+          /* detailed rx_errors: */
+          DWORD  rx_length_errors;
+          DWORD  rx_over_errors;        /* recv'r overrun error         */
+          DWORD  rx_osize_errors;       /* recv'r over-size error       */
+          DWORD  rx_crc_errors;         /* recv'd pkt with crc error    */
+          DWORD  rx_frame_errors;       /* recv'd frame alignment error */
+          DWORD  rx_fifo_errors;        /* recv'r fifo overrun          */
+          DWORD  rx_missed_errors;      /* recv'r missed packet         */
+
+          /* detailed tx_errors */
+          DWORD  tx_aborted_errors;
+          DWORD  tx_carrier_errors;
+          DWORD  tx_fifo_errors;
+          DWORD  tx_heartbeat_errors;
+          DWORD  tx_window_errors;
+          DWORD  tx_collisions;
+          DWORD  tx_jabbers;
+        } NET_STATS;
+#endif
+
+extern struct device       *active_dev  LOCKED_VAR;
+extern const struct device *dev_base    LOCKED_VAR;
+extern struct device       *probed_dev;
+
+extern int pcap_pkt_debug;
+
+extern void _w32_os_yield (void); /* Watt-32's misc.c */
+
+#ifdef NDEBUG
+  #define PCAP_ASSERT(x) ((void)0)
+
+#else
+  void pcap_assert (const char *what, const char *file, unsigned line);  
+
+  #define PCAP_ASSERT(x) do { \
+                           if (!(x)) \
+                              pcap_assert (#x, __FILE__, __LINE__); \
+                         } while (0)
+#endif
+
+#endif  /* __PCAP_DOS_H */
diff --git a/pcap-enet.c b/pcap-enet.c
new file mode 100644 (file)
index 0000000..5ad921c
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Stanford Enetfilter subroutines for tcpdump
+ *
+ * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c
+ * subroutines.
+ *
+ * Rayan Zachariassen, CA*Net
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.9 2006-10-04 18:09:22 guy Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <pcap/bpf.h>
+#include <net/enet.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "interface.h"
+
+struct packet_header {
+#ifdef IBMRTPC
+       struct LengthWords      length;
+       struct tap_header       tap;
+#endif /* IBMRTPC */
+       u_char                  packet[8]
+};
+
+extern int errno;
+
+#define BUFSPACE (4*1024)
+
+/* Forwards */
+static void efReadError(int, char *);
+
+void
+readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit)
+{
+#ifdef IBMRTPC
+       register struct packet_header *ph;
+       register u_char *bp;
+       register int inc;
+#else  /* !IBMRTPC */
+       static struct timeval tv = { 0 };
+#endif /* IBMRTPC */
+       register int cc, caplen;
+       register struct bpf_insn *fcode = fp->bf_insns;
+       union {
+               struct packet_header hdr;
+               u_char  p[BUFSPACE];
+               u_short s;
+       } buf;
+
+       while (1) {
+               if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0)
+                       efReadError(if_fd, "reader");
+
+#ifdef IBMRTPC
+               /*
+                * Loop through each packet.
+                */
+               bp = buf.p;
+               while (cc > 0) {
+                       ph = (struct packet_header *)bp;
+                       caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
+.th_wirelen ;
+                       if (bpf_filter(fcode, (char *)ph->packet,
+                                               ph->tap.th_wirelen, caplen)) {
+                               if (cnt >= 0 && --cnt < 0)
+                                       goto out;
+                               (*printit)((char *)ph->packet,
+                                       (struct timeval *)ph->tap.th_timestamp,
+                                       ph->tap.th_wirelen, caplen);
+                       }
+                       inc = ph->length.PacketOffset;
+                       cc -= inc;
+                       bp += inc;
+               }
+#else  /* !IBMRTPC */
+               caplen = cc > snaplen ? snaplen : cc ;
+               if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
+                       if (cnt >= 0 && --cnt < 0)
+                               goto out;
+                       (*printit)(buf.hdr.packet, &tv, cc, caplen);
+               }
+#endif /* IBMRTPC */
+       }
+ out:
+       wrapup(if_fd);
+}
+
+/* Call ONLY if read() has returned an error on packet filter */
+static void
+efReadError(int fid, char *msg)
+{
+       if (errno == EINVAL) {  /* read MAXINT bytes already! */
+               if (lseek(fid, 0, 0) < 0) {
+                       perror("tcpdump: efReadError/lseek");
+                       exit(-1);
+               }
+               else
+                       return;
+       }
+       else {
+               (void) fprintf(stderr, "tcpdump: ");
+               perror(msg);
+               exit(-1);
+       }
+}
+
+void
+wrapup(int fd)
+{
+#ifdef IBMRTPC
+       struct enstats es;
+
+       if (ioctl(fd, EIOSTATS, &es) == -1) {
+               perror("tcpdump: enet ioctl EIOSTATS error");
+               exit(-1);
+       }
+
+       fprintf(stderr, "%d packets queued", es.enStat_Rcnt);
+       if (es.enStat_Rdrops > 0)
+               fprintf(stderr, ", %d dropped", es.enStat_Rdrops);
+       if (es.enStat_Reads > 0)
+               fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads,
+                               es.enStat_Reads > 1 ? "reads" : "read");
+       if (es.enStat_MaxRead > 1)
+               fprintf(stderr, ", %d packets in largest read",
+                       es.enStat_MaxRead);
+       putc('\n', stderr);
+#endif /* IBMRTPC */
+       close(fd);
+}
+
+int
+initdevice(char *device, int pflag, int *linktype)
+{
+       struct eniocb ctl;
+       struct enfilter filter;
+       u_int maxwaiting;
+       int if_fd;
+
+#ifdef IBMRTPC
+       GETENETDEVICE(0, O_RDONLY, &if_fd);
+#else  /* !IBMRTPC */
+       if_fd = open("/dev/enet", O_RDONLY, 0);
+#endif /* IBMRTPC */
+
+       if (if_fd == -1) {
+               perror("tcpdump: enet open error");
+               error(
+"your system may not be properly configured; see \"man enet(4)\"");
+               exit(-1);
+       }
+
+       /*  Get operating parameters. */
+
+       if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) {
+               perror("tcpdump: enet ioctl EIOCGETP error");
+               exit(-1);
+       }
+
+       /*  Set operating parameters. */
+
+#ifdef IBMRTPC
+       ctl.en_rtout = 1 * ctl.en_hz;
+       ctl.en_tr_etherhead = 1;
+       ctl.en_tap_network = 1;
+       ctl.en_multi_packet = 1;
+       ctl.en_maxlen = BUFSPACE;
+#else  /* !IBMRTPC */
+       ctl.en_rtout = 64;      /* randomly picked value for HZ */
+#endif /* IBMRTPC */
+       if (ioctl(if_fd, EIOCSETP, &ctl) == -1) {
+               perror("tcpdump: enet ioctl EIOCSETP error");
+               exit(-1);
+       }
+
+       /*  Flush the receive queue, since we've changed
+           the operating parameters and we otherwise might
+           receive data without headers. */
+
+       if (ioctl(if_fd, EIOCFLUSH) == -1) {
+               perror("tcpdump: enet ioctl EIOCFLUSH error");
+               exit(-1);
+       }
+
+       /*  Set the receive queue depth to its maximum. */
+
+       maxwaiting = ctl.en_maxwaiting;
+       if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) {
+               perror("tcpdump: enet ioctl EIOCSETW error");
+               exit(-1);
+       }
+
+#ifdef IBMRTPC
+       /*  Clear statistics. */
+
+       if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) {
+               perror("tcpdump: enet ioctl EIOCLRSTAT error");
+               exit(-1);
+       }
+#endif /* IBMRTPC */
+
+       /*  Set the filter (accept all packets). */
+
+       filter.enf_Priority = 3;
+       filter.enf_FilterLen = 0;
+       if (ioctl(if_fd, EIOCSETF, &filter) == -1) {
+               perror("tcpdump: enet ioctl EIOCSETF error");
+               exit(-1);
+       }
+       /*
+        * "enetfilter" supports only ethernets.
+        */
+       *linktype = DLT_EN10MB;
+
+       return(if_fd);
+}
diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in
new file mode 100644 (file)
index 0000000..d7b4b0a
--- /dev/null
@@ -0,0 +1,962 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1 2008-10-21 07:33:01 guy Exp $ (LBL)
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "6 January 2008"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop() ,
+.BR pcap_dispatch() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+For some link layers, such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types, the
+.B inbound
+and
+.B outbound
+qualifiers can be used to specify a desired direction.
+.IP \fIproto\fP
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.''  FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers.  For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a number (see
+.IR ethers (3N)
+for numeric format).
+.IP "\fBether src \fIehost\fP
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, so this can be somewhat
+slow.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP  "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
+(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan protocol arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols.  The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code.  The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonomous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonomous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged.  Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4)),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan ra \fIehost\fR"
+True if the IEEE 802.11 RA is
+.IR ehost .
+The RA field is used in all frames except for management frames.
+.IP "\fBwlan ta \fIehost\fR"
+True if the IEEE 802.11 TA is
+.IR ehost .
+The TA field is used in all frames except for management frames and
+CTS (Clear To Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3)
+currently know how to parse these protocols.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet.  The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies.  Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet.  The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies.  Each use of that expression increments the
+filter offsets by 4. 
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP \fBpppoes\fP
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE.
+.IP  "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet.  If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBllc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP  "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, &, |, <<, >>], a length operator, and special packet data
+accessors.  Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+To access
+data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
+code field), and \fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
+
+The following TCP flags field values are available: \fBtcp-fin\fP,
+\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
+\fBtcp-ack\fP, \fBtcp-urg\fP.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators
+(parentheses are special to the Shell and must be escaped).
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets.  (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH AUTHORS
+The original authors are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+It is currently being maintained by tcpdump.org.
+.LP
+The current version of libpcap is available via http:
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.LP
+The original distribution is available via anonymous ftp:
+.LP
+.RS
+.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/pcap-int.h b/pcap-int.h
new file mode 100644 (file)
index 0000000..8444e62
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.94 2008-09-16 00:20:23 guy Exp $ (LBL)
+ */
+
+#ifndef pcap_int_h
+#define        pcap_int_h
+
+#include <pcap/pcap.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_LIBDLPI
+#include <libdlpi.h>
+#endif
+
+#ifdef WIN32
+#include <Packet32.h>
+extern CRITICAL_SECTION g_PcapCompileCriticalSection;
+#endif /* WIN32 */
+
+#ifdef MSDOS
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+#ifdef HAVE_SNF_API
+#include <snf.h>
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
+
+/*
+ * Swap byte ordering of unsigned long long timestamp on a big endian
+ * machine.
+ */
+#define SWAPLL(ull)  ((ull & 0xff00000000000000) >> 56) | \
+                      ((ull & 0x00ff000000000000) >> 40) | \
+                      ((ull & 0x0000ff0000000000) >> 24) | \
+                      ((ull & 0x000000ff00000000) >> 8)  | \
+                      ((ull & 0x00000000ff000000) << 8)  | \
+                      ((ull & 0x0000000000ff0000) << 24) | \
+                      ((ull & 0x000000000000ff00) << 40) | \
+                      ((ull & 0x00000000000000ff) << 56)
+
+#else /* A recent Visual studio compiler or not VC */
+
+/*
+ * Swap byte ordering of unsigned long long timestamp on a big endian
+ * machine.
+ */
+#define SWAPLL(ull)  ((ull & 0xff00000000000000LL) >> 56) | \
+                      ((ull & 0x00ff000000000000LL) >> 40) | \
+                      ((ull & 0x0000ff0000000000LL) >> 24) | \
+                      ((ull & 0x000000ff00000000LL) >> 8)  | \
+                      ((ull & 0x00000000ff000000LL) << 8)  | \
+                      ((ull & 0x0000000000ff0000LL) << 24) | \
+                      ((ull & 0x000000000000ff00LL) << 40) | \
+                      ((ull & 0x00000000000000ffLL) << 56)
+
+#endif /* _MSC_VER */
+
+/*
+ * Savefile
+ */
+typedef enum {
+       NOT_SWAPPED,
+       SWAPPED,
+       MAYBE_SWAPPED
+} swapped_type_t;
+
+/*
+ * Used when reading a savefile.
+ */
+struct pcap_sf {
+       FILE *rfile;
+       int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
+       int swapped;
+       size_t hdrsize;
+       swapped_type_t lengths_swapped;
+       int version_major;
+       int version_minor;
+       bpf_u_int32 ifcount;    /* number of interfaces seen in this capture */
+       u_int tsresol;          /* time stamp resolution */
+       u_int tsscale;          /* scaling factor for resolution -> microseconds */
+       u_int64_t tsoffset;     /* time stamp offset */
+};
+
+/*
+ * Used when doing a live capture.
+ */
+struct pcap_md {
+       struct pcap_stat stat;
+       /*XXX*/
+       int use_bpf;            /* using kernel filter */
+       u_long  TotPkts;        /* can't oflow for 79 hrs on ether */
+       u_long  TotAccepted;    /* count accepted by filter */
+       u_long  TotDrops;       /* count of dropped packets */
+       long    TotMissed;      /* missed by i/f during this run */
+       long    OrigMissed;     /* missed by i/f before this run */
+       char    *device;        /* device name */
+       int     timeout;        /* timeout for buffering */
+       int     must_do_on_close; /* stuff we must do when we close */
+       struct pcap *next;      /* list of open pcaps that need stuff cleared on close */
+#ifdef linux
+       int     sock_packet;    /* using Linux 2.0 compatible interface */
+       int     cooked;         /* using SOCK_DGRAM rather than SOCK_RAW */
+       int     ifindex;        /* interface index of device we're bound to */
+       int     lo_ifindex;     /* interface index of the loopback device */
+       u_int   packets_read;   /* count of packets read with recvfrom() */
+       bpf_u_int32 oldmode;    /* mode to restore when turning monitor mode off */
+       char    *mondevice;     /* mac80211 monitor device we created */
+       u_char  *mmapbuf;       /* memory-mapped region pointer */
+       size_t  mmapbuflen;     /* size of region */
+       u_int   tp_version;     /* version of tpacket_hdr for mmaped ring */
+       u_int   tp_hdrlen;      /* hdrlen of tpacket_hdr for mmaped ring */
+       u_char  *oneshot_buffer; /* buffer for copy of packet */
+       long    proc_dropped; /* packets reported dropped by /proc/net/dev */
+#endif /* linux */
+
+#ifdef HAVE_DAG_API
+#ifdef HAVE_DAG_STREAMS_API
+       u_char  *dag_mem_bottom;        /* DAG card current memory bottom pointer */
+       u_char  *dag_mem_top;   /* DAG card current memory top pointer */
+#else /* HAVE_DAG_STREAMS_API */
+       void    *dag_mem_base;  /* DAG card memory base address */
+       u_int   dag_mem_bottom; /* DAG card current memory bottom offset */
+       u_int   dag_mem_top;    /* DAG card current memory top offset */
+#endif /* HAVE_DAG_STREAMS_API */
+       int     dag_fcs_bits;   /* Number of checksum bits from link layer */
+       int     dag_offset_flags; /* Flags to pass to dag_offset(). */
+       int     dag_stream;     /* DAG stream number */
+       int     dag_timeout;    /* timeout specified to pcap_open_live.
+                                * Same as in linux above, introduce
+                                * generally? */
+#endif /* HAVE_DAG_API */
+#ifdef HAVE_SNF_API
+       snf_handle_t snf_handle; /* opaque device handle */
+       snf_ring_t   snf_ring;   /* opaque device ring handle */
+        int          snf_timeout;
+        int          snf_boardnum;
+#endif /*HAVE_SNF_API*/
+
+#ifdef HAVE_ZEROCOPY_BPF
+       /*
+        * Zero-copy read buffer -- for zero-copy BPF.  'buffer' above will
+        * alternative between these two actual mmap'd buffers as required.
+        * As there is a header on the front size of the mmap'd buffer, only
+        * some of the buffer is exposed to libpcap as a whole via bufsize;
+        * zbufsize is the true size.  zbuffer tracks the current zbuf
+        * assocated with buffer so that it can be used to decide which the
+        * next buffer to read will be.
+        */
+       u_char *zbuf1, *zbuf2, *zbuffer;
+       u_int zbufsize;
+       u_int zerocopy;
+       u_int interrupted;
+       struct timespec firstsel;
+       /*
+        * If there's currently a buffer being actively processed, then it is
+        * referenced here; 'buffer' is also pointed at it, but offset by the
+        * size of the header.
+        */
+       struct bpf_zbuf_header *bzh;
+#endif /* HAVE_ZEROCOPY_BPF */
+};
+
+/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_PROMISC     0x00000001      /* clear promiscuous mode */
+#define MUST_CLEAR_RFMON       0x00000002      /* clear rfmon (monitor) mode */
+#define MUST_DELETE_MONIF      0x00000004      /* delete monitor-mode interface */
+
+struct pcap_opt {
+       int     buffer_size;
+       char    *source;
+       int     promisc;
+       int     rfmon;
+       int     tstamp_type;
+};
+
+/*
+ * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H
+ * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything
+ * line up on a nice boundary.
+ */
+#ifdef __NetBSD__
+#include <sys/param.h> /* needed to declare __NetBSD_Version__ */
+#endif
+
+#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000)
+#define       PCAP_FDDIPAD 3
+#endif
+
+typedef int    (*activate_op_t)(pcap_t *);
+typedef int    (*can_set_rfmon_op_t)(pcap_t *);
+typedef int    (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
+typedef int    (*inject_op_t)(pcap_t *, const void *, size_t);
+typedef int    (*setfilter_op_t)(pcap_t *, struct bpf_program *);
+typedef int    (*setdirection_op_t)(pcap_t *, pcap_direction_t);
+typedef int    (*set_datalink_op_t)(pcap_t *, int);
+typedef int    (*getnonblock_op_t)(pcap_t *, char *);
+typedef int    (*setnonblock_op_t)(pcap_t *, int, char *);
+typedef int    (*stats_op_t)(pcap_t *, struct pcap_stat *);
+#ifdef WIN32
+typedef int    (*setbuff_op_t)(pcap_t *, int);
+typedef int    (*setmode_op_t)(pcap_t *, int);
+typedef int    (*setmintocopy_op_t)(pcap_t *, int);
+#endif
+typedef void   (*cleanup_op_t)(pcap_t *);
+
+struct pcap {
+#ifdef WIN32
+       ADAPTER *adapter;
+       LPPACKET Packet;
+       int nonblock;
+#else
+       int fd;
+       int selectable_fd;
+       int send_fd;
+#endif /* WIN32 */
+
+#ifdef HAVE_LIBDLPI
+       dlpi_handle_t dlpi_hd;
+#endif
+       int snapshot;
+       int linktype;           /* Network linktype */
+       int linktype_ext;       /* Extended information stored in the linktype field of a file */
+       int tzoff;              /* timezone offset */
+       int offset;             /* offset for proper alignment */
+       int activated;          /* true if the capture is really started */
+       int oldstyle;           /* if we're opening with pcap_open_live() */
+
+       int break_loop;         /* flag set to force break from packet-reading loop */
+
+#ifdef PCAP_FDDIPAD
+       int fddipad;
+#endif
+
+#ifdef MSDOS
+        void (*wait_proc)(void); /*          call proc while waiting */
+#endif
+
+       struct pcap_sf sf;
+       struct pcap_md md;
+       struct pcap_opt opt;
+
+       /*
+        * Read buffer.
+        */
+       int bufsize;
+       u_char *buffer;
+       u_char *bp;
+       int cc;
+
+       /*
+        * Place holder for pcap_next().
+        */
+       u_char *pkt;
+
+       /* We're accepting only packets in this direction/these directions. */
+       pcap_direction_t direction;
+
+       /*
+        * Methods.
+        */
+       activate_op_t activate_op;
+       can_set_rfmon_op_t can_set_rfmon_op;
+       read_op_t read_op;
+       inject_op_t inject_op;
+       setfilter_op_t setfilter_op;
+       setdirection_op_t setdirection_op;
+       set_datalink_op_t set_datalink_op;
+       getnonblock_op_t getnonblock_op;
+       setnonblock_op_t setnonblock_op;
+       stats_op_t stats_op;
+
+       /*
+        * Routine to use as callback for pcap_next()/pcap_next_ex().
+        */
+       pcap_handler oneshot_callback;
+
+#ifdef WIN32
+       /*
+        * These are, at least currently, specific to the Win32 NPF
+        * driver.
+        */
+       setbuff_op_t setbuff_op;
+       setmode_op_t setmode_op;
+       setmintocopy_op_t setmintocopy_op;
+#endif
+       cleanup_op_t cleanup_op;
+
+       /*
+        * Placeholder for filter code if bpf not in kernel.
+        */
+       struct bpf_program fcode;
+
+       char errbuf[PCAP_ERRBUF_SIZE + 1];
+       int dlt_count;
+       u_int *dlt_list;
+       int tstamp_type_count;
+       u_int *tstamp_type_list;
+
+       struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
+};
+
+/*
+ * This is a timeval as stored in a savefile.
+ * It has to use the same types everywhere, independent of the actual
+ * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some
+ * platforms and 64-bit tv_sec values on other platforms, and writing
+ * out native `struct timeval' values would mean files could only be
+ * read on systems with the same tv_sec size as the system on which
+ * the file was written.
+ */
+
+struct pcap_timeval {
+    bpf_int32 tv_sec;          /* seconds */
+    bpf_int32 tv_usec;         /* microseconds */
+};
+
+/*
+ * This is a `pcap_pkthdr' as actually stored in a savefile.
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure),
+ * and do not make the time stamp anything other than seconds and
+ * microseconds (e.g., seconds and nanoseconds).  Instead:
+ *
+ *     introduce a new structure for the new format;
+ *
+ *     send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ *     a new magic number for your new capture file format, and, when
+ *     you get the new magic number, put it in "savefile.c";
+ *
+ *     use that magic number for save files with the changed record
+ *     header;
+ *
+ *     make the code in "savefile.c" capable of reading files with
+ *     the old record header as well as files with the new record header
+ *     (using the magic number to determine the header format).
+ *
+ * Then supply the changes as a patch at
+ *
+ *     http://sourceforge.net/projects/libpcap/
+ *
+ * so that future versions of libpcap and programs that use it (such as
+ * tcpdump) will be able to read your new capture file format.
+ */
+
+struct pcap_sf_pkthdr {
+    struct pcap_timeval ts;    /* time stamp */
+    bpf_u_int32 caplen;                /* length of portion present */
+    bpf_u_int32 len;           /* length this packet (off wire) */
+};
+
+/*
+ * How a `pcap_pkthdr' is actually stored in savefiles written
+ * by some patched versions of libpcap (e.g. the ones in Red
+ * Hat Linux 6.1 and 6.2).
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ * Instead, introduce a new structure, as per the above.
+ */
+
+struct pcap_sf_patched_pkthdr {
+    struct pcap_timeval ts;    /* time stamp */
+    bpf_u_int32 caplen;                /* length of portion present */
+    bpf_u_int32 len;           /* length this packet (off wire) */
+    int                index;
+    unsigned short protocol;
+    unsigned char pkt_type;
+};
+
+/*
+ * User data structure for the one-shot callback used for pcap_next()
+ * and pcap_next_ex().
+ */
+struct oneshot_userdata {
+       struct pcap_pkthdr *hdr;
+       const u_char **pkt;
+       pcap_t *pd;
+};
+
+int    yylex(void);
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+/* XXX should these be in pcap.h? */
+int    pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
+int    pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
+
+#ifndef HAVE_STRLCPY
+#define strlcpy(x, y, z) \
+       (strncpy((x), (y), (z)), \
+        ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
+        strlen((y)))
+#endif
+
+#include <stdarg.h>
+
+#if !defined(HAVE_SNPRINTF)
+#define snprintf pcap_snprintf
+extern int snprintf (char *, size_t, const char *, ...);
+#endif
+
+#if !defined(HAVE_VSNPRINTF)
+#define vsnprintf pcap_vsnprintf
+extern int vsnprintf (char *, size_t, const char *, va_list ap);
+#endif
+
+/*
+ * Routines that most pcap implementations can use for non-blocking mode.
+ */
+#if !defined(WIN32) && !defined(MSDOS)
+int    pcap_getnonblock_fd(pcap_t *, char *);
+int    pcap_setnonblock_fd(pcap_t *p, int, char *);
+#endif
+
+pcap_t *pcap_create_common(const char *, char *);
+int    pcap_do_addexit(pcap_t *);
+void   pcap_add_to_pcaps_to_close(pcap_t *);
+void   pcap_remove_from_pcaps_to_close(pcap_t *);
+void   pcap_cleanup_live_common(pcap_t *);
+int    pcap_not_initialized(pcap_t *);
+int    pcap_check_activated(pcap_t *);
+
+/*
+ * Internal interfaces for "pcap_findalldevs()".
+ *
+ * "pcap_platform_finddevs()" is a platform-dependent routine to
+ * add devices not found by the "standard" mechanisms (SIOCGIFCONF,
+ * "getifaddrs()", etc..
+ *
+ * "pcap_add_if()" adds an interface to the list of interfaces.
+ */
+int    pcap_platform_finddevs(pcap_if_t **, char *);
+int    add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *,
+           size_t, struct sockaddr *, size_t, struct sockaddr *, size_t,
+           struct sockaddr *, size_t, char *);
+int    pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *);
+struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
+int    add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
+           const char *, char *);
+
+#ifdef WIN32
+char   *pcap_win32strerror(void);
+#endif
+
+int    install_bpf_program(pcap_t *, struct bpf_program *);
+
+int    pcap_strcasecmp(const char *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c
new file mode 100644 (file)
index 0000000..8d6a038
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This code contributed by Sagun Shakya (sagun.shakya@sun.com)
+ */
+/*
+ * Packet capture routines for DLPI using libdlpi under SunOS 5.11.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+       "@(#) $Header: /tcpdump/master/libpcap/pcap-libdlpi.c,v 1.6 2008-04-14 20:40:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/bufmod.h>
+#include <sys/stream.h>
+#include <libdlpi.h>
+#include <errno.h>
+#include <memory.h>
+#include <stropts.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+/* Forwards. */
+static int dlpromiscon(pcap_t *, bpf_u_int32);
+static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
+static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
+static void pcap_close_libdlpi(pcap_t *);
+static void pcap_libdlpi_err(const char *, const char *, int, char *);
+static void pcap_cleanup_libdlpi(pcap_t *);
+
+/*
+ * list_interfaces() will list all the network links that are
+ * available on a system.
+ */
+static boolean_t list_interfaces(const char *, void *);
+
+typedef struct linknamelist {
+       char    linkname[DLPI_LINKNAME_MAX];
+       struct linknamelist *lnl_next;
+} linknamelist_t;
+
+typedef struct linkwalk {
+       linknamelist_t  *lw_list;
+       int             lw_err;
+} linkwalk_t;
+
+/*
+ * The caller of this function should free the memory allocated
+ * for each linknamelist_t "entry" allocated.
+ */
+static boolean_t
+list_interfaces(const char *linkname, void *arg)
+{
+       linkwalk_t      *lwp = arg;
+       linknamelist_t  *entry;
+
+       if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
+               lwp->lw_err = ENOMEM;
+               return (B_TRUE);
+       }
+       (void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
+
+       if (lwp->lw_list == NULL) {
+               lwp->lw_list = entry;
+       } else {
+               entry->lnl_next = lwp->lw_list;
+               lwp->lw_list = entry;
+       }
+
+       return (B_FALSE);
+}
+
+static int
+pcap_activate_libdlpi(pcap_t *p)
+{
+       int retv;
+       dlpi_handle_t dh;
+       dlpi_info_t dlinfo;
+       int err = PCAP_ERROR;
+
+       /*
+        * Enable Solaris raw and passive DLPI extensions;
+        * dlpi_open() will not fail if the underlying link does not support
+        * passive mode. See dlpi(7P) for details.
+        */
+       retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE);
+       if (retv != DLPI_SUCCESS) {
+               if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
+                       err = PCAP_ERROR_NO_SUCH_DEVICE;
+               else if (retv == DL_SYSERR &&
+                   (errno == EPERM || errno == EACCES))
+                       err = PCAP_ERROR_PERM_DENIED;
+               pcap_libdlpi_err(p->opt.source, "dlpi_open", retv,
+                   p->errbuf);
+               return (err);
+       }
+       p->dlpi_hd = dh;
+
+       if (p->opt.rfmon) {
+               /*
+                * This device exists, but we don't support monitor mode
+                * any platforms that support DLPI.
+                */
+               err = PCAP_ERROR_RFMON_NOTSUP;
+               goto bad;
+       }
+
+       /* Bind with DLPI_ANY_SAP. */
+       if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
+               pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
+               goto bad;
+       }
+
+       /* Enable promiscuous mode. */
+       if (p->opt.promisc) {
+               err = dlpromiscon(p, DL_PROMISC_PHYS);
+               if (err < 0) {
+                       /*
+                        * "You don't have permission to capture on
+                        * this device" and "you don't have permission
+                        * to capture in promiscuous mode on this
+                        * device" are different; let the user know,
+                        * so if they can't get permission to
+                        * capture in promiscuous mode, they can at
+                        * least try to capture in non-promiscuous
+                        * mode.
+                        *
+                        * XXX - you might have to capture in
+                        * promiscuous mode to see outgoing packets.
+                        */
+                       if (err == PCAP_ERROR_PERM_DENIED)
+                               err = PCAP_ERROR_PROMISC_PERM_DENIED;
+                       goto bad;
+               }
+       } else {
+               /* Try to enable multicast. */
+               err = dlpromiscon(p, DL_PROMISC_MULTI);
+               if (err < 0)
+                       goto bad;
+       }
+
+       /* Try to enable SAP promiscuity. */
+       err = dlpromiscon(p, DL_PROMISC_SAP);
+       if (err < 0) {
+               /*
+                * Not fatal, since the DL_PROMISC_PHYS mode worked.
+                * Report it as a warning, however.
+                */
+               if (p->opt.promisc)
+                       err = PCAP_WARNING;
+               else
+                       goto bad;
+       }
+
+       /* Determine link type.  */
+       if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
+               pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
+               goto bad;
+       }
+
+       if (pcap_process_mactype(p, dlinfo.di_mactype) != 0)
+               goto bad;
+
+       p->fd = dlpi_fd(p->dlpi_hd);
+
+       /* Push and configure bufmod. */
+       if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0)
+               goto bad;
+
+       /*
+        * Flush the read side.
+        */
+       if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* Allocate data buffer. */
+       if (pcap_alloc_databuf(p) != 0)
+               goto bad;
+
+       /*
+        * "p->fd" is a FD for a STREAMS device, so "select()" and
+        * "poll()" should work on it.
+        */
+       p->selectable_fd = p->fd;
+
+       p->read_op = pcap_read_libdlpi;
+       p->inject_op = pcap_inject_libdlpi;
+       p->setfilter_op = install_bpf_program;  /* No kernel filtering */
+       p->setdirection_op = NULL;      /* Not implemented */
+       p->set_datalink_op = NULL;      /* Can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_dlpi;
+       p->cleanup_op = pcap_cleanup_libdlpi;
+
+       return (0);
+bad:
+       pcap_cleanup_libdlpi(p);
+       return (err);
+}
+
+#define STRINGIFY(n)   #n
+
+static int
+dlpromiscon(pcap_t *p, bpf_u_int32 level)
+{
+       int err;
+
+       retv = dlpi_promiscon(p->hd, level);
+       if (retv != DLPI_SUCCESS) {
+               if (retv == DL_SYSERR &&
+                   (errno == EPERM || errno == EACCES))
+                       err = PCAP_ERROR_PERM_DENIED;
+               else
+                       err = PCAP_ERROR;
+               pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level),
+                   retv, p->errbuf);
+               return (err);
+       }
+       return (0);
+}
+
+/*
+ * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
+ * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
+ * additional network links present in the system.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       int retv = 0;
+
+       linknamelist_t  *entry, *next;
+       linkwalk_t      lw = {NULL, 0};
+       int             save_errno;
+
+       /* dlpi_walk() for loopback will be added here. */
+
+       dlpi_walk(list_interfaces, &lw, 0);
+
+       if (lw.lw_err != 0) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "dlpi_walk: %s", pcap_strerror(lw.lw_err));
+               retv = -1;
+               goto done;
+       }
+
+       /* Add linkname if it does not exist on the list. */
+       for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
+               if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0)
+                       retv = -1;
+       }
+done:
+       save_errno = errno;
+       for (entry = lw.lw_list; entry != NULL; entry = next) {
+               next = entry->lnl_next;
+               free(entry);
+       }
+       errno = save_errno;
+
+       return (retv);
+}
+
+/*
+ * Read data received on DLPI handle. Returns -2 if told to terminate, else
+ * returns the number of packets read.
+ */
+static int
+pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
+{
+       int len;
+       u_char *bufp;
+       size_t msglen;
+       int retv;
+
+       len = p->cc;
+       if (len != 0) {
+               bufp = p->bp;
+               goto process_pkts;
+       }
+       do {
+               /* Has "pcap_breakloop()" been called? */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that it has,
+                        * and return -2 to indicate that we were told to
+                        * break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return (-2);
+               }
+
+               msglen = p->bufsize;
+               bufp = p->buffer + p->offset;
+
+               retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp,
+                   &msglen, -1, NULL);
+               if (retv != DLPI_SUCCESS) {
+                       /*
+                        * This is most likely a call to terminate out of the
+                        * loop. So, do not return an error message, instead
+                        * check if "pcap_breakloop()" has been called above.
+                        */
+                       if (retv == DL_SYSERR && errno == EINTR) {
+                               len = 0;
+                               continue;
+                       }
+                       pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd),
+                           "dlpi_recv", retv, p->errbuf);
+                       return (-1);
+               }
+               len = msglen;
+       } while (len == 0);
+
+process_pkts:
+       return (pcap_process_pkts(p, callback, user, count, bufp, len));
+}
+
+static int
+pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
+{
+       int retv;
+
+       retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL);
+       if (retv != DLPI_SUCCESS) {
+               pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv,
+                   p->errbuf);
+               return (-1);
+       }
+       /*
+        * dlpi_send(3DLPI) does not provide a way to return the number of
+        * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
+        * returned we are assuming 'size' bytes were sent.
+        */
+       return (size);
+}
+
+/*
+ * Close dlpi handle.
+ */
+static void
+pcap_cleanup_libdlpi(pcap_t *p)
+{
+       if (p->dlpi_hd != NULL) {
+               dlpi_close(p->dlpi_hd);
+               p->dlpi_hd = NULL;
+               p->fd = -1;
+       }
+       pcap_cleanup_live_common(p);
+}
+
+/*
+ * Write error message to buffer.
+ */
+static void
+pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
+{
+       snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+           func, linkname, dlpi_strerror(err));
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_libdlpi;
+       return (p);
+}
diff --git a/pcap-linktype.manmisc.in b/pcap-linktype.manmisc.in
new file mode 100644 (file)
index 0000000..8904387
--- /dev/null
@@ -0,0 +1,50 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-linktype.manmisc.in,v 1.3 2008-10-27 22:52:30 guy Exp $
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "23 October 2008"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides.  This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers.  The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are described at
+http://www.tcpdump.org/linktypes.html.
+.SH SEE ALSO
+pcap_datalink(3PCAP)
diff --git a/pcap-linux.c b/pcap-linux.c
new file mode 100644 (file)
index 0000000..8168e47
--- /dev/null
@@ -0,0 +1,5561 @@
+/*
+ *  pcap-linux.c: Packet capture interface to the Linux kernel
+ *
+ *  Copyright (c) 2000 Torsten Landschoff <torsten@debian.org>
+ *                    Sebastian Krahmer  <krahmer@cs.uni-potsdam.de>
+ *
+ *  License: BSD
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of the authors may not be used to endorse or promote
+ *     products derived from this software without specific prior
+ *     written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Modifications:     Added PACKET_MMAP support
+ *                     Paolo Abeni <paolo.abeni@email.it> 
+ *                     
+ *                     based on previous works of:
+ *                     Simon Patarin <patarin@cs.unibo.it>
+ *                     Phil Wood <cpw@lanl.gov>
+ *
+ * Monitor-mode support for mac80211 includes code taken from the iw
+ * command; the copyright notice for that code is
+ *
+ * Copyright (c) 2007, 2008    Johannes Berg
+ * Copyright (c) 2007          Andy Lutomirski
+ * Copyright (c) 2007          Mike Kershaw
+ * Copyright (c) 2008          Gábor Stefanik
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.164 2008-12-14 22:00:57 guy Exp $ (LBL)";
+#endif
+
+/*
+ * Known problems with 2.0[.x] kernels:
+ *
+ *   - The loopback device gives every packet twice; on 2.2[.x] kernels,
+ *     if we use PF_PACKET, we can filter out the transmitted version
+ *     of the packet by using data in the "sockaddr_ll" returned by
+ *     "recvfrom()", but, on 2.0[.x] kernels, we have to use
+ *     PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a
+ *     "sockaddr_pkt" which doesn't give us enough information to let
+ *     us do that.
+ *
+ *   - We have to set the interface's IFF_PROMISC flag ourselves, if
+ *     we're to run in promiscuous mode, which means we have to turn
+ *     it off ourselves when we're done; the kernel doesn't keep track
+ *     of how many sockets are listening promiscuously, which means
+ *     it won't get turned off automatically when no sockets are
+ *     listening promiscuously.  We catch "pcap_close()" and, for
+ *     interfaces we put into promiscuous mode, take them out of
+ *     promiscuous mode - which isn't necessarily the right thing to
+ *     do, if another socket also requested promiscuous mode between
+ *     the time when we opened the socket and the time when we close
+ *     the socket.
+ *
+ *   - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()"
+ *     return the amount of data that you could have read, rather than
+ *     the amount that was returned, so we can't just allocate a buffer
+ *     whose size is the snapshot length and pass the snapshot length
+ *     as the byte count, and also pass MSG_TRUNC, so that the return
+ *     value tells us how long the packet was on the wire.
+ *
+ *     This means that, if we want to get the actual size of the packet,
+ *     so we can return it in the "len" field of the packet header,
+ *     we have to read the entire packet, not just the part that fits
+ *     within the snapshot length, and thus waste CPU time copying data
+ *     from the kernel that our caller won't see.
+ *
+ *     We have to get the actual size, and supply it in "len", because
+ *     otherwise, the IP dissector in tcpdump, for example, will complain
+ *     about "truncated-ip", as the packet will appear to have been
+ *     shorter, on the wire, than the IP header said it should have been.
+ */
+
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <sys/mman.h>
+#include <linux/if.h>
+#include <netinet/in.h>
+#include <linux/if_ether.h>
+#include <net/if_arp.h>
+#include <poll.h>
+#include <dirent.h>
+
+#include "pcap-int.h"
+#include "pcap/sll.h"
+#include "pcap/vlan.h"
+
+#ifdef HAVE_DAG_API
+#include "pcap-dag.h"
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+#include "pcap-septel.h"
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef HAVE_SNF_API
+#include "pcap-snf.h"
+#endif /* HAVE_SNF_API */
+
+#ifdef PCAP_SUPPORT_USB
+#include "pcap-usb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_BT
+#include "pcap-bt-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_CAN
+#include "pcap-can-linux.h"
+#endif
+
+#if PCAP_SUPPORT_CANUSB
+#include "pcap-canusb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_NETFILTER
+#include "pcap-netfilter-linux.h"
+#endif
+
+/*
+ * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
+ * sockets rather than SOCK_PACKET sockets.
+ *
+ * To use them, we include <linux/if_packet.h> rather than
+ * <netpacket/packet.h>; we do so because
+ *
+ *     some Linux distributions (e.g., Slackware 4.0) have 2.2 or
+ *     later kernels and libc5, and don't provide a <netpacket/packet.h>
+ *     file;
+ *
+ *     not all versions of glibc2 have a <netpacket/packet.h> file
+ *     that defines stuff needed for some of the 2.4-or-later-kernel
+ *     features, so if the system has a 2.4 or later kernel, we
+ *     still can't use those features.
+ *
+ * We're already including a number of other <linux/XXX.h> headers, and
+ * this code is Linux-specific (no other OS has PF_PACKET sockets as
+ * a raw packet capture mechanism), so it's not as if you gain any
+ * useful portability by using <netpacket/packet.h>
+ *
+ * XXX - should we just include <linux/if_packet.h> even if PF_PACKET
+ * isn't defined?  It only defines one data structure in 2.0.x, so
+ * it shouldn't cause any problems.
+ */
+#ifdef PF_PACKET
+# include <linux/if_packet.h>
+
+ /*
+  * On at least some Linux distributions (for example, Red Hat 5.2),
+  * there's no <netpacket/packet.h> file, but PF_PACKET is defined if
+  * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
+  * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of
+  * the PACKET_xxx stuff.
+  *
+  * So we check whether PACKET_HOST is defined, and assume that we have
+  * PF_PACKET sockets only if it is defined.
+  */
+# ifdef PACKET_HOST
+#  define HAVE_PF_PACKET_SOCKETS
+#  ifdef PACKET_AUXDATA
+#   define HAVE_PACKET_AUXDATA
+#  endif /* PACKET_AUXDATA */
+# endif /* PACKET_HOST */
+
+
+ /* check for memory mapped access avaibility. We assume every needed 
+  * struct is defined if the macro TPACKET_HDRLEN is defined, because it
+  * uses many ring related structs and macros */
+# ifdef TPACKET_HDRLEN
+#  define HAVE_PACKET_RING
+#  ifdef TPACKET2_HDRLEN
+#   define HAVE_TPACKET2
+#  else
+#   define TPACKET_V1  0
+#  endif /* TPACKET2_HDRLEN */
+# endif /* TPACKET_HDRLEN */
+#endif /* PF_PACKET */
+
+#ifdef SO_ATTACH_FILTER
+#include <linux/types.h>
+#include <linux/filter.h>
+#endif
+
+/*
+ * We need linux/sockios.h if we have linux/net_tstamp.h (for time stamp
+ * specification) or linux/ethtool.h (for ethtool ioctls to get offloading
+ * information).
+ */
+#if defined(HAVE_LINUX_NET_TSTAMP_H) || defined(HAVE_LINUX_ETHTOOL_H)
+#include <linux/sockios.h>
+#endif
+
+#ifdef HAVE_LINUX_NET_TSTAMP_H
+#include <linux/net_tstamp.h>
+#endif
+
+/*
+ * Got Wireless Extensions?
+ */
+#ifdef HAVE_LINUX_WIRELESS_H
+#include <linux/wireless.h>
+#endif /* HAVE_LINUX_WIRELESS_H */
+
+/*
+ * Got libnl?
+ */
+#ifdef HAVE_LIBNL
+#include <linux/nl80211.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#endif /* HAVE_LIBNL */
+
+/*
+ * Got ethtool support?
+ */
+#ifdef HAVE_LINUX_ETHTOOL_H
+#include <linux/ethtool.h>
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef int            socklen_t;
+#endif
+
+#ifndef MSG_TRUNC
+/*
+ * This is being compiled on a system that lacks MSG_TRUNC; define it
+ * with the value it has in the 2.2 and later kernels, so that, on
+ * those kernels, when we pass it in the flags argument to "recvfrom()"
+ * we're passing the right value and thus get the MSG_TRUNC behavior
+ * we want.  (We don't get that behavior on 2.0[.x] kernels, because
+ * they didn't support MSG_TRUNC.)
+ */
+#define MSG_TRUNC      0x20
+#endif
+
+#ifndef SOL_PACKET
+/*
+ * This is being compiled on a system that lacks SOL_PACKET; define it
+ * with the value it has in the 2.2 and later kernels, so that we can
+ * set promiscuous mode in the good modern way rather than the old
+ * 2.0-kernel crappy way.
+ */
+#define SOL_PACKET     263
+#endif
+
+#define MAX_LINKHEADER_SIZE    256
+
+/*
+ * When capturing on all interfaces we use this as the buffer size.
+ * Should be bigger then all MTUs that occur in real life.
+ * 64kB should be enough for now.
+ */
+#define BIGGER_THAN_ALL_MTUS   (64*1024)
+
+/*
+ * Prototypes for internal functions and methods.
+ */
+static void map_arphrd_to_dlt(pcap_t *, int, int);
+#ifdef HAVE_PF_PACKET_SOCKETS
+static short int map_packet_type_to_sll_type(short int);
+#endif
+static int pcap_activate_linux(pcap_t *);
+static int activate_old(pcap_t *);
+static int activate_new(pcap_t *);
+static int activate_mmap(pcap_t *, int *);
+static int pcap_can_set_rfmon_linux(pcap_t *);
+static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
+static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
+static int pcap_inject_linux(pcap_t *, const void *, size_t);
+static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
+static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
+static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
+static void pcap_cleanup_linux(pcap_t *);
+
+union thdr {
+       struct tpacket_hdr      *h1;
+       struct tpacket2_hdr     *h2;
+       void                    *raw;
+};
+
+#ifdef HAVE_PACKET_RING
+#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
+
+static void destroy_ring(pcap_t *handle);
+static int create_ring(pcap_t *handle, int *status);
+static int prepare_tpacket_socket(pcap_t *handle);
+static void pcap_cleanup_linux_mmap(pcap_t *);
+static int pcap_read_linux_mmap(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
+static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
+static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf);
+static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+    const u_char *bytes);
+#endif
+
+/*
+ * Wrap some ioctl calls
+ */
+#ifdef HAVE_PF_PACKET_SOCKETS
+static int     iface_get_id(int fd, const char *device, char *ebuf);
+#endif /* HAVE_PF_PACKET_SOCKETS */
+static int     iface_get_mtu(int fd, const char *device, char *ebuf);
+static int     iface_get_arptype(int fd, const char *device, char *ebuf);
+#ifdef HAVE_PF_PACKET_SOCKETS
+static int     iface_bind(int fd, int ifindex, char *ebuf);
+#ifdef IW_MODE_MONITOR
+static int     has_wext(int sock_fd, const char *device, char *ebuf);
+#endif /* IW_MODE_MONITOR */
+static int     enter_rfmon_mode(pcap_t *handle, int sock_fd,
+    const char *device);
+#endif /* HAVE_PF_PACKET_SOCKETS */
+static int     iface_get_offload(pcap_t *handle);
+static int     iface_bind_old(int fd, const char *device, char *ebuf);
+
+#ifdef SO_ATTACH_FILTER
+static int     fix_program(pcap_t *handle, struct sock_fprog *fcode,
+    int is_mapped);
+static int     fix_offset(struct bpf_insn *p);
+static int     set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode);
+static int     reset_kernel_filter(pcap_t *handle);
+
+static struct sock_filter      total_insn
+       = BPF_STMT(BPF_RET | BPF_K, 0);
+static struct sock_fprog       total_fcode
+       = { 1, &total_insn };
+#endif /* SO_ATTACH_FILTER */
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *handle;
+
+       /*
+        * A null device name is equivalent to the "any" device.
+        */
+       if (device == NULL)
+               device = "any";
+
+#ifdef HAVE_DAG_API
+       if (strstr(device, "dag")) {
+               return dag_create(device, ebuf);
+       }
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+       if (strstr(device, "septel")) {
+               return septel_create(device, ebuf);
+       }
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef HAVE_SNF_API
+        handle = snf_create(device, ebuf);
+        if (strstr(device, "snf") || handle != NULL)
+               return handle;
+
+#endif /* HAVE_SNF_API */
+
+#ifdef PCAP_SUPPORT_BT
+       if (strstr(device, "bluetooth")) {
+               return bt_create(device, ebuf);
+       }
+#endif
+
+#if PCAP_SUPPORT_CANUSB
+  if (strstr(device, "canusb")) {
+    return canusb_create(device, ebuf);
+  }
+#endif
+
+#ifdef PCAP_SUPPORT_CAN
+       if ((strncmp(device, "can", 3) == 0 && isdigit(device[3])) ||
+           (strncmp(device, "vcan", 4) == 0 && isdigit(device[4]))) {
+               return can_create(device, ebuf);
+       }
+#endif
+
+#ifdef PCAP_SUPPORT_USB
+       if (strstr(device, "usbmon")) {
+               return usb_create(device, ebuf);
+       }
+#endif
+
+#ifdef PCAP_SUPPORT_NETFILTER
+       if (strncmp(device, "nflog", strlen("nflog")) == 0) {
+               return nflog_create(device, ebuf);
+       }
+#endif
+
+       handle = pcap_create_common(device, ebuf);
+       if (handle == NULL)
+               return NULL;
+
+       handle->activate_op = pcap_activate_linux;
+       handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+       /*
+        * We claim that we support:
+        *
+        *      software time stamps, with no details about their precision;
+        *      hardware time stamps, synced to the host time;
+        *      hardware time stamps, not synced to the host time.
+        *
+        * XXX - we can't ask a device whether it supports
+        * hardware time stamps, so we just claim all devices do.
+        */
+       handle->tstamp_type_count = 3;
+       handle->tstamp_type_list = malloc(3 * sizeof(u_int));
+       if (handle->tstamp_type_list == NULL) {
+               free(handle);
+               return NULL;
+       }
+       handle->tstamp_type_list[0] = PCAP_TSTAMP_HOST;
+       handle->tstamp_type_list[1] = PCAP_TSTAMP_ADAPTER;
+       handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED;
+#endif
+
+       return handle;
+}
+
+#ifdef HAVE_LIBNL
+/*
+ * If interface {if} is a mac80211 driver, the file
+ * /sys/class/net/{if}/phy80211 is a symlink to
+ * /sys/class/ieee80211/{phydev}, for some {phydev}.
+ *
+ * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
+ * least, has a "wmaster0" device and a "wlan0" device; the
+ * latter is the one with the IP address.  Both show up in
+ * "tcpdump -D" output.  Capturing on the wmaster0 device
+ * captures with 802.11 headers.
+ *
+ * airmon-ng searches through /sys/class/net for devices named
+ * monN, starting with mon0; as soon as one *doesn't* exist,
+ * it chooses that as the monitor device name.  If the "iw"
+ * command exists, it does "iw dev {if} interface add {monif}
+ * type monitor", where {monif} is the monitor device.  It
+ * then (sigh) sleeps .1 second, and then configures the
+ * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
+ * is a file, it writes {mondev}, without a newline, to that file,
+ * and again (sigh) sleeps .1 second, and then iwconfig's that
+ * device into monitor mode and configures it up.  Otherwise,
+ * you can't do monitor mode.
+ *
+ * All these devices are "glued" together by having the
+ * /sys/class/net/{device}/phy80211 links pointing to the same
+ * place, so, given a wmaster, wlan, or mon device, you can
+ * find the other devices by looking for devices with
+ * the same phy80211 link.
+ *
+ * To turn monitor mode off, delete the monitor interface,
+ * either with "iw dev {monif} interface del" or by sending
+ * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+ *
+ * Note: if you try to create a monitor device named "monN", and
+ * there's already a "monN" device, it fails, as least with
+ * the netlink interface (which is what iw uses), with a return
+ * value of -ENFILE.  (Return values are negative errnos.)  We
+ * could probably use that to find an unused device.
+ *
+ * Yes, you can have multiple monitor devices for a given
+ * physical device.
+*/
+
+/*
+ * Is this a mac80211 device?  If so, fill in the physical device path and
+ * return 1; if not, return 0.  On an error, fill in handle->errbuf and
+ * return PCAP_ERROR.
+ */
+static int
+get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
+    size_t phydev_max_pathlen)
+{
+       char *pathstr;
+       ssize_t bytes_read;
+
+       /*
+        * Generate the path string for the symlink to the physical device.
+        */
+       if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: Can't generate path name string for /sys/class/net device",
+                   device);
+               return PCAP_ERROR;
+       }
+       bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen);
+       if (bytes_read == -1) {
+               if (errno == ENOENT || errno == EINVAL) {
+                       /*
+                        * Doesn't exist, or not a symlink; assume that
+                        * means it's not a mac80211 device.
+                        */
+                       free(pathstr);
+                       return 0;
+               }
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: Can't readlink %s: %s", device, pathstr,
+                   strerror(errno));
+               free(pathstr);
+               return PCAP_ERROR;
+       }
+       free(pathstr);
+       phydev_path[bytes_read] = '\0';
+       return 1;
+}
+
+#ifdef HAVE_LIBNL_2_x
+#define get_nl_errmsg  nl_geterror
+#else
+/* libnl 2.x compatibility code */
+
+#define nl_sock nl_handle
+
+static inline struct nl_handle *
+nl_socket_alloc(void)
+{
+       return nl_handle_alloc();
+}
+
+static inline void
+nl_socket_free(struct nl_handle *h)
+{
+       nl_handle_destroy(h);
+}
+
+#define get_nl_errmsg  strerror
+
+static inline int
+__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache)
+{
+       struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
+       if (!tmp)
+               return -ENOMEM;
+       *cache = tmp;
+       return 0;
+}
+#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
+#endif /* !HAVE_LIBNL_2_x */
+
+struct nl80211_state {
+       struct nl_sock *nl_sock;
+       struct nl_cache *nl_cache;
+       struct genl_family *nl80211;
+};
+
+static int
+nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
+{
+       int err;
+
+       state->nl_sock = nl_socket_alloc();
+       if (!state->nl_sock) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: failed to allocate netlink handle", device);
+               return PCAP_ERROR;
+       }
+
+       if (genl_connect(state->nl_sock)) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: failed to connect to generic netlink", device);
+               goto out_handle_destroy;
+       }
+
+       err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
+       if (err < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: failed to allocate generic netlink cache: %s",
+                   device, get_nl_errmsg(-err));
+               goto out_handle_destroy;
+       }
+
+       state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
+       if (!state->nl80211) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: nl80211 not found", device);
+               goto out_cache_free;
+       }
+
+       return 0;
+
+out_cache_free:
+       nl_cache_free(state->nl_cache);
+out_handle_destroy:
+       nl_socket_free(state->nl_sock);
+       return PCAP_ERROR;
+}
+
+static void
+nl80211_cleanup(struct nl80211_state *state)
+{
+       genl_family_put(state->nl80211);
+       nl_cache_free(state->nl_cache);
+       nl_socket_free(state->nl_sock);
+}
+
+static int
+add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+    const char *device, const char *mondevice)
+{
+       int ifindex;
+       struct nl_msg *msg;
+       int err;
+
+       ifindex = iface_get_id(sock_fd, device, handle->errbuf);
+       if (ifindex == -1)
+               return PCAP_ERROR;
+
+       msg = nlmsg_alloc();
+       if (!msg) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: failed to allocate netlink msg", device);
+               return PCAP_ERROR;
+       }
+
+       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+                   0, NL80211_CMD_NEW_INTERFACE, 0);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+       NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
+
+       err = nl_send_auto_complete(state->nl_sock, msg);
+       if (err < 0) {
+#ifdef HAVE_LIBNL_2_x
+               if (err == -NLE_FAILURE) {
+#else
+               if (err == -ENFILE) {
+#endif
+                       /*
+                        * Device not available; our caller should just
+                        * keep trying.  (libnl 2.x maps ENFILE to
+                        * NLE_FAILURE; it can also map other errors
+                        * to that, but there's not much we can do
+                        * about that.)
+                        */
+                       nlmsg_free(msg);
+                       return 0;
+               } else {
+                       /*
+                        * Real failure, not just "that device is not
+                        * available.
+                        */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: nl_send_auto_complete failed adding %s interface: %s",
+                           device, mondevice, get_nl_errmsg(-err));
+                       nlmsg_free(msg);
+                       return PCAP_ERROR;
+               }
+       }
+       err = nl_wait_for_ack(state->nl_sock);
+       if (err < 0) {
+#ifdef HAVE_LIBNL_2_x
+               if (err == -NLE_FAILURE) {
+#else
+               if (err == -ENFILE) {
+#endif
+                       /*
+                        * Device not available; our caller should just
+                        * keep trying.  (libnl 2.x maps ENFILE to
+                        * NLE_FAILURE; it can also map other errors
+                        * to that, but there's not much we can do
+                        * about that.)
+                        */
+                       nlmsg_free(msg);
+                       return 0;
+               } else {
+                       /*
+                        * Real failure, not just "that device is not
+                        * available.
+                        */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: nl_wait_for_ack failed adding %s interface: %s",
+                           device, mondevice, get_nl_errmsg(-err));
+                       nlmsg_free(msg);
+                       return PCAP_ERROR;
+               }
+       }
+
+       /*
+        * Success.
+        */
+       nlmsg_free(msg);
+       return 1;
+
+nla_put_failure:
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "%s: nl_put failed adding %s interface",
+           device, mondevice);
+       nlmsg_free(msg);
+       return PCAP_ERROR;
+}
+
+static int
+del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+    const char *device, const char *mondevice)
+{
+       int ifindex;
+       struct nl_msg *msg;
+       int err;
+
+       ifindex = iface_get_id(sock_fd, mondevice, handle->errbuf);
+       if (ifindex == -1)
+               return PCAP_ERROR;
+
+       msg = nlmsg_alloc();
+       if (!msg) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: failed to allocate netlink msg", device);
+               return PCAP_ERROR;
+       }
+
+       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+                   0, NL80211_CMD_DEL_INTERFACE, 0);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+
+       err = nl_send_auto_complete(state->nl_sock, msg);
+       if (err < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: nl_send_auto_complete failed deleting %s interface: %s",
+                   device, mondevice, get_nl_errmsg(-err));
+               nlmsg_free(msg);
+               return PCAP_ERROR;
+       }
+       err = nl_wait_for_ack(state->nl_sock);
+       if (err < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: nl_wait_for_ack failed adding %s interface: %s",
+                   device, mondevice, get_nl_errmsg(-err));
+               nlmsg_free(msg);
+               return PCAP_ERROR;
+       }
+
+       /*
+        * Success.
+        */
+       nlmsg_free(msg);
+       return 1;
+
+nla_put_failure:
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "%s: nl_put failed deleting %s interface",
+           device, mondevice);
+       nlmsg_free(msg);
+       return PCAP_ERROR;
+}
+
+static int
+enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
+{
+       int ret;
+       char phydev_path[PATH_MAX+1];
+       struct nl80211_state nlstate;
+       struct ifreq ifr;
+       u_int n;
+
+       /*
+        * Is this a mac80211 device?
+        */
+       ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
+       if (ret < 0)
+               return ret;     /* error */
+       if (ret == 0)
+               return 0;       /* no error, but not mac80211 device */
+
+       /*
+        * XXX - is this already a monN device?
+        * If so, we're done.
+        * Is that determined by old Wireless Extensions ioctls?
+        */
+
+       /*
+        * OK, it's apparently a mac80211 device.
+        * Try to find an unused monN device for it.
+        */
+       ret = nl80211_init(handle, &nlstate, device);
+       if (ret != 0)
+               return ret;
+       for (n = 0; n < UINT_MAX; n++) {
+               /*
+                * Try mon{n}.
+                */
+               char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */
+
+               snprintf(mondevice, sizeof mondevice, "mon%u", n);
+               ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
+               if (ret == 1) {
+                       handle->md.mondevice = strdup(mondevice);
+                       goto added;
+               }
+               if (ret < 0) {
+                       /*
+                        * Hard failure.  Just return ret; handle->errbuf
+                        * has already been set.
+                        */
+                       nl80211_cleanup(&nlstate);
+                       return ret;
+               }
+       }
+
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "%s: No free monN interfaces", device);
+       nl80211_cleanup(&nlstate);
+       return PCAP_ERROR;
+
+added:
+
+#if 0
+       /*
+        * Sleep for .1 seconds.
+        */
+       delay.tv_sec = 0;
+       delay.tv_nsec = 500000000;
+       nanosleep(&delay, NULL);
+#endif
+
+       /*
+        * If we haven't already done so, arrange to have
+        * "pcap_close_all()" called when we exit.
+        */
+       if (!pcap_do_addexit(handle)) {
+               /*
+                * "atexit()" failed; don't put the interface
+                * in rfmon mode, just give up.
+                */
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       /*
+        * Now configure the monitor interface up.
+        */
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, handle->md.mondevice, sizeof(ifr.ifr_name));
+       if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: Can't get flags for %s: %s", device,
+                   handle->md.mondevice, strerror(errno));
+               del_mon_if(handle, sock_fd, &nlstate, device,
+                   handle->md.mondevice);
+               nl80211_cleanup(&nlstate);
+               return PCAP_ERROR;
+       }
+       ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
+       if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: Can't set flags for %s: %s", device,
+                   handle->md.mondevice, strerror(errno));
+               del_mon_if(handle, sock_fd, &nlstate, device,
+                   handle->md.mondevice);
+               nl80211_cleanup(&nlstate);
+               return PCAP_ERROR;
+       }
+
+       /*
+        * Success.  Clean up the libnl state.
+        */
+       nl80211_cleanup(&nlstate);
+
+       /*
+        * Note that we have to delete the monitor device when we close
+        * the handle.
+        */
+       handle->md.must_do_on_close |= MUST_DELETE_MONIF;
+
+       /*
+        * Add this to the list of pcaps to close when we exit.
+        */
+       pcap_add_to_pcaps_to_close(handle);
+
+       return 1;
+}
+#endif /* HAVE_LIBNL */
+
+static int
+pcap_can_set_rfmon_linux(pcap_t *handle)
+{
+#ifdef HAVE_LIBNL
+       char phydev_path[PATH_MAX+1];
+       int ret;
+#endif
+#ifdef IW_MODE_MONITOR
+       int sock_fd;
+       struct iwreq ireq;
+#endif
+
+       if (strcmp(handle->opt.source, "any") == 0) {
+               /*
+                * Monitor mode makes no sense on the "any" device.
+                */
+               return 0;
+       }
+
+#ifdef HAVE_LIBNL
+       /*
+        * Bleah.  There doesn't seem to be a way to ask a mac80211
+        * device, through libnl, whether it supports monitor mode;
+        * we'll just check whether the device appears to be a
+        * mac80211 device and, if so, assume the device supports
+        * monitor mode.
+        *
+        * wmaster devices don't appear to support the Wireless
+        * Extensions, but we can create a mon device for a
+        * wmaster device, so we don't bother checking whether
+        * a mac80211 device supports the Wireless Extensions.
+        */
+       ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path,
+           PATH_MAX);
+       if (ret < 0)
+               return ret;     /* error */
+       if (ret == 1)
+               return 1;       /* mac80211 device */
+#endif
+
+#ifdef IW_MODE_MONITOR
+       /*
+        * Bleah.  There doesn't appear to be an ioctl to use to ask
+        * whether a device supports monitor mode; we'll just do
+        * SIOCGIWMODE and, if it succeeds, assume the device supports
+        * monitor mode.
+        *
+        * Open a socket on which to attempt to get the mode.
+        * (We assume that if we have Wireless Extensions support
+        * we also have PF_PACKET support.)
+        */
+       sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+       if (sock_fd == -1) {
+               (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               return PCAP_ERROR;
+       }
+
+       /*
+        * Attempt to get the current mode.
+        */
+       strncpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source,
+           sizeof ireq.ifr_ifrn.ifrn_name);
+       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+       if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
+               /*
+                * Well, we got the mode; assume we can set it.
+                */
+               close(sock_fd);
+               return 1;
+       }
+       if (errno == ENODEV) {
+               /* The device doesn't even exist. */
+               (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "SIOCGIWMODE failed: %s", pcap_strerror(errno));
+               close(sock_fd);
+               return PCAP_ERROR_NO_SUCH_DEVICE;
+       }
+       close(sock_fd);
+#endif
+       return 0;
+}
+
+/*
+ * Grabs the number of dropped packets by the interface from /proc/net/dev.
+ *
+ * XXX - what about /sys/class/net/{interface name}/rx_*?  There are
+ * individual devices giving, in ASCII, various rx_ and tx_ statistics.
+ *
+ * Or can we get them in binary form from netlink?
+ */
+static long int
+linux_if_drops(const char * if_name)
+{
+       char buffer[512];
+       char * bufptr;
+       FILE * file;
+       int field_to_convert = 3, if_name_sz = strlen(if_name);
+       long int dropped_pkts = 0;
+       
+       file = fopen("/proc/net/dev", "r");
+       if (!file)
+               return 0;
+
+       while (!dropped_pkts && fgets( buffer, sizeof(buffer), file ))
+       {
+               /*      search for 'bytes' -- if its in there, then
+                       that means we need to grab the fourth field. otherwise
+                       grab the third field. */
+               if (field_to_convert != 4 && strstr(buffer, "bytes"))
+               {
+                       field_to_convert = 4;
+                       continue;
+               }
+       
+               /* find iface and make sure it actually matches -- space before the name and : after it */
+               if ((bufptr = strstr(buffer, if_name)) &&
+                       (bufptr == buffer || *(bufptr-1) == ' ') &&
+                       *(bufptr + if_name_sz) == ':')
+               {
+                       bufptr = bufptr + if_name_sz + 1;
+
+                       /* grab the nth field from it */
+                       while( --field_to_convert && *bufptr != '\0')
+                       {
+                               while (*bufptr != '\0' && *(bufptr++) == ' ');
+                               while (*bufptr != '\0' && *(bufptr++) != ' ');
+                       }
+                       
+                       /* get rid of any final spaces */
+                       while (*bufptr != '\0' && *bufptr == ' ') bufptr++;
+                       
+                       if (*bufptr != '\0')
+                               dropped_pkts = strtol(bufptr, NULL, 10);
+
+                       break;
+               }
+       }
+       
+       fclose(file);
+       return dropped_pkts;
+} 
+
+
+/*
+ * With older kernels promiscuous mode is kind of interesting because we
+ * have to reset the interface before exiting. The problem can't really
+ * be solved without some daemon taking care of managing usage counts.
+ * If we put the interface into promiscuous mode, we set a flag indicating
+ * that we must take it out of that mode when the interface is closed,
+ * and, when closing the interface, if that flag is set we take it out
+ * of promiscuous mode.
+ *
+ * Even with newer kernels, we have the same issue with rfmon mode.
+ */
+
+static void    pcap_cleanup_linux( pcap_t *handle )
+{
+       struct ifreq    ifr;
+#ifdef HAVE_LIBNL
+       struct nl80211_state nlstate;
+       int ret;
+#endif /* HAVE_LIBNL */
+#ifdef IW_MODE_MONITOR
+       int oldflags;
+       struct iwreq ireq;
+#endif /* IW_MODE_MONITOR */
+
+       if (handle->md.must_do_on_close != 0) {
+               /*
+                * There's something we have to do when closing this
+                * pcap_t.
+                */
+               if (handle->md.must_do_on_close & MUST_CLEAR_PROMISC) {
+                       /*
+                        * We put the interface into promiscuous mode;
+                        * take it out of promiscuous mode.
+                        *
+                        * XXX - if somebody else wants it in promiscuous
+                        * mode, this code cannot know that, so it'll take
+                        * it out of promiscuous mode.  That's not fixable
+                        * in 2.0[.x] kernels.
+                        */
+                       memset(&ifr, 0, sizeof(ifr));
+                       strncpy(ifr.ifr_name, handle->md.device,
+                           sizeof(ifr.ifr_name));
+                       if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+                               fprintf(stderr,
+                                   "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n"
+                                   "Please adjust manually.\n"
+                                   "Hint: This can't happen with Linux >= 2.2.0.\n",
+                                   handle->md.device, strerror(errno));
+                       } else {
+                               if (ifr.ifr_flags & IFF_PROMISC) {
+                                       /*
+                                        * Promiscuous mode is currently on;
+                                        * turn it off.
+                                        */
+                                       ifr.ifr_flags &= ~IFF_PROMISC;
+                                       if (ioctl(handle->fd, SIOCSIFFLAGS,
+                                           &ifr) == -1) {
+                                               fprintf(stderr,
+                                                   "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n"
+                                                   "Please adjust manually.\n"
+                                                   "Hint: This can't happen with Linux >= 2.2.0.\n",
+                                                   handle->md.device,
+                                                   strerror(errno));
+                                       }
+                               }
+                       }
+               }
+
+#ifdef HAVE_LIBNL
+               if (handle->md.must_do_on_close & MUST_DELETE_MONIF) {
+                       ret = nl80211_init(handle, &nlstate, handle->md.device);
+                       if (ret >= 0) {
+                               ret = del_mon_if(handle, handle->fd, &nlstate,
+                                   handle->md.device, handle->md.mondevice);
+                               nl80211_cleanup(&nlstate);
+                       }
+                       if (ret < 0) {
+                               fprintf(stderr,
+                                   "Can't delete monitor interface %s (%s).\n"
+                                   "Please delete manually.\n",
+                                   handle->md.mondevice, handle->errbuf);
+                       }
+               }
+#endif /* HAVE_LIBNL */
+
+#ifdef IW_MODE_MONITOR
+               if (handle->md.must_do_on_close & MUST_CLEAR_RFMON) {
+                       /*
+                        * We put the interface into rfmon mode;
+                        * take it out of rfmon mode.
+                        *
+                        * XXX - if somebody else wants it in rfmon
+                        * mode, this code cannot know that, so it'll take
+                        * it out of rfmon mode.
+                        */
+
+                       /*
+                        * First, take the interface down if it's up;
+                        * otherwise, we might get EBUSY.
+                        * If we get errors, just drive on and print
+                        * a warning if we can't restore the mode.
+                        */
+                       oldflags = 0;
+                       memset(&ifr, 0, sizeof(ifr));
+                       strncpy(ifr.ifr_name, handle->md.device,
+                           sizeof(ifr.ifr_name));
+                       if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
+                               if (ifr.ifr_flags & IFF_UP) {
+                                       oldflags = ifr.ifr_flags;
+                                       ifr.ifr_flags &= ~IFF_UP;
+                                       if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1)
+                                               oldflags = 0;   /* didn't set, don't restore */
+                               }
+                       }
+
+                       /*
+                        * Now restore the mode.
+                        */
+                       strncpy(ireq.ifr_ifrn.ifrn_name, handle->md.device,
+                           sizeof ireq.ifr_ifrn.ifrn_name);
+                       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1]
+                           = 0;
+                       ireq.u.mode = handle->md.oldmode;
+                       if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
+                               /*
+                                * Scientist, you've failed.
+                                */
+                               fprintf(stderr,
+                                   "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n"
+                                   "Please adjust manually.\n",
+                                   handle->md.device, strerror(errno));
+                       }
+
+                       /*
+                        * Now bring the interface back up if we brought
+                        * it down.
+                        */
+                       if (oldflags != 0) {
+                               ifr.ifr_flags = oldflags;
+                               if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
+                                       fprintf(stderr,
+                                           "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n"
+                                           "Please adjust manually.\n",
+                                           handle->md.device, strerror(errno));
+                               }
+                       }
+               }
+#endif /* IW_MODE_MONITOR */
+
+               /*
+                * Take this pcap out of the list of pcaps for which we
+                * have to take the interface out of some mode.
+                */
+               pcap_remove_from_pcaps_to_close(handle);
+       }
+
+       if (handle->md.mondevice != NULL) {
+               free(handle->md.mondevice);
+               handle->md.mondevice = NULL;
+       }
+       if (handle->md.device != NULL) {
+               free(handle->md.device);
+               handle->md.device = NULL;
+       }
+       pcap_cleanup_live_common(handle);
+}
+
+/*
+ *  Get a handle for a live capture from the given device. You can
+ *  pass NULL as device to get all packages (without link level
+ *  information of course). If you pass 1 as promisc the interface
+ *  will be set to promiscous mode (XXX: I think this usage should
+ *  be deprecated and functions be added to select that later allow
+ *  modification of that values -- Torsten).
+ */
+static int
+pcap_activate_linux(pcap_t *handle)
+{
+       const char      *device;
+       int             status = 0;
+
+       device = handle->opt.source;
+
+       handle->inject_op = pcap_inject_linux;
+       handle->setfilter_op = pcap_setfilter_linux;
+       handle->setdirection_op = pcap_setdirection_linux;
+       handle->set_datalink_op = NULL; /* can't change data link type */
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->cleanup_op = pcap_cleanup_linux;
+       handle->read_op = pcap_read_linux;
+       handle->stats_op = pcap_stats_linux;
+
+       /*
+        * The "any" device is a special device which causes us not
+        * to bind to a particular device and thus to look at all
+        * devices.
+        */
+       if (strcmp(device, "any") == 0) {
+               if (handle->opt.promisc) {
+                       handle->opt.promisc = 0;
+                       /* Just a warning. */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "Promiscuous mode not supported on the \"any\" device");
+                       status = PCAP_WARNING_PROMISC_NOTSUP;
+               }
+       }
+
+       handle->md.device       = strdup(device);
+       if (handle->md.device == NULL) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+                        pcap_strerror(errno) );
+               return PCAP_ERROR;
+       }
+       
+       /*
+        * If we're in promiscuous mode, then we probably want 
+        * to see when the interface drops packets too, so get an
+        * initial count from /proc/net/dev
+        */
+       if (handle->opt.promisc)
+               handle->md.proc_dropped = linux_if_drops(handle->md.device);
+
+       /*
+        * Current Linux kernels use the protocol family PF_PACKET to
+        * allow direct access to all packets on the network while
+        * older kernels had a special socket type SOCK_PACKET to
+        * implement this feature.
+        * While this old implementation is kind of obsolete we need
+        * to be compatible with older kernels for a while so we are
+        * trying both methods with the newer method preferred.
+        */
+       status = activate_new(handle);
+       if (status < 0) {
+               /*
+                * Fatal error with the new way; just fail.
+                * status has the error return; if it's PCAP_ERROR,
+                * handle->errbuf has been set appropriately.
+                */
+               goto fail;
+       }
+       if (status == 1) {
+               /*
+                * Success.
+                * Try to use memory-mapped access.
+                */
+               switch (activate_mmap(handle, &status)) {
+
+               case 1:
+                       /*
+                        * We succeeded.  status has been
+                        * set to the status to return,
+                        * which might be 0, or might be
+                        * a PCAP_WARNING_ value.
+                        */
+                       return status;
+
+               case 0:
+                       /*
+                        * Kernel doesn't support it - just continue
+                        * with non-memory-mapped access.
+                        */
+                       break;
+
+               case -1:
+                       /*
+                        * We failed to set up to use it, or the kernel
+                        * supports it, but we failed to enable it.
+                        * status has been set to the error status to
+                        * return and, if it's PCAP_ERROR, handle->errbuf
+                        * contains the error message.
+                        */
+                       goto fail;
+               }
+       }
+       else if (status == 0) {
+               /* Non-fatal error; try old way */
+               if ((status = activate_old(handle)) != 1) {
+                       /*
+                        * Both methods to open the packet socket failed.
+                        * Tidy up and report our failure (handle->errbuf
+                        * is expected to be set by the functions above).
+                        */
+                       goto fail;
+               }
+       }
+
+       /*
+        * We set up the socket, but not with memory-mapped access.
+        */
+       status = 0;
+       if (handle->opt.buffer_size != 0) {
+               /*
+                * Set the socket buffer size to the specified value.
+                */
+               if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+                   &handle->opt.buffer_size,
+                   sizeof(handle->opt.buffer_size)) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                "SO_RCVBUF: %s", pcap_strerror(errno));
+                       status = PCAP_ERROR;
+                       goto fail;
+               }
+       }
+
+       /* Allocate the buffer */
+
+       handle->buffer   = malloc(handle->bufsize + handle->offset);
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "malloc: %s", pcap_strerror(errno));
+               status = PCAP_ERROR;
+               goto fail;
+       }
+
+       /*
+        * "handle->fd" is a socket, so "select()" and "poll()"
+        * should work on it.
+        */
+       handle->selectable_fd = handle->fd;
+
+       return status;
+
+fail:
+       pcap_cleanup_linux(handle);
+       return status;
+}
+
+/*
+ *  Read at most max_packets from the capture stream and call the callback
+ *  for each of them. Returns the number of packets handled or -1 if an
+ *  error occured.
+ */
+static int
+pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       /*
+        * Currently, on Linux only one packet is delivered per read,
+        * so we don't loop.
+        */
+       return pcap_read_packet(handle, callback, user);
+}
+
+/*
+ *  Read a packet from the socket calling the handler provided by
+ *  the user. Returns the number of packets received or -1 if an
+ *  error occured.
+ */
+static int
+pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
+{
+       u_char                  *bp;
+       int                     offset;
+#ifdef HAVE_PF_PACKET_SOCKETS
+       struct sockaddr_ll      from;
+       struct sll_header       *hdrp;
+#else
+       struct sockaddr         from;
+#endif
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+       struct iovec            iov;
+       struct msghdr           msg;
+       struct cmsghdr          *cmsg;
+       union {
+               struct cmsghdr  cmsg;
+               char            buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
+       } cmsg_buf;
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+       socklen_t               fromlen;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+       int                     packet_len, caplen;
+       struct pcap_pkthdr      pcap_header;
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+       /*
+        * If this is a cooked device, leave extra room for a
+        * fake packet header.
+        */
+       if (handle->md.cooked)
+               offset = SLL_HDR_LEN;
+       else
+               offset = 0;
+#else
+       /*
+        * This system doesn't have PF_PACKET sockets, so it doesn't
+        * support cooked devices.
+        */
+       offset = 0;
+#endif
+
+       /*
+        * Receive a single packet from the kernel.
+        * We ignore EINTR, as that might just be due to a signal
+        * being delivered - if the signal should interrupt the
+        * loop, the signal handler should call pcap_breakloop()
+        * to set handle->break_loop (we ignore it on other
+        * platforms as well).
+        * We also ignore ENETDOWN, so that we can continue to
+        * capture traffic if the interface goes down and comes
+        * back up again; comments in the kernel indicate that
+        * we'll just block waiting for packets if we try to
+        * receive from a socket that delivered ENETDOWN, and,
+        * if we're using a memory-mapped buffer, we won't even
+        * get notified of "network down" events.
+        */
+       bp = handle->buffer + handle->offset;
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+       msg.msg_name            = &from;
+       msg.msg_namelen         = sizeof(from);
+       msg.msg_iov             = &iov;
+       msg.msg_iovlen          = 1;
+       msg.msg_control         = &cmsg_buf;
+       msg.msg_controllen      = sizeof(cmsg_buf);
+       msg.msg_flags           = 0;
+
+       iov.iov_len             = handle->bufsize - offset;
+       iov.iov_base            = bp + offset;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+
+       do {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (handle->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that it has,
+                        * and return PCAP_ERROR_BREAK as an indication that
+                        * we were told to break out of the loop.
+                        */
+                       handle->break_loop = 0;
+                       return PCAP_ERROR_BREAK;
+               }
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+               packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+               fromlen = sizeof(from);
+               packet_len = recvfrom(
+                       handle->fd, bp + offset,
+                       handle->bufsize - offset, MSG_TRUNC,
+                       (struct sockaddr *) &from, &fromlen);
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+       } while (packet_len == -1 && errno == EINTR);
+
+       /* Check if an error occured */
+
+       if (packet_len == -1) {
+               switch (errno) {
+
+               case EAGAIN:
+                       return 0;       /* no packet there */
+
+               case ENETDOWN:
+                       /*
+                        * The device on which we're capturing went away.
+                        *
+                        * XXX - we should really return
+                        * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch()
+                        * etc. aren't defined to return that.
+                        */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "The interface went down");
+                       return PCAP_ERROR;
+
+               default:
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                "recvfrom: %s", pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+       }
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+       if (!handle->md.sock_packet) {
+               /*
+                * Unfortunately, there is a window between socket() and
+                * bind() where the kernel may queue packets from any
+                * interface.  If we're bound to a particular interface,
+                * discard packets not from that interface.
+                *
+                * (If socket filters are supported, we could do the
+                * same thing we do when changing the filter; however,
+                * that won't handle packet sockets without socket
+                * filter support, and it's a bit more complicated.
+                * It would save some instructions per packet, however.)
+                */
+               if (handle->md.ifindex != -1 &&
+                   from.sll_ifindex != handle->md.ifindex)
+                       return 0;
+
+               /*
+                * Do checks based on packet direction.
+                * We can only do this if we're using PF_PACKET; the
+                * address returned for SOCK_PACKET is a "sockaddr_pkt"
+                * which lacks the relevant packet type information.
+                */
+               if (from.sll_pkttype == PACKET_OUTGOING) {
+                       /*
+                        * Outgoing packet.
+                        * If this is from the loopback device, reject it;
+                        * we'll see the packet as an incoming packet as well,
+                        * and we don't want to see it twice.
+                        */
+                       if (from.sll_ifindex == handle->md.lo_ifindex)
+                               return 0;
+
+                       /*
+                        * If the user only wants incoming packets, reject it.
+                        */
+                       if (handle->direction == PCAP_D_IN)
+                               return 0;
+               } else {
+                       /*
+                        * Incoming packet.
+                        * If the user only wants outgoing packets, reject it.
+                        */
+                       if (handle->direction == PCAP_D_OUT)
+                               return 0;
+               }
+       }
+#endif
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+       /*
+        * If this is a cooked device, fill in the fake packet header.
+        */
+       if (handle->md.cooked) {
+               /*
+                * Add the length of the fake header to the length
+                * of packet data we read.
+                */
+               packet_len += SLL_HDR_LEN;
+
+               hdrp = (struct sll_header *)bp;
+               hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype);
+               hdrp->sll_hatype = htons(from.sll_hatype);
+               hdrp->sll_halen = htons(from.sll_halen);
+               memcpy(hdrp->sll_addr, from.sll_addr,
+                   (from.sll_halen > SLL_ADDRLEN) ?
+                     SLL_ADDRLEN :
+                     from.sll_halen);
+               hdrp->sll_protocol = from.sll_protocol;
+       }
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+       for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+               struct tpacket_auxdata *aux;
+               unsigned int len;
+               struct vlan_tag *tag;
+
+               if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
+                   cmsg->cmsg_level != SOL_PACKET ||
+                   cmsg->cmsg_type != PACKET_AUXDATA)
+                       continue;
+
+               aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
+               if (aux->tp_vlan_tci == 0)
+                       continue;
+
+               len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
+               if (len < 2 * ETH_ALEN)
+                       break;
+
+               bp -= VLAN_TAG_LEN;
+               memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);
+
+               tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
+               tag->vlan_tpid = htons(ETH_P_8021Q);
+               tag->vlan_tci = htons(aux->tp_vlan_tci);
+
+               packet_len += VLAN_TAG_LEN;
+       }
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* HAVE_PF_PACKET_SOCKETS */
+
+       /*
+        * XXX: According to the kernel source we should get the real
+        * packet len if calling recvfrom with MSG_TRUNC set. It does
+        * not seem to work here :(, but it is supported by this code
+        * anyway.
+        * To be honest the code RELIES on that feature so this is really
+        * broken with 2.2.x kernels.
+        * I spend a day to figure out what's going on and I found out
+        * that the following is happening:
+        *
+        * The packet comes from a random interface and the packet_rcv
+        * hook is called with a clone of the packet. That code inserts
+        * the packet into the receive queue of the packet socket.
+        * If a filter is attached to that socket that filter is run
+        * first - and there lies the problem. The default filter always
+        * cuts the packet at the snaplen:
+        *
+        * # tcpdump -d
+        * (000) ret      #68
+        *
+        * So the packet filter cuts down the packet. The recvfrom call
+        * says "hey, it's only 68 bytes, it fits into the buffer" with
+        * the result that we don't get the real packet length. This
+        * is valid at least until kernel 2.2.17pre6.
+        *
+        * We currently handle this by making a copy of the filter
+        * program, fixing all "ret" instructions with non-zero
+        * operands to have an operand of 65535 so that the filter
+        * doesn't truncate the packet, and supplying that modified
+        * filter to the kernel.
+        */
+
+       caplen = packet_len;
+       if (caplen > handle->snapshot)
+               caplen = handle->snapshot;
+
+       /* Run the packet filter if not using kernel filter */
+       if (!handle->md.use_bpf && handle->fcode.bf_insns) {
+               if (bpf_filter(handle->fcode.bf_insns, bp,
+                               packet_len, caplen) == 0)
+               {
+                       /* rejected by filter */
+                       return 0;
+               }
+       }
+
+       /* Fill in our own header data */
+
+       if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "SIOCGSTAMP: %s", pcap_strerror(errno));
+               return PCAP_ERROR;
+       }
+       pcap_header.caplen      = caplen;
+       pcap_header.len         = packet_len;
+
+       /*
+        * Count the packet.
+        *
+        * Arguably, we should count them before we check the filter,
+        * as on many other platforms "ps_recv" counts packets
+        * handed to the filter rather than packets that passed
+        * the filter, but if filtering is done in the kernel, we
+        * can't get a count of packets that passed the filter,
+        * and that would mean the meaning of "ps_recv" wouldn't
+        * be the same on all Linux systems.
+        *
+        * XXX - it's not the same on all systems in any case;
+        * ideally, we should have a "get the statistics" call
+        * that supplies more counts and indicates which of them
+        * it supplies, so that we supply a count of packets
+        * handed to the filter only on platforms where that
+        * information is available.
+        *
+        * We count them here even if we can get the packet count
+        * from the kernel, as we can only determine at run time
+        * whether we'll be able to get it from the kernel (if
+        * HAVE_TPACKET_STATS isn't defined, we can't get it from
+        * the kernel, but if it is defined, the library might
+        * have been built with a 2.4 or later kernel, but we
+        * might be running on a 2.2[.x] kernel without Alexey
+        * Kuznetzov's turbopacket patches, and thus the kernel
+        * might not be able to supply those statistics).  We
+        * could, I guess, try, when opening the socket, to get
+        * the statistics, and if we can not increment the count
+        * here, but it's not clear that always incrementing
+        * the count is more expensive than always testing a flag
+        * in memory.
+        *
+        * We keep the count in "md.packets_read", and use that for
+        * "ps_recv" if we can't get the statistics from the kernel.
+        * We do that because, if we *can* get the statistics from
+        * the kernel, we use "md.stat.ps_recv" and "md.stat.ps_drop"
+        * as running counts, as reading the statistics from the
+        * kernel resets the kernel statistics, and if we directly
+        * increment "md.stat.ps_recv" here, that means it will
+        * count packets *twice* on systems where we can get kernel
+        * statistics - once here, and once in pcap_stats_linux().
+        */
+       handle->md.packets_read++;
+
+       /* Call the user supplied callback function */
+       callback(userdata, &pcap_header, bp);
+
+       return 1;
+}
+
+static int
+pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       int ret;
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+       if (!handle->md.sock_packet) {
+               /* PF_PACKET socket */
+               if (handle->md.ifindex == -1) {
+                       /*
+                        * We don't support sending on the "any" device.
+                        */
+                       strlcpy(handle->errbuf,
+                           "Sending packets isn't supported on the \"any\" device",
+                           PCAP_ERRBUF_SIZE);
+                       return (-1);
+               }
+
+               if (handle->md.cooked) {
+                       /*
+                        * We don't support sending on the "any" device.
+                        *
+                        * XXX - how do you send on a bound cooked-mode
+                        * socket?
+                        * Is a "sendto()" required there?
+                        */
+                       strlcpy(handle->errbuf,
+                           "Sending packets isn't supported in cooked mode",
+                           PCAP_ERRBUF_SIZE);
+                       return (-1);
+               }
+       }
+#endif
+
+       ret = send(handle->fd, buf, size, 0);
+       if (ret == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (ret);
+}                           
+
+/*
+ *  Get the statistics for the given packet capture handle.
+ *  Reports the number of dropped packets iff the kernel supports
+ *  the PACKET_STATISTICS "getsockopt()" argument (2.4 and later
+ *  kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket
+ *  patches); otherwise, that information isn't available, and we lie
+ *  and report 0 as the count of dropped packets.
+ */
+static int
+pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+#ifdef HAVE_TPACKET_STATS
+       struct tpacket_stats kstats;
+       socklen_t len = sizeof (struct tpacket_stats);
+#endif
+
+       long if_dropped = 0;
+       
+       /* 
+        *      To fill in ps_ifdrop, we parse /proc/net/dev for the number
+        */
+       if (handle->opt.promisc)
+       {
+               if_dropped = handle->md.proc_dropped;
+               handle->md.proc_dropped = linux_if_drops(handle->md.device);
+               handle->md.stat.ps_ifdrop += (handle->md.proc_dropped - if_dropped);
+       }
+
+#ifdef HAVE_TPACKET_STATS
+       /*
+        * Try to get the packet counts from the kernel.
+        */
+       if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
+                       &kstats, &len) > -1) {
+               /*
+                * On systems where the PACKET_STATISTICS "getsockopt()"
+                * argument is supported on PF_PACKET sockets:
+                *
+                *      "ps_recv" counts only packets that *passed* the
+                *      filter, not packets that didn't pass the filter.
+                *      This includes packets later dropped because we
+                *      ran out of buffer space.
+                *
+                *      "ps_drop" counts packets dropped because we ran
+                *      out of buffer space.  It doesn't count packets
+                *      dropped by the interface driver.  It counts only
+                *      packets that passed the filter.
+                *
+                *      See above for ps_ifdrop. 
+                *
+                *      Both statistics include packets not yet read from
+                *      the kernel by libpcap, and thus not yet seen by
+                *      the application.
+                *
+                * In "linux/net/packet/af_packet.c", at least in the
+                * 2.4.9 kernel, "tp_packets" is incremented for every
+                * packet that passes the packet filter *and* is
+                * successfully queued on the socket; "tp_drops" is
+                * incremented for every packet dropped because there's
+                * not enough free space in the socket buffer.
+                *
+                * When the statistics are returned for a PACKET_STATISTICS
+                * "getsockopt()" call, "tp_drops" is added to "tp_packets",
+                * so that "tp_packets" counts all packets handed to
+                * the PF_PACKET socket, including packets dropped because
+                * there wasn't room on the socket buffer - but not
+                * including packets that didn't pass the filter.
+                *
+                * In the BSD BPF, the count of received packets is
+                * incremented for every packet handed to BPF, regardless
+                * of whether it passed the filter.
+                *
+                * We can't make "pcap_stats()" work the same on both
+                * platforms, but the best approximation is to return
+                * "tp_packets" as the count of packets and "tp_drops"
+                * as the count of drops.
+                *
+                * Keep a running total because each call to 
+                *    getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
+                * resets the counters to zero.
+                */
+               handle->md.stat.ps_recv += kstats.tp_packets;
+               handle->md.stat.ps_drop += kstats.tp_drops;
+               *stats = handle->md.stat;
+               return 0;
+       }
+       else
+       {
+               /*
+                * If the error was EOPNOTSUPP, fall through, so that
+                * if you build the library on a system with
+                * "struct tpacket_stats" and run it on a system
+                * that doesn't, it works as it does if the library
+                * is built on a system without "struct tpacket_stats".
+                */
+               if (errno != EOPNOTSUPP) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "pcap_stats: %s", pcap_strerror(errno));
+                       return -1;
+               }
+       }
+#endif
+       /*
+        * On systems where the PACKET_STATISTICS "getsockopt()" argument
+        * is not supported on PF_PACKET sockets:
+        *
+        *      "ps_recv" counts only packets that *passed* the filter,
+        *      not packets that didn't pass the filter.  It does not
+        *      count packets dropped because we ran out of buffer
+        *      space.
+        *
+        *      "ps_drop" is not supported.
+        *
+        *      "ps_ifdrop" is supported. It will return the number
+        *      of drops the interface reports in /proc/net/dev,
+        *      if that is available.
+        *
+        *      "ps_recv" doesn't include packets not yet read from
+        *      the kernel by libpcap.
+        *
+        * We maintain the count of packets processed by libpcap in
+        * "md.packets_read", for reasons described in the comment
+        * at the end of pcap_read_packet().  We have no idea how many
+        * packets were dropped by the kernel buffers -- but we know 
+        * how many the interface dropped, so we can return that.
+        */
+        
+       stats->ps_recv = handle->md.packets_read;
+       stats->ps_drop = 0;
+       stats->ps_ifdrop = handle->md.stat.ps_ifdrop;
+       return 0;
+}
+
+/*
+ * Get from "/sys/class/net" all interfaces listed there; if they're
+ * already in the list of interfaces we have, that won't add another
+ * instance, but if they're not, that'll add them.
+ *
+ * We don't bother getting any addresses for them; it appears you can't
+ * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
+ * although some other types of addresses can be fetched with SIOCGIFADDR,
+ * we don't bother with them for now.
+ *
+ * We also don't fail if we couldn't open "/sys/class/net"; we just leave
+ * the list of interfaces as is, and return 0, so that we can try
+ * scanning /proc/net/dev.
+ */
+static int
+scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
+{
+       DIR *sys_class_net_d;
+       int fd;
+       struct dirent *ent;
+       char *p;
+       char name[512]; /* XXX - pick a size */
+       char *q, *saveq;
+       struct ifreq ifrflags;
+       int ret = 1;
+
+       sys_class_net_d = opendir("/sys/class/net");
+       if (sys_class_net_d == NULL) {
+               /*
+                * Don't fail if it doesn't exist at all.
+                */
+               if (errno == ENOENT)
+                       return (0);
+
+               /*
+                * Fail if we got some other error.
+                */
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't open /sys/class/net: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * Create a socket from which to fetch interface information.
+        */
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               (void)closedir(sys_class_net_d);
+               return (-1);
+       }
+
+       for (;;) {
+               errno = 0;
+               ent = readdir(sys_class_net_d);
+               if (ent == NULL) {
+                       /*
+                        * Error or EOF; if errno != 0, it's an error.
+                        */
+                       break;
+               }
+
+               /*
+                * Ignore directories (".", "..", and any subdirectories).
+                */
+               if (ent->d_type == DT_DIR)
+                       continue;
+
+               /*
+                * Get the interface name.
+                */
+               p = &ent->d_name[0];
+               q = &name[0];
+               while (*p != '\0' && isascii(*p) && !isspace(*p)) {
+                       if (*p == ':') {
+                               /*
+                                * This could be the separator between a
+                                * name and an alias number, or it could be
+                                * the separator between a name with no
+                                * alias number and the next field.
+                                *
+                                * If there's a colon after digits, it
+                                * separates the name and the alias number,
+                                * otherwise it separates the name and the
+                                * next field.
+                                */
+                               saveq = q;
+                               while (isascii(*p) && isdigit(*p))
+                                       *q++ = *p++;
+                               if (*p != ':') {
+                                       /*
+                                        * That was the next field,
+                                        * not the alias number.
+                                        */
+                                       q = saveq;
+                               }
+                               break;
+                       } else
+                               *q++ = *p++;
+               }
+               *q = '\0';
+
+               /*
+                * Get the flags for this interface, and skip it if
+                * it's not up.
+                */
+               strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+                       if (errno == ENXIO || errno == ENODEV)
+                               continue;
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGIFFLAGS: %.*s: %s",
+                           (int)sizeof(ifrflags.ifr_name),
+                           ifrflags.ifr_name,
+                           pcap_strerror(errno));
+                       ret = -1;
+                       break;
+               }
+               if (!(ifrflags.ifr_flags & IFF_UP))
+                       continue;
+
+               /*
+                * Add an entry for this interface, with no addresses.
+                */
+               if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
+                   errbuf) == -1) {
+                       /*
+                        * Failure.
+                        */
+                       ret = -1;
+                       break;
+               }
+       }
+       if (ret != -1) {
+               /*
+                * Well, we didn't fail for any other reason; did we
+                * fail due to an error reading the directory?
+                */
+               if (errno != 0) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "Error reading /sys/class/net: %s",
+                           pcap_strerror(errno));
+                       ret = -1;
+               }
+       }
+
+       (void)close(fd);
+       (void)closedir(sys_class_net_d);
+       return (ret);
+}
+
+/*
+ * Get from "/proc/net/dev" all interfaces listed there; if they're
+ * already in the list of interfaces we have, that won't add another
+ * instance, but if they're not, that'll add them.
+ *
+ * See comments from scan_sys_class_net().
+ */
+static int
+scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
+{
+       FILE *proc_net_f;
+       int fd;
+       char linebuf[512];
+       int linenum;
+       char *p;
+       char name[512]; /* XXX - pick a size */
+       char *q, *saveq;
+       struct ifreq ifrflags;
+       int ret = 0;
+
+       proc_net_f = fopen("/proc/net/dev", "r");
+       if (proc_net_f == NULL) {
+               /*
+                * Don't fail if it doesn't exist at all.
+                */
+               if (errno == ENOENT)
+                       return (0);
+
+               /*
+                * Fail if we got some other error.
+                */
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't open /proc/net/dev: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * Create a socket from which to fetch interface information.
+        */
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               (void)fclose(proc_net_f);
+               return (-1);
+       }
+
+       for (linenum = 1;
+           fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
+               /*
+                * Skip the first two lines - they're headers.
+                */
+               if (linenum <= 2)
+                       continue;
+
+               p = &linebuf[0];
+
+               /*
+                * Skip leading white space.
+                */
+               while (*p != '\0' && isascii(*p) && isspace(*p))
+                       p++;
+               if (*p == '\0' || *p == '\n')
+                       continue;       /* blank line */
+
+               /*
+                * Get the interface name.
+                */
+               q = &name[0];
+               while (*p != '\0' && isascii(*p) && !isspace(*p)) {
+                       if (*p == ':') {
+                               /*
+                                * This could be the separator between a
+                                * name and an alias number, or it could be
+                                * the separator between a name with no
+                                * alias number and the next field.
+                                *
+                                * If there's a colon after digits, it
+                                * separates the name and the alias number,
+                                * otherwise it separates the name and the
+                                * next field.
+                                */
+                               saveq = q;
+                               while (isascii(*p) && isdigit(*p))
+                                       *q++ = *p++;
+                               if (*p != ':') {
+                                       /*
+                                        * That was the next field,
+                                        * not the alias number.
+                                        */
+                                       q = saveq;
+                               }
+                               break;
+                       } else
+                               *q++ = *p++;
+               }
+               *q = '\0';
+
+               /*
+                * Get the flags for this interface, and skip it if
+                * it's not up.
+                */
+               strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+                       if (errno == ENXIO)
+                               continue;
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "SIOCGIFFLAGS: %.*s: %s",
+                           (int)sizeof(ifrflags.ifr_name),
+                           ifrflags.ifr_name,
+                           pcap_strerror(errno));
+                       ret = -1;
+                       break;
+               }
+               if (!(ifrflags.ifr_flags & IFF_UP))
+                       continue;
+
+               /*
+                * Add an entry for this interface, with no addresses.
+                */
+               if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
+                   errbuf) == -1) {
+                       /*
+                        * Failure.
+                        */
+                       ret = -1;
+                       break;
+               }
+       }
+       if (ret != -1) {
+               /*
+                * Well, we didn't fail for any other reason; did we
+                * fail due to an error reading the file?
+                */
+               if (ferror(proc_net_f)) {
+                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "Error reading /proc/net/dev: %s",
+                           pcap_strerror(errno));
+                       ret = -1;
+               }
+       }
+
+       (void)close(fd);
+       (void)fclose(proc_net_f);
+       return (ret);
+}
+
+/*
+ * Description string for the "any" device.
+ */
+static const char any_descr[] = "Pseudo-device that captures on all interfaces";
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       int ret;
+
+       /*
+        * Read "/sys/class/net", and add to the list of interfaces all
+        * interfaces listed there that we don't already have, because,
+        * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
+        * and even getifaddrs() won't return information about
+        * interfaces with no addresses, so you need to read "/sys/class/net"
+        * to get the names of the rest of the interfaces.
+        */
+       ret = scan_sys_class_net(alldevsp, errbuf);
+       if (ret == -1)
+               return (-1);    /* failed */
+       if (ret == 0) {
+               /*
+                * No /sys/class/net; try reading /proc/net/dev instead.
+                */
+               if (scan_proc_net_dev(alldevsp, errbuf) == -1)
+                       return (-1);
+       }
+
+       /*
+        * Add the "any" device.
+        */
+       if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0)
+               return (-1);
+
+#ifdef HAVE_DAG_API
+       /*
+        * Add DAG devices.
+        */
+       if (dag_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+       /*
+        * Add Septel devices.
+        */
+       if (septel_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef HAVE_SNF_API
+       if (snf_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif /* HAVE_SNF_API */
+
+#ifdef PCAP_SUPPORT_BT
+       /*
+        * Add Bluetooth devices.
+        */
+       if (bt_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif
+
+#ifdef PCAP_SUPPORT_USB
+       /*
+        * Add USB devices.
+        */
+       if (usb_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif
+
+#ifdef PCAP_SUPPORT_NETFILTER
+       /*
+        * Add netfilter devices.
+        */
+       if (netfilter_platform_finddevs(alldevsp, errbuf) < 0)
+               return (-1);
+#endif
+
+#if PCAP_SUPPORT_CANUSB
+  if (canusb_platform_finddevs(alldevsp, errbuf) < 0)
+    return (-1);
+#endif
+
+       return (0);
+}
+
+/*
+ *  Attach the given BPF code to the packet capture device.
+ */
+static int
+pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
+    int is_mmapped)
+{
+#ifdef SO_ATTACH_FILTER
+       struct sock_fprog       fcode;
+       int                     can_filter_in_kernel;
+       int                     err = 0;
+#endif
+
+       if (!handle)
+               return -1;
+       if (!filter) {
+               strncpy(handle->errbuf, "setfilter: No filter specified",
+                       PCAP_ERRBUF_SIZE);
+               return -1;
+       }
+
+       /* Make our private copy of the filter */
+
+       if (install_bpf_program(handle, filter) < 0)
+               /* install_bpf_program() filled in errbuf */
+               return -1;
+
+       /*
+        * Run user level packet filter by default. Will be overriden if
+        * installing a kernel filter succeeds.
+        */
+       handle->md.use_bpf = 0;
+
+       /* Install kernel level filter if possible */
+
+#ifdef SO_ATTACH_FILTER
+#ifdef USHRT_MAX
+       if (handle->fcode.bf_len > USHRT_MAX) {
+               /*
+                * fcode.len is an unsigned short for current kernel.
+                * I have yet to see BPF-Code with that much
+                * instructions but still it is possible. So for the
+                * sake of correctness I added this check.
+                */
+               fprintf(stderr, "Warning: Filter too complex for kernel\n");
+               fcode.len = 0;
+               fcode.filter = NULL;
+               can_filter_in_kernel = 0;
+       } else
+#endif /* USHRT_MAX */
+       {
+               /*
+                * Oh joy, the Linux kernel uses struct sock_fprog instead
+                * of struct bpf_program and of course the length field is
+                * of different size. Pointed out by Sebastian
+                *
+                * Oh, and we also need to fix it up so that all "ret"
+                * instructions with non-zero operands have 65535 as the
+                * operand if we're not capturing in memory-mapped modee,
+                * and so that, if we're in cooked mode, all memory-reference
+                * instructions use special magic offsets in references to
+                * the link-layer header and assume that the link-layer
+                * payload begins at 0; "fix_program()" will do that.
+                */
+               switch (fix_program(handle, &fcode, is_mmapped)) {
+
+               case -1:
+               default:
+                       /*
+                        * Fatal error; just quit.
+                        * (The "default" case shouldn't happen; we
+                        * return -1 for that reason.)
+                        */
+                       return -1;
+
+               case 0:
+                       /*
+                        * The program performed checks that we can't make
+                        * work in the kernel.
+                        */
+                       can_filter_in_kernel = 0;
+                       break;
+
+               case 1:
+                       /*
+                        * We have a filter that'll work in the kernel.
+                        */
+                       can_filter_in_kernel = 1;
+                       break;
+               }
+       }
+
+       /*
+        * NOTE: at this point, we've set both the "len" and "filter"
+        * fields of "fcode".  As of the 2.6.32.4 kernel, at least,
+        * those are the only members of the "sock_fprog" structure,
+        * so we initialize every member of that structure.
+        *
+        * If there is anything in "fcode" that is not initialized,
+        * it is either a field added in a later kernel, or it's
+        * padding.
+        *
+        * If a new field is added, this code needs to be updated
+        * to set it correctly.
+        *
+        * If there are no other fields, then:
+        *
+        *      if the Linux kernel looks at the padding, it's
+        *      buggy;
+        *
+        *      if the Linux kernel doesn't look at the padding,
+        *      then if some tool complains that we're passing
+        *      uninitialized data to the kernel, then the tool
+        *      is buggy and needs to understand that it's just
+        *      padding.
+        */
+       if (can_filter_in_kernel) {
+               if ((err = set_kernel_filter(handle, &fcode)) == 0)
+               {
+                       /* Installation succeded - using kernel filter. */
+                       handle->md.use_bpf = 1;
+               }
+               else if (err == -1)     /* Non-fatal error */
+               {
+                       /*
+                        * Print a warning if we weren't able to install
+                        * the filter for a reason other than "this kernel
+                        * isn't configured to support socket filters.
+                        */
+                       if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
+                               fprintf(stderr,
+                                   "Warning: Kernel filter failed: %s\n",
+                                       pcap_strerror(errno));
+                       }
+               }
+       }
+
+       /*
+        * If we're not using the kernel filter, get rid of any kernel
+        * filter that might've been there before, e.g. because the
+        * previous filter could work in the kernel, or because some other
+        * code attached a filter to the socket by some means other than
+        * calling "pcap_setfilter()".  Otherwise, the kernel filter may
+        * filter out packets that would pass the new userland filter.
+        */
+       if (!handle->md.use_bpf)
+               reset_kernel_filter(handle);
+
+       /*
+        * Free up the copy of the filter that was made by "fix_program()".
+        */
+       if (fcode.filter != NULL)
+               free(fcode.filter);
+
+       if (err == -2)
+               /* Fatal error */
+               return -1;
+#endif /* SO_ATTACH_FILTER */
+
+       return 0;
+}
+
+static int
+pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
+{
+       return pcap_setfilter_linux_common(handle, filter, 0);
+}
+
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+static int
+pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
+{
+#ifdef HAVE_PF_PACKET_SOCKETS
+       if (!handle->md.sock_packet) {
+               handle->direction = d;
+               return 0;
+       }
+#endif
+       /*
+        * We're not using PF_PACKET sockets, so we can't determine
+        * the direction of the packet.
+        */
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "Setting direction is not supported on SOCK_PACKET sockets");
+       return -1;
+}
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+/*
+ * Map the PACKET_ value to a LINUX_SLL_ value; we
+ * want the same numerical value to be used in
+ * the link-layer header even if the numerical values
+ * for the PACKET_ #defines change, so that programs
+ * that look at the packet type field will always be
+ * able to handle DLT_LINUX_SLL captures.
+ */
+static short int
+map_packet_type_to_sll_type(short int sll_pkttype)
+{
+       switch (sll_pkttype) {
+
+       case PACKET_HOST:
+               return htons(LINUX_SLL_HOST);
+
+       case PACKET_BROADCAST:
+               return htons(LINUX_SLL_BROADCAST);
+
+       case PACKET_MULTICAST:
+               return  htons(LINUX_SLL_MULTICAST);
+
+       case PACKET_OTHERHOST:
+               return htons(LINUX_SLL_OTHERHOST);
+
+       case PACKET_OUTGOING:
+               return htons(LINUX_SLL_OUTGOING);
+
+       default:
+               return -1;
+       }
+}
+#endif
+
+/*
+ *  Linux uses the ARP hardware type to identify the type of an
+ *  interface. pcap uses the DLT_xxx constants for this. This
+ *  function takes a pointer to a "pcap_t", and an ARPHRD_xxx
+ *  constant, as arguments, and sets "handle->linktype" to the
+ *  appropriate DLT_XXX constant and sets "handle->offset" to
+ *  the appropriate value (to make "handle->offset" plus link-layer
+ *  header length be a multiple of 4, so that the link-layer payload
+ *  will be aligned on a 4-byte boundary when capturing packets).
+ *  (If the offset isn't set here, it'll be 0; add code as appropriate
+ *  for cases where it shouldn't be 0.)
+ *
+ *  If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture
+ *  in cooked mode; otherwise, we can't use cooked mode, so we have
+ *  to pick some type that works in raw mode, or fail.
+ *
+ *  Sets the link type to -1 if unable to map the type.
+ */
+static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
+{
+       switch (arptype) {
+
+       case ARPHRD_ETHER:
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                *
+                * XXX - are there any sorts of "fake Ethernet" that have
+                * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
+                * a Cisco CMTS won't put traffic onto it or get traffic
+                * bridged onto it?  ISDN is handled in "activate_new()",
+                * as we fall back on cooked mode there; are there any
+                * others?
+                */
+               handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (handle->dlt_list != NULL) {
+                       handle->dlt_list[0] = DLT_EN10MB;
+                       handle->dlt_list[1] = DLT_DOCSIS;
+                       handle->dlt_count = 2;
+               }
+               /* FALLTHROUGH */
+
+       case ARPHRD_METRICOM:
+       case ARPHRD_LOOPBACK:
+               handle->linktype = DLT_EN10MB;
+               handle->offset = 2;
+               break;
+
+       case ARPHRD_EETHER:
+               handle->linktype = DLT_EN3MB;
+               break;
+
+       case ARPHRD_AX25:
+               handle->linktype = DLT_AX25_KISS;
+               break;
+
+       case ARPHRD_PRONET:
+               handle->linktype = DLT_PRONET;
+               break;
+
+       case ARPHRD_CHAOS:
+               handle->linktype = DLT_CHAOS;
+               break;
+#ifndef ARPHRD_CAN
+#define ARPHRD_CAN 280
+#endif
+       case ARPHRD_CAN:
+               handle->linktype = DLT_CAN_SOCKETCAN;
+               break;
+
+#ifndef ARPHRD_IEEE802_TR
+#define ARPHRD_IEEE802_TR 800  /* From Linux 2.4 */
+#endif
+       case ARPHRD_IEEE802_TR:
+       case ARPHRD_IEEE802:
+               handle->linktype = DLT_IEEE802;
+               handle->offset = 2;
+               break;
+
+       case ARPHRD_ARCNET:
+               handle->linktype = DLT_ARCNET_LINUX;
+               break;
+
+#ifndef ARPHRD_FDDI    /* From Linux 2.2.13 */
+#define ARPHRD_FDDI    774
+#endif
+       case ARPHRD_FDDI:
+               handle->linktype = DLT_FDDI;
+               handle->offset = 3;
+               break;
+
+#ifndef ARPHRD_ATM  /* FIXME: How to #include this? */
+#define ARPHRD_ATM 19
+#endif
+       case ARPHRD_ATM:
+               /*
+                * The Classical IP implementation in ATM for Linux
+                * supports both what RFC 1483 calls "LLC Encapsulation",
+                * in which each packet has an LLC header, possibly
+                * with a SNAP header as well, prepended to it, and
+                * what RFC 1483 calls "VC Based Multiplexing", in which
+                * different virtual circuits carry different network
+                * layer protocols, and no header is prepended to packets.
+                *
+                * They both have an ARPHRD_ type of ARPHRD_ATM, so
+                * you can't use the ARPHRD_ type to find out whether
+                * captured packets will have an LLC header, and,
+                * while there's a socket ioctl to *set* the encapsulation
+                * type, there's no ioctl to *get* the encapsulation type.
+                *
+                * This means that
+                *
+                *      programs that dissect Linux Classical IP frames
+                *      would have to check for an LLC header and,
+                *      depending on whether they see one or not, dissect
+                *      the frame as LLC-encapsulated or as raw IP (I
+                *      don't know whether there's any traffic other than
+                *      IP that would show up on the socket, or whether
+                *      there's any support for IPv6 in the Linux
+                *      Classical IP code);
+                *
+                *      filter expressions would have to compile into
+                *      code that checks for an LLC header and does
+                *      the right thing.
+                *
+                * Both of those are a nuisance - and, at least on systems
+                * that support PF_PACKET sockets, we don't have to put
+                * up with those nuisances; instead, we can just capture
+                * in cooked mode.  That's what we'll do, if we can.
+                * Otherwise, we'll just fail.
+                */
+               if (cooked_ok)
+                       handle->linktype = DLT_LINUX_SLL;
+               else
+                       handle->linktype = -1;
+               break;
+
+#ifndef ARPHRD_IEEE80211  /* From Linux 2.4.6 */
+#define ARPHRD_IEEE80211 801
+#endif
+       case ARPHRD_IEEE80211:
+               handle->linktype = DLT_IEEE802_11;
+               break;
+
+#ifndef ARPHRD_IEEE80211_PRISM  /* From Linux 2.4.18 */
+#define ARPHRD_IEEE80211_PRISM 802
+#endif
+       case ARPHRD_IEEE80211_PRISM:
+               handle->linktype = DLT_PRISM_HEADER;
+               break;
+
+#ifndef ARPHRD_IEEE80211_RADIOTAP /* new */
+#define ARPHRD_IEEE80211_RADIOTAP 803
+#endif
+       case ARPHRD_IEEE80211_RADIOTAP:
+               handle->linktype = DLT_IEEE802_11_RADIO;
+               break;
+
+       case ARPHRD_PPP:
+               /*
+                * Some PPP code in the kernel supplies no link-layer
+                * header whatsoever to PF_PACKET sockets; other PPP
+                * code supplies PPP link-layer headers ("syncppp.c");
+                * some PPP code might supply random link-layer
+                * headers (PPP over ISDN - there's code in Ethereal,
+                * for example, to cope with PPP-over-ISDN captures
+                * with which the Ethereal developers have had to cope,
+                * heuristically trying to determine which of the
+                * oddball link-layer headers particular packets have).
+                *
+                * As such, we just punt, and run all PPP interfaces
+                * in cooked mode, if we can; otherwise, we just treat
+                * it as DLT_RAW, for now - if somebody needs to capture,
+                * on a 2.0[.x] kernel, on PPP devices that supply a
+                * link-layer header, they'll have to add code here to
+                * map to the appropriate DLT_ type (possibly adding a
+                * new DLT_ type, if necessary).
+                */
+               if (cooked_ok)
+                       handle->linktype = DLT_LINUX_SLL;
+               else {
+                       /*
+                        * XXX - handle ISDN types here?  We can't fall
+                        * back on cooked sockets, so we'd have to
+                        * figure out from the device name what type of
+                        * link-layer encapsulation it's using, and map
+                        * that to an appropriate DLT_ value, meaning
+                        * we'd map "isdnN" devices to DLT_RAW (they
+                        * supply raw IP packets with no link-layer
+                        * header) and "isdY" devices to a new DLT_I4L_IP
+                        * type that has only an Ethernet packet type as
+                        * a link-layer header.
+                        *
+                        * But sometimes we seem to get random crap
+                        * in the link-layer header when capturing on
+                        * ISDN devices....
+                        */
+                       handle->linktype = DLT_RAW;
+               }
+               break;
+
+#ifndef ARPHRD_CISCO
+#define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */
+#endif
+       case ARPHRD_CISCO:
+               handle->linktype = DLT_C_HDLC;
+               break;
+
+       /* Not sure if this is correct for all tunnels, but it
+        * works for CIPE */
+       case ARPHRD_TUNNEL:
+#ifndef ARPHRD_SIT
+#define ARPHRD_SIT 776 /* From Linux 2.2.13 */
+#endif
+       case ARPHRD_SIT:
+       case ARPHRD_CSLIP:
+       case ARPHRD_SLIP6:
+       case ARPHRD_CSLIP6:
+       case ARPHRD_ADAPT:
+       case ARPHRD_SLIP:
+#ifndef ARPHRD_RAWHDLC
+#define ARPHRD_RAWHDLC 518
+#endif
+       case ARPHRD_RAWHDLC:
+#ifndef ARPHRD_DLCI
+#define ARPHRD_DLCI 15
+#endif
+       case ARPHRD_DLCI:
+               /*
+                * XXX - should some of those be mapped to DLT_LINUX_SLL
+                * instead?  Should we just map all of them to DLT_LINUX_SLL?
+                */
+               handle->linktype = DLT_RAW;
+               break;
+
+#ifndef ARPHRD_FRAD
+#define ARPHRD_FRAD 770
+#endif
+       case ARPHRD_FRAD:
+               handle->linktype = DLT_FRELAY;
+               break;
+
+       case ARPHRD_LOCALTLK:
+               handle->linktype = DLT_LTALK;
+               break;
+
+#ifndef ARPHRD_FCPP
+#define ARPHRD_FCPP    784
+#endif
+       case ARPHRD_FCPP:
+#ifndef ARPHRD_FCAL
+#define ARPHRD_FCAL    785
+#endif
+       case ARPHRD_FCAL:
+#ifndef ARPHRD_FCPL
+#define ARPHRD_FCPL    786
+#endif
+       case ARPHRD_FCPL:
+#ifndef ARPHRD_FCFABRIC
+#define ARPHRD_FCFABRIC        787
+#endif
+       case ARPHRD_FCFABRIC:
+               /*
+                * We assume that those all mean RFC 2625 IP-over-
+                * Fibre Channel, with the RFC 2625 header at
+                * the beginning of the packet.
+                */
+               handle->linktype = DLT_IP_OVER_FC;
+               break;
+
+#ifndef ARPHRD_IRDA
+#define ARPHRD_IRDA    783
+#endif
+       case ARPHRD_IRDA:
+               /* Don't expect IP packet out of this interfaces... */
+               handle->linktype = DLT_LINUX_IRDA;
+               /* We need to save packet direction for IrDA decoding,
+                * so let's use "Linux-cooked" mode. Jean II */
+               //handle->md.cooked = 1;
+               break;
+
+       /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
+        * is needed, please report it to <daniele@orlandi.com> */
+#ifndef ARPHRD_LAPD
+#define ARPHRD_LAPD    8445
+#endif
+       case ARPHRD_LAPD:
+               /* Don't expect IP packet out of this interfaces... */
+               handle->linktype = DLT_LINUX_LAPD;
+               break;
+
+#ifndef ARPHRD_NONE
+#define ARPHRD_NONE    0xFFFE
+#endif
+       case ARPHRD_NONE:
+               /*
+                * No link-layer header; packets are just IP
+                * packets, so use DLT_RAW.
+                */
+               handle->linktype = DLT_RAW;
+               break;
+
+#ifndef ARPHRD_IEEE802154
+#define ARPHRD_IEEE802154      804
+#endif
+       case ARPHRD_IEEE802154:
+               handle->linktype =  DLT_IEEE802_15_4_NOFCS;
+               break;
+
+       default:
+               handle->linktype = -1;
+               break;
+       }
+}
+
+/* ===== Functions to interface to the newer kernels ================== */
+
+/*
+ * Try to open a packet socket using the new kernel PF_PACKET interface.
+ * Returns 1 on success, 0 on an error that means the new interface isn't
+ * present (so the old SOCK_PACKET interface should be tried), and a
+ * PCAP_ERROR_ value on an error that means that the old mechanism won't
+ * work either (so it shouldn't be tried).
+ */
+static int
+activate_new(pcap_t *handle)
+{
+#ifdef HAVE_PF_PACKET_SOCKETS
+       const char              *device = handle->opt.source;
+       int                     is_any_device = (strcmp(device, "any") == 0);
+       int                     sock_fd = -1, arptype;
+#ifdef HAVE_PACKET_AUXDATA
+       int                     val;
+#endif
+       int                     err = 0;
+       struct packet_mreq      mr;
+
+       /*
+        * Open a socket with protocol family packet. If the
+        * "any" device was specified, we open a SOCK_DGRAM
+        * socket for the cooked interface, otherwise we first
+        * try a SOCK_RAW socket for the raw interface.
+        */
+       sock_fd = is_any_device ?
+               socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
+               socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+
+       if (sock_fd == -1) {
+               if (errno == EINVAL || errno == EAFNOSUPPORT) {
+                       /*
+                        * We don't support PF_PACKET/SOCK_whatever
+                        * sockets; try the old mechanism.
+                        */
+                       return 0;
+               }
+
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+                        pcap_strerror(errno) );
+               if (errno == EPERM || errno == EACCES) {
+                       /*
+                        * You don't have permission to open the
+                        * socket.
+                        */
+                       return PCAP_ERROR_PERM_DENIED;
+               } else {
+                       /*
+                        * Other error.
+                        */
+                       return PCAP_ERROR;
+               }
+       }
+
+       /* It seems the kernel supports the new interface. */
+       handle->md.sock_packet = 0;
+
+       /*
+        * Get the interface index of the loopback device.
+        * If the attempt fails, don't fail, just set the
+        * "md.lo_ifindex" to -1.
+        *
+        * XXX - can there be more than one device that loops
+        * packets back, i.e. devices other than "lo"?  If so,
+        * we'd need to find them all, and have an array of
+        * indices for them, and check all of them in
+        * "pcap_read_packet()".
+        */
+       handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
+
+       /*
+        * Default value for offset to align link-layer payload
+        * on a 4-byte boundary.
+        */
+       handle->offset   = 0;
+
+       /*
+        * What kind of frames do we have to deal with? Fall back
+        * to cooked mode if we have an unknown interface type
+        * or a type we know doesn't work well in raw mode.
+        */
+       if (!is_any_device) {
+               /* Assume for now we don't need cooked mode. */
+               handle->md.cooked = 0;
+
+               if (handle->opt.rfmon) {
+                       /*
+                        * We were asked to turn on monitor mode.
+                        * Do so before we get the link-layer type,
+                        * because entering monitor mode could change
+                        * the link-layer type.
+                        */
+                       err = enter_rfmon_mode(handle, sock_fd, device);
+                       if (err < 0) {
+                               /* Hard failure */
+                               close(sock_fd);
+                               return err;
+                       }
+                       if (err == 0) {
+                               /*
+                                * Nothing worked for turning monitor mode
+                                * on.
+                                */
+                               close(sock_fd);
+                               return PCAP_ERROR_RFMON_NOTSUP;
+                       }
+
+                       /*
+                        * Either monitor mode has been turned on for
+                        * the device, or we've been given a different
+                        * device to open for monitor mode.  If we've
+                        * been given a different device, use it.
+                        */
+                       if (handle->md.mondevice != NULL)
+                               device = handle->md.mondevice;
+               }
+               arptype = iface_get_arptype(sock_fd, device, handle->errbuf);
+               if (arptype < 0) {
+                       close(sock_fd);
+                       return arptype;
+               }
+               map_arphrd_to_dlt(handle, arptype, 1);
+               if (handle->linktype == -1 ||
+                   handle->linktype == DLT_LINUX_SLL ||
+                   handle->linktype == DLT_LINUX_IRDA ||
+                   handle->linktype == DLT_LINUX_LAPD ||
+                   (handle->linktype == DLT_EN10MB &&
+                    (strncmp("isdn", device, 4) == 0 ||
+                     strncmp("isdY", device, 4) == 0))) {
+                       /*
+                        * Unknown interface type (-1), or a
+                        * device we explicitly chose to run
+                        * in cooked mode (e.g., PPP devices),
+                        * or an ISDN device (whose link-layer
+                        * type we can only determine by using
+                        * APIs that may be different on different
+                        * kernels) - reopen in cooked mode.
+                        */
+                       if (close(sock_fd) == -1) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                        "close: %s", pcap_strerror(errno));
+                               return PCAP_ERROR;
+                       }
+                       sock_fd = socket(PF_PACKET, SOCK_DGRAM,
+                           htons(ETH_P_ALL));
+                       if (sock_fd == -1) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                   "socket: %s", pcap_strerror(errno));
+                               if (errno == EPERM || errno == EACCES) {
+                                       /*
+                                        * You don't have permission to
+                                        * open the socket.
+                                        */
+                                       return PCAP_ERROR_PERM_DENIED;
+                               } else {
+                                       /*
+                                        * Other error.
+                                        */
+                                       return PCAP_ERROR;
+                               }
+                       }
+                       handle->md.cooked = 1;
+
+                       /*
+                        * Get rid of any link-layer type list
+                        * we allocated - this only supports cooked
+                        * capture.
+                        */
+                       if (handle->dlt_list != NULL) {
+                               free(handle->dlt_list);
+                               handle->dlt_list = NULL;
+                               handle->dlt_count = 0;
+                       }
+
+                       if (handle->linktype == -1) {
+                               /*
+                                * Warn that we're falling back on
+                                * cooked mode; we may want to
+                                * update "map_arphrd_to_dlt()"
+                                * to handle the new type.
+                                */
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "arptype %d not "
+                                       "supported by libpcap - "
+                                       "falling back to cooked "
+                                       "socket",
+                                       arptype);
+                       }
+
+                       /*
+                        * IrDA capture is not a real "cooked" capture,
+                        * it's IrLAP frames, not IP packets.  The
+                        * same applies to LAPD capture.
+                        */
+                       if (handle->linktype != DLT_LINUX_IRDA &&
+                           handle->linktype != DLT_LINUX_LAPD)
+                               handle->linktype = DLT_LINUX_SLL;
+               }
+
+               handle->md.ifindex = iface_get_id(sock_fd, device,
+                   handle->errbuf);
+               if (handle->md.ifindex == -1) {
+                       close(sock_fd);
+                       return PCAP_ERROR;
+               }
+
+               if ((err = iface_bind(sock_fd, handle->md.ifindex,
+                   handle->errbuf)) != 1) {
+                       close(sock_fd);
+                       if (err < 0)
+                               return err;
+                       else
+                               return 0;       /* try old mechanism */
+               }
+       } else {
+               /*
+                * The "any" device.
+                */
+               if (handle->opt.rfmon) {
+                       /*
+                        * It doesn't support monitor mode.
+                        */
+                       return PCAP_ERROR_RFMON_NOTSUP;
+               }
+
+               /*
+                * It uses cooked mode.
+                */
+               handle->md.cooked = 1;
+               handle->linktype = DLT_LINUX_SLL;
+
+               /*
+                * We're not bound to a device.
+                * For now, we're using this as an indication
+                * that we can't transmit; stop doing that only
+                * if we figure out how to transmit in cooked
+                * mode.
+                */
+               handle->md.ifindex = -1;
+       }
+
+       /*
+        * Select promiscuous mode on if "promisc" is set.
+        *
+        * Do not turn allmulti mode on if we don't select
+        * promiscuous mode - on some devices (e.g., Orinoco
+        * wireless interfaces), allmulti mode isn't supported
+        * and the driver implements it by turning promiscuous
+        * mode on, and that screws up the operation of the
+        * card as a normal networking interface, and on no
+        * other platform I know of does starting a non-
+        * promiscuous capture affect which multicast packets
+        * are received by the interface.
+        */
+
+       /*
+        * Hmm, how can we set promiscuous mode on all interfaces?
+        * I am not sure if that is possible at all.  For now, we
+        * silently ignore attempts to turn promiscuous mode on
+        * for the "any" device (so you don't have to explicitly
+        * disable it in programs such as tcpdump).
+        */
+
+       if (!is_any_device && handle->opt.promisc) {
+               memset(&mr, 0, sizeof(mr));
+               mr.mr_ifindex = handle->md.ifindex;
+               mr.mr_type    = PACKET_MR_PROMISC;
+               if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+                   &mr, sizeof(mr)) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "setsockopt: %s", pcap_strerror(errno));
+                       close(sock_fd);
+                       return PCAP_ERROR;
+               }
+       }
+
+       /* Enable auxillary data if supported and reserve room for
+        * reconstructing VLAN headers. */
+#ifdef HAVE_PACKET_AUXDATA
+       val = 1;
+       if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
+                      sizeof(val)) == -1 && errno != ENOPROTOOPT) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "setsockopt: %s", pcap_strerror(errno));
+               close(sock_fd);
+               return PCAP_ERROR;
+       }
+       handle->offset += VLAN_TAG_LEN;
+#endif /* HAVE_PACKET_AUXDATA */
+
+       /*
+        * This is a 2.2[.x] or later kernel (we know that
+        * because we're not using a SOCK_PACKET socket -
+        * PF_PACKET is supported only in 2.2 and later
+        * kernels).
+        *
+        * We can safely pass "recvfrom()" a byte count
+        * based on the snapshot length.
+        *
+        * If we're in cooked mode, make the snapshot length
+        * large enough to hold a "cooked mode" header plus
+        * 1 byte of packet data (so we don't pass a byte
+        * count of 0 to "recvfrom()").
+        */
+       if (handle->md.cooked) {
+               if (handle->snapshot < SLL_HDR_LEN + 1)
+                       handle->snapshot = SLL_HDR_LEN + 1;
+       }
+       handle->bufsize = handle->snapshot;
+
+       /* Save the socket FD in the pcap structure */
+       handle->fd = sock_fd;
+
+       return 1;
+#else
+       strncpy(ebuf,
+               "New packet capturing interface not supported by build "
+               "environment", PCAP_ERRBUF_SIZE);
+       return 0;
+#endif
+}
+
+#ifdef HAVE_PACKET_RING
+/*
+ * Attempt to activate with memory-mapped access.
+ *
+ * On success, returns 1, and sets *status to 0 if there are no warnings
+ * or to a PCAP_WARNING_ code if there is a warning.
+ *
+ * On failure due to lack of support for memory-mapped capture, returns
+ * 0.
+ *
+ * On error, returns -1, and sets *status to the appropriate error code;
+ * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
+ */
+static int 
+activate_mmap(pcap_t *handle, int *status)
+{
+       int ret;
+
+       /*
+        * Attempt to allocate a buffer to hold the contents of one
+        * packet, for use by the oneshot callback.
+        */
+       handle->md.oneshot_buffer = malloc(handle->snapshot);
+       if (handle->md.oneshot_buffer == NULL) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "can't allocate oneshot buffer: %s",
+                        pcap_strerror(errno));
+               *status = PCAP_ERROR;
+               return -1;
+       }
+
+       if (handle->opt.buffer_size == 0) {
+               /* by default request 2M for the ring buffer */
+               handle->opt.buffer_size = 2*1024*1024;
+       }
+       ret = prepare_tpacket_socket(handle);
+       if (ret == -1) {
+               free(handle->md.oneshot_buffer);
+               *status = PCAP_ERROR;
+               return ret;
+       }
+       ret = create_ring(handle, status);
+       if (ret == 0) {
+               /*
+                * We don't support memory-mapped capture; our caller
+                * will fall back on reading from the socket.
+                */
+               free(handle->md.oneshot_buffer);
+               return 0;
+       }
+       if (ret == -1) {
+               /*
+                * Error attempting to enable memory-mapped capture;
+                * fail.  create_ring() has set *status.
+                */
+               free(handle->md.oneshot_buffer);
+               return -1;
+       }
+
+       /*
+        * Success.  *status has been set either to 0 if there are no
+        * warnings or to a PCAP_WARNING_ value if there is a warning.
+        *
+        * Override some defaults and inherit the other fields from
+        * activate_new.
+        * handle->offset is used to get the current position into the rx ring.
+        * handle->cc is used to store the ring size.
+        */
+       handle->read_op = pcap_read_linux_mmap;
+       handle->cleanup_op = pcap_cleanup_linux_mmap;
+       handle->setfilter_op = pcap_setfilter_linux_mmap;
+       handle->setnonblock_op = pcap_setnonblock_mmap;
+       handle->getnonblock_op = pcap_getnonblock_mmap;
+       handle->oneshot_callback = pcap_oneshot_mmap;
+       handle->selectable_fd = handle->fd;
+       return 1;
+}
+#else /* HAVE_PACKET_RING */
+static int 
+activate_mmap(pcap_t *handle _U_, int *status _U_)
+{
+       return 0;
+}
+#endif /* HAVE_PACKET_RING */
+
+#ifdef HAVE_PACKET_RING
+/*
+ * Attempt to set the socket to version 2 of the memory-mapped header.
+ * Return 1 if we succeed or if we fail because version 2 isn't
+ * supported; return -1 on any other error, and set handle->errbuf.
+ */
+static int
+prepare_tpacket_socket(pcap_t *handle)
+{
+#ifdef HAVE_TPACKET2
+       socklen_t len;
+       int val;
+#endif
+
+       handle->md.tp_version = TPACKET_V1;
+       handle->md.tp_hdrlen = sizeof(struct tpacket_hdr);
+
+#ifdef HAVE_TPACKET2
+       /* Probe whether kernel supports TPACKET_V2 */
+       val = TPACKET_V2;
+       len = sizeof(val);
+       if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
+               if (errno == ENOPROTOOPT)
+                       return 1;       /* no - just drive on */
+
+               /* Yes - treat as a failure. */
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't get TPACKET_V2 header len on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
+       }
+       handle->md.tp_hdrlen = val;
+
+       val = TPACKET_V2;
+       if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
+                      sizeof(val)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't activate TPACKET_V2 on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
+       }
+       handle->md.tp_version = TPACKET_V2;
+
+       /* Reserve space for VLAN tag reconstruction */
+       val = VLAN_TAG_LEN;
+       if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
+                      sizeof(val)) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't set up reserve on packet socket: %s",
+                   pcap_strerror(errno));
+               return -1;
+       }
+
+#endif /* HAVE_TPACKET2 */
+       return 1;
+}
+
+/*
+ * Attempt to set up memory-mapped access.
+ *
+ * On success, returns 1, and sets *status to 0 if there are no warnings
+ * or to a PCAP_WARNING_ code if there is a warning.
+ *
+ * On failure due to lack of support for memory-mapped capture, returns
+ * 0.
+ *
+ * On error, returns -1, and sets *status to the appropriate error code;
+ * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
+ */
+static int
+create_ring(pcap_t *handle, int *status)
+{
+       unsigned i, j, frames_per_block;
+       struct tpacket_req req;
+       socklen_t len;
+       unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
+       unsigned int frame_size;
+
+       /*
+        * Start out assuming no warnings or errors.
+        */
+       *status = 0;
+
+       /* Note that with large snapshot length (say 64K, which is the default
+        * for recent versions of tcpdump, the value that "-s 0" has given
+        * for a long time with tcpdump, and the default in Wireshark/TShark),
+        * if we use the snapshot length to calculate the frame length,
+        * only a few frames will be available in the ring even with pretty
+        * large ring size (and a lot of memory will be unused).
+        *
+        * Ideally, we should choose a frame length based on the
+        * minimum of the specified snapshot length and the maximum
+        * packet size.  That's not as easy as it sounds; consider, for
+        * example, an 802.11 interface in monitor mode, where the
+        * frame would include a radiotap header, where the maximum
+        * radiotap header length is device-dependent.
+        *
+        * So, for now, we just do this for Ethernet devices, where
+        * there's no metadata header, and the link-layer header is
+        * fixed length.  We can get the maximum packet size by
+        * adding 18, the Ethernet header length plus the CRC length
+        * (just in case we happen to get the CRC in the packet), to
+        * the MTU of the interface; we fetch the MTU in the hopes
+        * that it reflects support for jumbo frames.  (Even if the
+        * interface is just being used for passive snooping, the driver
+        * might set the size of buffers in the receive ring based on
+        * the MTU, so that the MTU limits the maximum size of packets
+        * that we can receive.)
+        *
+        * We don't do that if segmentation/fragmentation or receive
+        * offload are enabled, so we don't get rudely surprised by
+        * "packets" bigger than the MTU. */
+       frame_size = handle->snapshot;
+       if (handle->linktype == DLT_EN10MB) {
+               int mtu;
+               int offload;
+
+               offload = iface_get_offload(handle);
+               if (offload == -1) {
+                       *status = PCAP_ERROR;
+                       return -1;
+               }
+               if (!offload) {
+                       mtu = iface_get_mtu(handle->fd, handle->opt.source,
+                           handle->errbuf);
+                       if (mtu == -1) {
+                               *status = PCAP_ERROR;
+                               return -1;
+                       }
+                       if (frame_size > mtu + 18)
+                               frame_size = mtu + 18;
+               }
+       }
+       
+       /* NOTE: calculus matching those in tpacket_rcv()
+        * in linux-2.6/net/packet/af_packet.c
+        */
+       len = sizeof(sk_type);
+       if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
+               *status = PCAP_ERROR;
+               return -1;
+       }
+#ifdef PACKET_RESERVE
+       len = sizeof(tp_reserve);
+       if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) {
+               if (errno != ENOPROTOOPT) {
+                       /*
+                        * ENOPROTOOPT means "kernel doesn't support
+                        * PACKET_RESERVE", in which case we fall back
+                        * as best we can.
+                        */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno));
+                       *status = PCAP_ERROR;
+                       return -1;
+               }
+               tp_reserve = 0; /* older kernel, reserve not supported */
+       }
+#else
+       tp_reserve = 0; /* older kernel, reserve not supported */
+#endif
+       maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
+               /* XXX: in the kernel maclen is calculated from
+                * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
+                * in:  packet_snd()           in linux-2.6/net/packet/af_packet.c
+                * then packet_alloc_skb()     in linux-2.6/net/packet/af_packet.c
+                * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c
+                * but I see no way to get those sizes in userspace,
+                * like for instance with an ifreq ioctl();
+                * the best thing I've found so far is MAX_HEADER in the kernel
+                * part of linux-2.6/include/linux/netdevice.h
+                * which goes up to 128+48=176; since pcap-linux.c defines
+                * a MAX_LINKHEADER_SIZE of 256 which is greater than that,
+                * let's use it.. maybe is it even large enough to directly
+                * replace macoff..
+                */
+       tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ;
+       netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
+               /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of
+                * netoff, which contradicts
+                * linux-2.6/Documentation/networking/packet_mmap.txt
+                * documenting that:
+                * "- Gap, chosen so that packet data (Start+tp_net)
+                * aligns to TPACKET_ALIGNMENT=16"
+                */
+               /* NOTE: in linux-2.6/include/linux/skbuff.h:
+                * "CPUs often take a performance hit
+                *  when accessing unaligned memory locations"
+                */
+       macoff = netoff - maclen;
+       req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size);
+       req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
+
+       /* compute the minumum block size that will handle this frame. 
+        * The block has to be page size aligned. 
+        * The max block size allowed by the kernel is arch-dependent and 
+        * it's not explicitly checked here. */
+       req.tp_block_size = getpagesize();
+       while (req.tp_block_size < req.tp_frame_size) 
+               req.tp_block_size <<= 1;
+
+       frames_per_block = req.tp_block_size/req.tp_frame_size;
+
+       /*
+        * PACKET_TIMESTAMP was added after linux/net_tstamp.h was,
+        * so we check for PACKET_TIMESTAMP.  We check for
+        * linux/net_tstamp.h just in case a system somehow has
+        * PACKET_TIMESTAMP but not linux/net_tstamp.h; that might
+        * be unnecessary.
+        *
+        * SIOCSHWTSTAMP was introduced in the patch that introduced
+        * linux/net_tstamp.h, so we don't bother checking whether
+        * SIOCSHWTSTAMP is defined (if your Linux system has
+        * linux/net_tstamp.h but doesn't define SIOCSHWTSTAMP, your
+        * Linux system is badly broken).
+        */
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+       /*
+        * If we were told to do so, ask the kernel and the driver
+        * to use hardware timestamps.
+        *
+        * Hardware timestamps are only supported with mmapped
+        * captures.
+        */
+       if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER ||
+           handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER_UNSYNCED) {
+               struct hwtstamp_config hwconfig;
+               struct ifreq ifr;
+               int timesource;
+
+               /*
+                * Ask for hardware time stamps on all packets,
+                * including transmitted packets.
+                */
+               memset(&hwconfig, 0, sizeof(hwconfig));
+               hwconfig.tx_type = HWTSTAMP_TX_ON;
+               hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
+
+               memset(&ifr, 0, sizeof(ifr));
+               strcpy(ifr.ifr_name, handle->opt.source);
+               ifr.ifr_data = (void *)&hwconfig;
+
+               if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
+                       switch (errno) {
+
+                       case EPERM:
+                               /*
+                                * Treat this as an error, as the
+                                * user should try to run this
+                                * with the appropriate privileges -
+                                * and, if they can't, shouldn't
+                                * try requesting hardware time stamps.
+                                */
+                               *status = PCAP_ERROR_PERM_DENIED;
+                               return -1;
+
+                       case EOPNOTSUPP:
+                               /*
+                                * Treat this as a warning, as the
+                                * only way to fix the warning is to
+                                * get an adapter that supports hardware
+                                * time stamps.  We'll just fall back
+                                * on the standard host time stamps.
+                                */
+                               *status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
+                               break;
+
+                       default:
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "SIOCSHWTSTAMP failed: %s",
+                                       pcap_strerror(errno));
+                               *status = PCAP_ERROR;
+                               return -1;
+                       }
+               } else {
+                       /*
+                        * Well, that worked.  Now specify the type of
+                        * hardware time stamp we want for this
+                        * socket.
+                        */
+                       if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
+                               /*
+                                * Hardware timestamp, synchronized
+                                * with the system clock.
+                                */
+                               timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
+                       } else {
+                               /*
+                                * PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware
+                                * timestamp, not synchronized with the
+                                * system clock.
+                                */
+                               timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
+                       }
+                       if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
+                               (void *)&timesource, sizeof(timesource))) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
+                                       "can't set PACKET_TIMESTAMP: %s", 
+                                       pcap_strerror(errno));
+                               *status = PCAP_ERROR;
+                               return -1;
+                       }
+               }
+       }
+#endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */
+
+       /* ask the kernel to create the ring */
+retry:
+       req.tp_block_nr = req.tp_frame_nr / frames_per_block;
+
+       /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */
+       req.tp_frame_nr = req.tp_block_nr * frames_per_block;
+       
+       if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+                                       (void *) &req, sizeof(req))) {
+               if ((errno == ENOMEM) && (req.tp_block_nr > 1)) {
+                       /*
+                        * Memory failure; try to reduce the requested ring
+                        * size.
+                        *
+                        * We used to reduce this by half -- do 5% instead.
+                        * That may result in more iterations and a longer
+                        * startup, but the user will be much happier with
+                        * the resulting buffer size.
+                        */
+                       if (req.tp_frame_nr < 20)
+                               req.tp_frame_nr -= 1;
+                       else
+                               req.tp_frame_nr -= req.tp_frame_nr/20;
+                       goto retry;
+               }
+               if (errno == ENOPROTOOPT) {
+                       /*
+                        * We don't have ring buffer support in this kernel.
+                        */
+                       return 0;
+               }
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't create rx ring on packet socket: %s",
+                   pcap_strerror(errno));
+               *status = PCAP_ERROR;
+               return -1;
+       }
+
+       /* memory map the rx ring */
+       handle->md.mmapbuflen = req.tp_block_nr * req.tp_block_size;
+       handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen,
+           PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+       if (handle->md.mmapbuf == MAP_FAILED) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't mmap rx ring: %s", pcap_strerror(errno));
+
+               /* clear the allocated ring on error*/
+               destroy_ring(handle);
+               *status = PCAP_ERROR;
+               return -1;
+       }
+
+       /* allocate a ring for each frame header pointer*/
+       handle->cc = req.tp_frame_nr;
+       handle->buffer = malloc(handle->cc * sizeof(union thdr *));
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "can't allocate ring of frame headers: %s",
+                   pcap_strerror(errno));
+
+               destroy_ring(handle);
+               *status = PCAP_ERROR;
+               return -1;
+       }
+
+       /* fill the header ring with proper frame ptr*/
+       handle->offset = 0;
+       for (i=0; i<req.tp_block_nr; ++i) {
+               void *base = &handle->md.mmapbuf[i*req.tp_block_size];
+               for (j=0; j<frames_per_block; ++j, ++handle->offset) {
+                       RING_GET_FRAME(handle) = base;
+                       base += req.tp_frame_size;
+               }
+       }
+
+       handle->bufsize = req.tp_frame_size;
+       handle->offset = 0;
+       return 1;
+}
+
+/* free all ring related resources*/
+static void
+destroy_ring(pcap_t *handle)
+{
+       /* tell the kernel to destroy the ring*/
+       struct tpacket_req req;
+       memset(&req, 0, sizeof(req));
+       setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+                               (void *) &req, sizeof(req));
+
+       /* if ring is mapped, unmap it*/
+       if (handle->md.mmapbuf) {
+               /* do not test for mmap failure, as we can't recover from any error */
+               munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
+               handle->md.mmapbuf = NULL;
+       }
+}
+
+/*
+ * Special one-shot callback, used for pcap_next() and pcap_next_ex(),
+ * for Linux mmapped capture.
+ *
+ * The problem is that pcap_next() and pcap_next_ex() expect the packet
+ * data handed to the callback to be valid after the callback returns,
+ * but pcap_read_linux_mmap() has to release that packet as soon as
+ * the callback returns (otherwise, the kernel thinks there's still
+ * at least one unprocessed packet available in the ring, so a select()
+ * will immediately return indicating that there's data to process), so,
+ * in the callback, we have to make a copy of the packet.
+ *
+ * Yes, this means that, if the capture is using the ring buffer, using
+ * pcap_next() or pcap_next_ex() requires more copies than using
+ * pcap_loop() or pcap_dispatch().  If that bothers you, don't use
+ * pcap_next() or pcap_next_ex().
+ */
+static void
+pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+    const u_char *bytes)
+{
+       struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
+
+       *sp->hdr = *h;
+       memcpy(sp->pd->md.oneshot_buffer, bytes, h->caplen);
+       *sp->pkt = sp->pd->md.oneshot_buffer;
+}
+    
+static void
+pcap_cleanup_linux_mmap( pcap_t *handle )
+{
+       destroy_ring(handle);
+       if (handle->md.oneshot_buffer != NULL) {
+               free(handle->md.oneshot_buffer);
+               handle->md.oneshot_buffer = NULL;
+       }
+       pcap_cleanup_linux(handle);
+}
+
+
+static int
+pcap_getnonblock_mmap(pcap_t *p, char *errbuf)
+{
+       /* use negative value of timeout to indicate non blocking ops */
+       return (p->md.timeout<0);
+}
+
+static int
+pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
+{
+       /* map each value to the corresponding 2's complement, to 
+        * preserve the timeout value provided with pcap_set_timeout */
+       if (nonblock) {
+               if (p->md.timeout >= 0) {
+                       /*
+                        * Timeout is non-negative, so we're not already
+                        * in non-blocking mode; set it to the 2's
+                        * complement, to make it negative, as an
+                        * indication that we're in non-blocking mode.
+                        */
+                       p->md.timeout = p->md.timeout*-1 - 1;
+               }
+       } else {
+               if (p->md.timeout < 0) {
+                       /*
+                        * Timeout is negative, so we're not already
+                        * in blocking mode; reverse the previous
+                        * operation, to make the timeout non-negative
+                        * again.
+                        */
+                       p->md.timeout = (p->md.timeout+1)*-1;
+               }
+       }
+       return 0;
+}
+
+static inline union thdr *
+pcap_get_ring_frame(pcap_t *handle, int status)
+{
+       union thdr h;
+
+       h.raw = RING_GET_FRAME(handle);
+       switch (handle->md.tp_version) {
+       case TPACKET_V1:
+               if (status != (h.h1->tp_status ? TP_STATUS_USER :
+                                               TP_STATUS_KERNEL))
+                       return NULL;
+               break;
+#ifdef HAVE_TPACKET2
+       case TPACKET_V2:
+               if (status != (h.h2->tp_status ? TP_STATUS_USER :
+                                               TP_STATUS_KERNEL))
+                       return NULL;
+               break;
+#endif
+       }
+       return h.raw;
+}
+
+#ifndef POLLRDHUP
+#define POLLRDHUP 0
+#endif
+
+static int
+pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, 
+               u_char *user)
+{
+       int timeout;
+       int pkts = 0;
+       char c;
+
+       /* wait for frames availability.*/
+       if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) {
+               struct pollfd pollinfo;
+               int ret;
+
+               pollinfo.fd = handle->fd;
+               pollinfo.events = POLLIN;
+
+               if (handle->md.timeout == 0)
+                       timeout = -1;   /* block forever */
+               else if (handle->md.timeout > 0)
+                       timeout = handle->md.timeout;   /* block for that amount of time */
+               else
+                       timeout = 0;    /* non-blocking mode - poll to pick up errors */
+               do {
+                       ret = poll(&pollinfo, 1, timeout);
+                       if (ret < 0 && errno != EINTR) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
+                                       "can't poll on packet socket: %s",
+                                       pcap_strerror(errno));
+                               return PCAP_ERROR;
+                       } else if (ret > 0 &&
+                           (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
+                               /*
+                                * There's some indication other than
+                                * "you can read on this descriptor" on
+                                * the descriptor.
+                                */
+                               if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
+                                       snprintf(handle->errbuf,
+                                               PCAP_ERRBUF_SIZE,
+                                               "Hangup on packet socket");
+                                       return PCAP_ERROR;
+                               }
+                               if (pollinfo.revents & POLLERR) {
+                                       /*
+                                        * A recv() will give us the
+                                        * actual error code.
+                                        *
+                                        * XXX - make the socket non-blocking?
+                                        */
+                                       if (recv(handle->fd, &c, sizeof c,
+                                           MSG_PEEK) != -1)
+                                               continue;       /* what, no error? */
+                                       if (errno == ENETDOWN) {
+                                               /*
+                                                * The device on which we're
+                                                * capturing went away.
+                                                *
+                                                * XXX - we should really return
+                                                * PCAP_ERROR_IFACE_NOT_UP,
+                                                * but pcap_dispatch() etc.
+                                                * aren't defined to return
+                                                * that.
+                                                */
+                                               snprintf(handle->errbuf,
+                                                       PCAP_ERRBUF_SIZE,
+                                                       "The interface went down");
+                                       } else {
+                                               snprintf(handle->errbuf,
+                                                       PCAP_ERRBUF_SIZE, 
+                                                       "Error condition on packet socket: %s",
+                                                       strerror(errno));
+                                       }
+                                       return PCAP_ERROR;
+                               }
+                               if (pollinfo.revents & POLLNVAL) {
+                                       snprintf(handle->errbuf,
+                                               PCAP_ERRBUF_SIZE, 
+                                               "Invalid polling request on packet socket");
+                                       return PCAP_ERROR;
+                               }
+                       }
+                       /* check for break loop condition on interrupted syscall*/
+                       if (handle->break_loop) {
+                               handle->break_loop = 0;
+                               return PCAP_ERROR_BREAK;
+                       }
+               } while (ret < 0);
+       }
+
+       /* non-positive values of max_packets are used to require all 
+        * packets currently available in the ring */
+       while ((pkts < max_packets) || (max_packets <= 0)) {
+               int run_bpf;
+               struct sockaddr_ll *sll;
+               struct pcap_pkthdr pcaphdr;
+               unsigned char *bp;
+               union thdr h;
+               unsigned int tp_len;
+               unsigned int tp_mac;
+               unsigned int tp_snaplen;
+               unsigned int tp_sec;
+               unsigned int tp_usec;
+
+               h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
+               if (!h.raw)
+                       break;
+
+               switch (handle->md.tp_version) {
+               case TPACKET_V1:
+                       tp_len     = h.h1->tp_len;
+                       tp_mac     = h.h1->tp_mac;
+                       tp_snaplen = h.h1->tp_snaplen;
+                       tp_sec     = h.h1->tp_sec;
+                       tp_usec    = h.h1->tp_usec;
+                       break;
+#ifdef HAVE_TPACKET2
+               case TPACKET_V2:
+                       tp_len     = h.h2->tp_len;
+                       tp_mac     = h.h2->tp_mac;
+                       tp_snaplen = h.h2->tp_snaplen;
+                       tp_sec     = h.h2->tp_sec;
+                       tp_usec    = h.h2->tp_nsec / 1000;
+                       break;
+#endif
+               default:
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
+                               "unsupported tpacket version %d",
+                               handle->md.tp_version);
+                       return -1;
+               }
+               /* perform sanity check on internal offset. */
+               if (tp_mac + tp_snaplen > handle->bufsize) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
+                               "corrupted frame on kernel ring mac "
+                               "offset %d + caplen %d > frame len %d", 
+                               tp_mac, tp_snaplen, handle->bufsize);
+                       return -1;
+               }
+
+               /* run filter on received packet
+                * If the kernel filtering is enabled we need to run the
+                * filter until all the frames present into the ring 
+                * at filter creation time are processed. 
+                * In such case md.use_bpf is used as a counter for the 
+                * packet we need to filter.
+                * Note: alternatively it could be possible to stop applying 
+                * the filter when the ring became empty, but it can possibly
+                * happen a lot later... */
+               bp = (unsigned char*)h.raw + tp_mac;
+               run_bpf = (!handle->md.use_bpf) || 
+                       ((handle->md.use_bpf>1) && handle->md.use_bpf--);
+               if (run_bpf && handle->fcode.bf_insns && 
+                               (bpf_filter(handle->fcode.bf_insns, bp,
+                                       tp_len, tp_snaplen) == 0))
+                       goto skip;
+
+               /*
+                * Do checks based on packet direction.
+                */
+               sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen);
+               if (sll->sll_pkttype == PACKET_OUTGOING) {
+                       /*
+                        * Outgoing packet.
+                        * If this is from the loopback device, reject it;
+                        * we'll see the packet as an incoming packet as well,
+                        * and we don't want to see it twice.
+                        */
+                       if (sll->sll_ifindex == handle->md.lo_ifindex)
+                               goto skip;
+
+                       /*
+                        * If the user only wants incoming packets, reject it.
+                        */
+                       if (handle->direction == PCAP_D_IN)
+                               goto skip;
+               } else {
+                       /*
+                        * Incoming packet.
+                        * If the user only wants outgoing packets, reject it.
+                        */
+                       if (handle->direction == PCAP_D_OUT)
+                               goto skip;
+               }
+
+               /* get required packet info from ring header */
+               pcaphdr.ts.tv_sec = tp_sec;
+               pcaphdr.ts.tv_usec = tp_usec;
+               pcaphdr.caplen = tp_snaplen;
+               pcaphdr.len = tp_len;
+
+               /* if required build in place the sll header*/
+               if (handle->md.cooked) {
+                       struct sll_header *hdrp;
+
+                       /*
+                        * The kernel should have left us with enough
+                        * space for an sll header; back up the packet
+                        * data pointer into that space, as that'll be
+                        * the beginning of the packet we pass to the
+                        * callback.
+                        */
+                       bp -= SLL_HDR_LEN;
+
+                       /*
+                        * Let's make sure that's past the end of
+                        * the tpacket header, i.e. >=
+                        * ((u_char *)thdr + TPACKET_HDRLEN), so we
+                        * don't step on the header when we construct
+                        * the sll header.
+                        */
+                       if (bp < (u_char *)h.raw +
+                                          TPACKET_ALIGN(handle->md.tp_hdrlen) +
+                                          sizeof(struct sockaddr_ll)) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
+                                       "cooked-mode frame doesn't have room for sll header");
+                               return -1;
+                       }
+
+                       /*
+                        * OK, that worked; construct the sll header.
+                        */
+                       hdrp = (struct sll_header *)bp;
+                       hdrp->sll_pkttype = map_packet_type_to_sll_type(
+                                                       sll->sll_pkttype);
+                       hdrp->sll_hatype = htons(sll->sll_hatype);
+                       hdrp->sll_halen = htons(sll->sll_halen);
+                       memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
+                       hdrp->sll_protocol = sll->sll_protocol;
+
+                       /* update packet len */
+                       pcaphdr.caplen += SLL_HDR_LEN;
+                       pcaphdr.len += SLL_HDR_LEN;
+               }
+
+#ifdef HAVE_TPACKET2
+               if (handle->md.tp_version == TPACKET_V2 && h.h2->tp_vlan_tci &&
+                   tp_snaplen >= 2 * ETH_ALEN) {
+                       struct vlan_tag *tag;
+
+                       bp -= VLAN_TAG_LEN;
+                       memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);
+
+                       tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
+                       tag->vlan_tpid = htons(ETH_P_8021Q);
+                       tag->vlan_tci = htons(h.h2->tp_vlan_tci);
+
+                       pcaphdr.caplen += VLAN_TAG_LEN;
+                       pcaphdr.len += VLAN_TAG_LEN;
+               }
+#endif
+
+               /*
+                * The only way to tell the kernel to cut off the
+                * packet at a snapshot length is with a filter program;
+                * if there's no filter program, the kernel won't cut
+                * the packet off.
+                *
+                * Trim the snapshot length to be no longer than the
+                * specified snapshot length.
+                */
+               if (pcaphdr.caplen > handle->snapshot)
+                       pcaphdr.caplen = handle->snapshot;
+
+               /* pass the packet to the user */
+               pkts++;
+               callback(user, &pcaphdr, bp);
+               handle->md.packets_read++;
+
+skip:
+               /* next packet */
+               switch (handle->md.tp_version) {
+               case TPACKET_V1:
+                       h.h1->tp_status = TP_STATUS_KERNEL;
+                       break;
+#ifdef HAVE_TPACKET2
+               case TPACKET_V2:
+                       h.h2->tp_status = TP_STATUS_KERNEL;
+                       break;
+#endif
+               }
+               if (++handle->offset >= handle->cc)
+                       handle->offset = 0;
+
+               /* check for break loop condition*/
+               if (handle->break_loop) {
+                       handle->break_loop = 0;
+                       return PCAP_ERROR_BREAK;
+               }
+       }
+       return pkts;
+}
+
+static int 
+pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
+{
+       int n, offset;
+       int ret;
+
+       /*
+        * Don't rewrite "ret" instructions; we don't need to, as
+        * we're not reading packets with recvmsg(), and we don't
+        * want to, as, by not rewriting them, the kernel can avoid
+        * copying extra data.
+        */
+       ret = pcap_setfilter_linux_common(handle, filter, 1);
+       if (ret < 0)
+               return ret;
+
+       /* if the kernel filter is enabled, we need to apply the filter on
+        * all packets present into the ring. Get an upper bound of their number
+        */
+       if (!handle->md.use_bpf)
+               return ret;
+
+       /* walk the ring backward and count the free slot */
+       offset = handle->offset;
+       if (--handle->offset < 0)
+               handle->offset = handle->cc - 1;
+       for (n=0; n < handle->cc; ++n) {
+               if (--handle->offset < 0)
+                       handle->offset = handle->cc - 1;
+               if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL))
+                       break;
+       }
+
+       /* be careful to not change current ring position */
+       handle->offset = offset;
+
+       /* store the number of packets currently present in the ring */
+       handle->md.use_bpf = 1 + (handle->cc - n);
+       return ret;
+}
+
+#endif /* HAVE_PACKET_RING */
+
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+/*
+ *  Return the index of the given device name. Fill ebuf and return
+ *  -1 on failure.
+ */
+static int
+iface_get_id(int fd, const char *device, char *ebuf)
+{
+       struct ifreq    ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+       if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                        "SIOCGIFINDEX: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       return ifr.ifr_ifindex;
+}
+
+/*
+ *  Bind the socket associated with FD to the given device.
+ *  Return 1 on success, 0 if we should try a SOCK_PACKET socket,
+ *  or a PCAP_ERROR_ value on a hard error.
+ */
+static int
+iface_bind(int fd, int ifindex, char *ebuf)
+{
+       struct sockaddr_ll      sll;
+       int                     err;
+       socklen_t               errlen = sizeof(err);
+
+       memset(&sll, 0, sizeof(sll));
+       sll.sll_family          = AF_PACKET;
+       sll.sll_ifindex         = ifindex;
+       sll.sll_protocol        = htons(ETH_P_ALL);
+
+       if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
+               if (errno == ENETDOWN) {
+                       /*
+                        * Return a "network down" indication, so that
+                        * the application can report that rather than
+                        * saying we had a mysterious failure and
+                        * suggest that they report a problem to the
+                        * libpcap developers.
+                        */
+                       return PCAP_ERROR_IFACE_NOT_UP;
+               } else {
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                                "bind: %s", pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+       }
+
+       /* Any pending errors, e.g., network is down? */
+
+       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                       "getsockopt: %s", pcap_strerror(errno));
+               return 0;
+       }
+
+       if (err == ENETDOWN) {
+               /*
+                * Return a "network down" indication, so that
+                * the application can report that rather than
+                * saying we had a mysterious failure and
+                * suggest that they report a problem to the
+                * libpcap developers.
+                */
+               return PCAP_ERROR_IFACE_NOT_UP;
+       } else if (err > 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                       "bind: %s", pcap_strerror(err));
+               return 0;
+       }
+
+       return 1;
+}
+
+#ifdef IW_MODE_MONITOR
+/*
+ * Check whether the device supports the Wireless Extensions.
+ * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE
+ * if the device doesn't even exist.
+ */
+static int
+has_wext(int sock_fd, const char *device, char *ebuf)
+{
+       struct iwreq ireq;
+
+       strncpy(ireq.ifr_ifrn.ifrn_name, device,
+           sizeof ireq.ifr_ifrn.ifrn_name);
+       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+       if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
+               return 1;       /* yes */
+       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+           "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
+       if (errno == ENODEV)
+               return PCAP_ERROR_NO_SUCH_DEVICE;
+       return 0;
+}
+
+/*
+ * Per me si va ne la citta dolente,
+ * Per me si va ne l'etterno dolore,
+ *     ...
+ * Lasciate ogne speranza, voi ch'intrate.
+ *
+ * XXX - airmon-ng does special stuff with the Orinoco driver and the
+ * wlan-ng driver.
+ */
+typedef enum {
+       MONITOR_WEXT,
+       MONITOR_HOSTAP,
+       MONITOR_PRISM,
+       MONITOR_PRISM54,
+       MONITOR_ACX100,
+       MONITOR_RT2500,
+       MONITOR_RT2570,
+       MONITOR_RT73,
+       MONITOR_RTL8XXX
+} monitor_type;
+
+/*
+ * Use the Wireless Extensions, if we have them, to try to turn monitor mode
+ * on if it's not already on.
+ *
+ * Returns 1 on success, 0 if we don't support the Wireless Extensions
+ * on this device, or a PCAP_ERROR_ value if we do support them but
+ * we weren't able to turn monitor mode on.
+ */
+static int
+enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
+{
+       /*
+        * XXX - at least some adapters require non-Wireless Extensions
+        * mechanisms to turn monitor mode on.
+        *
+        * Atheros cards might require that a separate "monitor virtual access
+        * point" be created, with later versions of the madwifi driver.
+        * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode
+        * monitor -bssid", which apparently spits out a line "athN"
+        * where "athN" is the monitor mode device.  To leave monitor
+        * mode, it destroys the monitor mode device.
+        *
+        * Some Intel Centrino adapters might require private ioctls to get
+        * radio headers; the ipw2200 and ipw3945 drivers allow you to
+        * configure a separate "rtapN" interface to capture in monitor
+        * mode without preventing the adapter from operating normally.
+        * (airmon-ng doesn't appear to use that, though.)
+        *
+        * It would be Truly Wonderful if mac80211 and nl80211 cleaned this
+        * up, and if all drivers were converted to mac80211 drivers.
+        *
+        * If interface {if} is a mac80211 driver, the file
+        * /sys/class/net/{if}/phy80211 is a symlink to
+        * /sys/class/ieee80211/{phydev}, for some {phydev}.
+        *
+        * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
+        * least, has a "wmaster0" device and a "wlan0" device; the
+        * latter is the one with the IP address.  Both show up in
+        * "tcpdump -D" output.  Capturing on the wmaster0 device
+        * captures with 802.11 headers.
+        *
+        * airmon-ng searches through /sys/class/net for devices named
+        * monN, starting with mon0; as soon as one *doesn't* exist,
+        * it chooses that as the monitor device name.  If the "iw"
+        * command exists, it does "iw dev {if} interface add {monif}
+        * type monitor", where {monif} is the monitor device.  It
+        * then (sigh) sleeps .1 second, and then configures the
+        * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
+        * is a file, it writes {mondev}, without a newline, to that file,
+        * and again (sigh) sleeps .1 second, and then iwconfig's that
+        * device into monitor mode and configures it up.  Otherwise,
+        * you can't do monitor mode.
+        *
+        * All these devices are "glued" together by having the
+        * /sys/class/net/{device}/phy80211 links pointing to the same
+        * place, so, given a wmaster, wlan, or mon device, you can
+        * find the other devices by looking for devices with
+        * the same phy80211 link.
+        *
+        * To turn monitor mode off, delete the monitor interface,
+        * either with "iw dev {monif} interface del" or by sending
+        * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+        *
+        * Note: if you try to create a monitor device named "monN", and
+        * there's already a "monN" device, it fails, as least with
+        * the netlink interface (which is what iw uses), with a return
+        * value of -ENFILE.  (Return values are negative errnos.)  We
+        * could probably use that to find an unused device.
+        */
+       int err;
+       struct iwreq ireq;
+       struct iw_priv_args *priv;
+       monitor_type montype;
+       int i;
+       __u32 cmd;
+       struct ifreq ifr;
+       int oldflags;
+       int args[2];
+       int channel;
+
+       /*
+        * Does this device *support* the Wireless Extensions?
+        */
+       err = has_wext(sock_fd, device, handle->errbuf);
+       if (err <= 0)
+               return err;     /* either it doesn't or the device doesn't even exist */
+       /*
+        * Start out assuming we have no private extensions to control
+        * radio metadata.
+        */
+       montype = MONITOR_WEXT;
+       cmd = 0;
+
+       /*
+        * Try to get all the Wireless Extensions private ioctls
+        * supported by this device.
+        *
+        * First, get the size of the buffer we need, by supplying no
+        * buffer and a length of 0.  If the device supports private
+        * ioctls, it should return E2BIG, with ireq.u.data.length set
+        * to the length we need.  If it doesn't support them, it should
+        * return EOPNOTSUPP.
+        */
+       memset(&ireq, 0, sizeof ireq);
+       strncpy(ireq.ifr_ifrn.ifrn_name, device,
+           sizeof ireq.ifr_ifrn.ifrn_name);
+       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+       ireq.u.data.pointer = (void *)args;
+       ireq.u.data.length = 0;
+       ireq.u.data.flags = 0;
+       if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
+                   device);
+               return PCAP_ERROR;
+       }
+       if (errno != EOPNOTSUPP) {
+               /*
+                * OK, it's not as if there are no private ioctls.
+                */
+               if (errno != E2BIG) {
+                       /*
+                        * Failed.
+                        */
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: SIOCGIWPRIV: %s", device,
+                           pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+
+               /*
+                * OK, try to get the list of private ioctls.
+                */
+               priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
+               if (priv == NULL) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "malloc: %s", pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+               ireq.u.data.pointer = (void *)priv;
+               if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: SIOCGIWPRIV: %s", device,
+                           pcap_strerror(errno));
+                       free(priv);
+                       return PCAP_ERROR;
+               }
+
+               /*
+                * Look for private ioctls to turn monitor mode on or, if
+                * monitor mode is on, to set the header type.
+                */
+               for (i = 0; i < ireq.u.data.length; i++) {
+                       if (strcmp(priv[i].name, "monitor_type") == 0) {
+                               /*
+                                * Hostap driver, use this one.
+                                * Set monitor mode first.
+                                * You can set it to 0 to get DLT_IEEE80211,
+                                * 1 to get DLT_PRISM, 2 to get
+                                * DLT_IEEE80211_RADIO_AVS, and, with more
+                                * recent versions of the driver, 3 to get
+                                * DLT_IEEE80211_RADIO.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+                                       break;
+                               if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+                                       break;
+                               montype = MONITOR_HOSTAP;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "set_prismhdr") == 0) {
+                               /*
+                                * Prism54 driver, use this one.
+                                * Set monitor mode first.
+                                * You can set it to 2 to get DLT_IEEE80211
+                                * or 3 or get DLT_PRISM.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+                                       break;
+                               if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+                                       break;
+                               montype = MONITOR_PRISM54;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "forceprismheader") == 0) {
+                               /*
+                                * RT2570 driver, use this one.
+                                * Do this after turning monitor mode on.
+                                * You can set it to 1 to get DLT_PRISM or 2
+                                * to get DLT_IEEE80211.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+                                       break;
+                               if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+                                       break;
+                               montype = MONITOR_RT2570;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "forceprism") == 0) {
+                               /*
+                                * RT73 driver, use this one.
+                                * Do this after turning monitor mode on.
+                                * Its argument is a *string*; you can
+                                * set it to "1" to get DLT_PRISM or "2"
+                                * to get DLT_IEEE80211.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
+                                       break;
+                               if (priv[i].set_args & IW_PRIV_SIZE_FIXED)
+                                       break;
+                               montype = MONITOR_RT73;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "prismhdr") == 0) {
+                               /*
+                                * One of the RTL8xxx drivers, use this one.
+                                * It can only be done after monitor mode
+                                * has been turned on.  You can set it to 1
+                                * to get DLT_PRISM or 0 to get DLT_IEEE80211.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+                                       break;
+                               if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+                                       break;
+                               montype = MONITOR_RTL8XXX;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "rfmontx") == 0) {
+                               /*
+                                * RT2500 or RT61 driver, use this one.
+                                * It has one one-byte parameter; set
+                                * u.data.length to 1 and u.data.pointer to
+                                * point to the parameter.
+                                * It doesn't itself turn monitor mode on.
+                                * You can set it to 1 to allow transmitting
+                                * in monitor mode(?) and get DLT_IEEE80211,
+                                * or set it to 0 to disallow transmitting in
+                                * monitor mode(?) and get DLT_PRISM.
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2)
+                                       break;
+                               montype = MONITOR_RT2500;
+                               cmd = priv[i].cmd;
+                               break;
+                       }
+                       if (strcmp(priv[i].name, "monitor") == 0) {
+                               /*
+                                * Either ACX100 or hostap, use this one.
+                                * It turns monitor mode on.
+                                * If it takes two arguments, it's ACX100;
+                                * the first argument is 1 for DLT_PRISM
+                                * or 2 for DLT_IEEE80211, and the second
+                                * argument is the channel on which to
+                                * run.  If it takes one argument, it's
+                                * HostAP, and the argument is 2 for
+                                * DLT_IEEE80211 and 3 for DLT_PRISM.
+                                *
+                                * If we see this, we don't quit, as this
+                                * might be a version of the hostap driver
+                                * that also supports "monitor_type".
+                                */
+                               if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+                                       break;
+                               if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+                                       break;
+                               switch (priv[i].set_args & IW_PRIV_SIZE_MASK) {
+
+                               case 1:
+                                       montype = MONITOR_PRISM;
+                                       cmd = priv[i].cmd;
+                                       break;
+
+                               case 2:
+                                       montype = MONITOR_ACX100;
+                                       cmd = priv[i].cmd;
+                                       break;
+
+                               default:
+                                       break;
+                               }
+                       }
+               }
+               free(priv);
+       }
+
+       /*
+        * XXX - ipw3945?  islism?
+        */
+
+       /*
+        * Get the old mode.
+        */
+       strncpy(ireq.ifr_ifrn.ifrn_name, device,
+           sizeof ireq.ifr_ifrn.ifrn_name);
+       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+       if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
+               /*
+                * We probably won't be able to set the mode, either.
+                */
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       /*
+        * Is it currently in monitor mode?
+        */
+       if (ireq.u.mode == IW_MODE_MONITOR) {
+               /*
+                * Yes.  Just leave things as they are.
+                * We don't offer multiple link-layer types, as
+                * changing the link-layer type out from under
+                * somebody else capturing in monitor mode would
+                * be considered rude.
+                */
+               return 1;
+       }
+       /*
+        * No.  We have to put the adapter into rfmon mode.
+        */
+
+       /*
+        * If we haven't already done so, arrange to have
+        * "pcap_close_all()" called when we exit.
+        */
+       if (!pcap_do_addexit(handle)) {
+               /*
+                * "atexit()" failed; don't put the interface
+                * in rfmon mode, just give up.
+                */
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       /*
+        * Save the old mode.
+        */
+       handle->md.oldmode = ireq.u.mode;
+
+       /*
+        * Put the adapter in rfmon mode.  How we do this depends
+        * on whether we have a special private ioctl or not.
+        */
+       if (montype == MONITOR_PRISM) {
+               /*
+                * We have the "monitor" private ioctl, but none of
+                * the other private ioctls.  Use this, and select
+                * the Prism header.
+                *
+                * If it fails, just fall back on SIOCSIWMODE.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               ireq.u.data.length = 1; /* 1 argument */
+               args[0] = 3;    /* request Prism header */
+               memcpy(ireq.u.name, args, IFNAMSIZ);
+               if (ioctl(sock_fd, cmd, &ireq) != -1) {
+                       /*
+                        * Success.
+                        * Note that we have to put the old mode back
+                        * when we close the device.
+                        */
+                       handle->md.must_do_on_close |= MUST_CLEAR_RFMON;
+
+                       /*
+                        * Add this to the list of pcaps to close
+                        * when we exit.
+                        */
+                       pcap_add_to_pcaps_to_close(handle);
+
+                       return 1;
+               }
+
+               /*
+                * Failure.  Fall back on SIOCSIWMODE.
+                */
+       }
+
+       /*
+        * First, take the interface down if it's up; otherwise, we
+        * might get EBUSY.
+        */
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: Can't get flags: %s", device, strerror(errno));
+               return PCAP_ERROR;
+       }
+       oldflags = 0;
+       if (ifr.ifr_flags & IFF_UP) {
+               oldflags = ifr.ifr_flags;
+               ifr.ifr_flags &= ~IFF_UP;
+               if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: Can't set flags: %s", device, strerror(errno));
+                       return PCAP_ERROR;
+               }
+       }
+
+       /*
+        * Then turn monitor mode on.
+        */
+       strncpy(ireq.ifr_ifrn.ifrn_name, device,
+           sizeof ireq.ifr_ifrn.ifrn_name);
+       ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+       ireq.u.mode = IW_MODE_MONITOR;
+       if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
+               /*
+                * Scientist, you've failed.
+                * Bring the interface back up if we shut it down.
+                */
+               ifr.ifr_flags = oldflags;
+               if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: Can't set flags: %s", device, strerror(errno));
+                       return PCAP_ERROR;
+               }
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       /*
+        * XXX - airmon-ng does "iwconfig {if} key off" after setting
+        * monitor mode and setting the channel, and then does
+        * "iwconfig up".
+        */
+
+       /*
+        * Now select the appropriate radio header.
+        */
+       switch (montype) {
+
+       case MONITOR_WEXT:
+               /*
+                * We don't have any private ioctl to set the header.
+                */
+               break;
+
+       case MONITOR_HOSTAP:
+               /*
+                * Try to select the radiotap header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 3;    /* request radiotap header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               if (ioctl(sock_fd, cmd, &ireq) != -1)
+                       break;  /* success */
+
+               /*
+                * That failed.  Try to select the AVS header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 2;    /* request AVS header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               if (ioctl(sock_fd, cmd, &ireq) != -1)
+                       break;  /* success */
+
+               /*
+                * That failed.  Try to select the Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 1;    /* request Prism header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_PRISM:
+               /*
+                * The private ioctl failed.
+                */
+               break;
+
+       case MONITOR_PRISM54:
+               /*
+                * Select the Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 3;    /* request Prism header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_ACX100:
+               /*
+                * Get the current channel.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: SIOCGIWFREQ: %s", device,
+                           pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+               channel = ireq.u.freq.m;
+
+               /*
+                * Select the Prism header, and set the channel to the
+                * current value.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 1;            /* request Prism header */
+               args[1] = channel;      /* set channel */
+               memcpy(ireq.u.name, args, 2*sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_RT2500:
+               /*
+                * Disallow transmission - that turns on the
+                * Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 0;    /* disallow transmitting */
+               memcpy(ireq.u.name, args, sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_RT2570:
+               /*
+                * Force the Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 1;    /* request Prism header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_RT73:
+               /*
+                * Force the Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               ireq.u.data.length = 1; /* 1 argument */
+               ireq.u.data.pointer = "1";
+               ireq.u.data.flags = 0;
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+
+       case MONITOR_RTL8XXX:
+               /*
+                * Force the Prism header.
+                */
+               memset(&ireq, 0, sizeof ireq);
+               strncpy(ireq.ifr_ifrn.ifrn_name, device,
+                   sizeof ireq.ifr_ifrn.ifrn_name);
+               ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+               args[0] = 1;    /* request Prism header */
+               memcpy(ireq.u.name, args, sizeof (int));
+               ioctl(sock_fd, cmd, &ireq);
+               break;
+       }
+
+       /*
+        * Now bring the interface back up if we brought it down.
+        */
+       if (oldflags != 0) {
+               ifr.ifr_flags = oldflags;
+               if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: Can't set flags: %s", device, strerror(errno));
+
+                       /*
+                        * At least try to restore the old mode on the
+                        * interface.
+                        */
+                       if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
+                               /*
+                                * Scientist, you've failed.
+                                */
+                               fprintf(stderr,
+                                   "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n"
+                                   "Please adjust manually.\n",
+                                   strerror(errno));
+                       }
+                       return PCAP_ERROR;
+               }
+       }
+
+       /*
+        * Note that we have to put the old mode back when we
+        * close the device.
+        */
+       handle->md.must_do_on_close |= MUST_CLEAR_RFMON;
+
+       /*
+        * Add this to the list of pcaps to close when we exit.
+        */
+       pcap_add_to_pcaps_to_close(handle);
+
+       return 1;
+}
+#endif /* IW_MODE_MONITOR */
+
+/*
+ * Try various mechanisms to enter monitor mode.
+ */
+static int
+enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
+{
+#if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR)
+       int ret;
+#endif
+
+#ifdef HAVE_LIBNL
+       ret = enter_rfmon_mode_mac80211(handle, sock_fd, device);
+       if (ret < 0)
+               return ret;     /* error attempting to do so */
+       if (ret == 1)
+               return 1;       /* success */
+#endif /* HAVE_LIBNL */
+
+#ifdef IW_MODE_MONITOR
+       ret = enter_rfmon_mode_wext(handle, sock_fd, device);
+       if (ret < 0)
+               return ret;     /* error attempting to do so */
+       if (ret == 1)
+               return 1;       /* success */
+#endif /* IW_MODE_MONITOR */
+
+       /*
+        * Either none of the mechanisms we know about work or none
+        * of those mechanisms are available, so we can't do monitor
+        * mode.
+        */
+       return 0;
+}
+
+/*
+ * Find out if we have any form of fragmentation/reassembly offloading.
+ *
+ * We do so using SIOCETHTOOL checking for various types of offloading;
+ * if SIOCETHTOOL isn't defined, or we don't have any #defines for any
+ * of the types of offloading, there's nothing we can do to check, so
+ * we just say "no, we don't".
+ */
+#if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO))
+static int
+iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname)
+{
+       struct ifreq    ifr;
+       struct ethtool_value eval;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+       eval.cmd = cmd;
+       ifr.ifr_data = (caddr_t)&eval;
+       if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) {
+               if (errno == EOPNOTSUPP) {
+                       /*
+                        * OK, let's just return 0, which, in our
+                        * case, either means "no, what we're asking
+                        * about is not enabled" or "all the flags
+                        * are clear (i.e., nothing is enabled)".
+                        */
+                       return 0;
+               }
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: SIOETHTOOL(%s) ioctl failed: %s", handle->opt.source,
+                   cmdname, strerror(errno));
+               return -1;
+       }
+       return eval.data;       
+}
+
+static int
+iface_get_offload(pcap_t *handle)
+{
+       int ret;
+
+#ifdef ETHTOOL_GTSO
+       ret = iface_ethtool_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO");
+       if (ret == -1)
+               return -1;
+       if (ret)
+               return 1;       /* TCP segmentation offloading on */
+#endif
+
+#ifdef ETHTOOL_GUFO
+       ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
+       if (ret == -1)
+               return -1;
+       if (ret)
+               return 1;       /* UDP fragmentation offloading on */
+#endif
+
+#ifdef ETHTOOL_GGSO
+       /*
+        * XXX - will this cause large unsegmented packets to be
+        * handed to PF_PACKET sockets on transmission?  If not,
+        * this need not be checked.
+        */
+       ret = iface_ethtool_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO");
+       if (ret == -1)
+               return -1;
+       if (ret)
+               return 1;       /* generic segmentation offloading on */
+#endif
+
+#ifdef ETHTOOL_GFLAGS
+       ret = iface_ethtool_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
+       if (ret == -1)
+               return -1;
+       if (ret & ETH_FLAG_LRO)
+               return 1;       /* large receive offloading on */
+#endif
+
+#ifdef ETHTOOL_GGRO
+       /*
+        * XXX - will this cause large reassembled packets to be
+        * handed to PF_PACKET sockets on receipt?  If not,
+        * this need not be checked.
+        */
+       ret = iface_ethtool_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO");
+       if (ret == -1)
+               return -1;
+       if (ret)
+               return 1;       /* generic (large) receive offloading on */
+#endif
+
+       return 0;
+}
+#else /* SIOCETHTOOL */
+static int
+iface_get_offload(pcap_t *handle _U_)
+{
+       /*
+        * XXX - do we need to get this information if we don't
+        * have the ethtool ioctls?  If so, how do we do that?
+        */
+       return 0;
+}
+#endif /* SIOCETHTOOL */
+
+#endif /* HAVE_PF_PACKET_SOCKETS */
+
+/* ===== Functions to interface to the older kernels ================== */
+
+/*
+ * Try to open a packet socket using the old kernel interface.
+ * Returns 1 on success and a PCAP_ERROR_ value on an error.
+ */
+static int
+activate_old(pcap_t *handle)
+{
+       int             arptype;
+       struct ifreq    ifr;
+       const char      *device = handle->opt.source;
+       struct utsname  utsname;
+       int             mtu;
+
+       /* Open the socket */
+
+       handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+       if (handle->fd == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "socket: %s", pcap_strerror(errno));
+               if (errno == EPERM || errno == EACCES) {
+                       /*
+                        * You don't have permission to open the
+                        * socket.
+                        */
+                       return PCAP_ERROR_PERM_DENIED;
+               } else {
+                       /*
+                        * Other error.
+                        */
+                       return PCAP_ERROR;
+               }
+       }
+
+       /* It worked - we are using the old interface */
+       handle->md.sock_packet = 1;
+
+       /* ...which means we get the link-layer header. */
+       handle->md.cooked = 0;
+
+       /* Bind to the given device */
+
+       if (strcmp(device, "any") == 0) {
+               strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
+                       PCAP_ERRBUF_SIZE);
+               return PCAP_ERROR;
+       }
+       if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
+               return PCAP_ERROR;
+
+       /*
+        * Try to get the link-layer type.
+        */
+       arptype = iface_get_arptype(handle->fd, device, handle->errbuf);
+       if (arptype < 0)
+               return PCAP_ERROR;
+
+       /*
+        * Try to find the DLT_ type corresponding to that
+        * link-layer type.
+        */
+       map_arphrd_to_dlt(handle, arptype, 0);
+       if (handle->linktype == -1) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "unknown arptype %d", arptype);
+               return PCAP_ERROR;
+       }
+
+       /* Go to promisc mode if requested */
+
+       if (handle->opt.promisc) {
+               memset(&ifr, 0, sizeof(ifr));
+               strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+               if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                "SIOCGIFFLAGS: %s", pcap_strerror(errno));
+                       return PCAP_ERROR;
+               }
+               if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
+                       /*
+                        * Promiscuous mode isn't currently on,
+                        * so turn it on, and remember that
+                        * we should turn it off when the
+                        * pcap_t is closed.
+                        */
+
+                       /*
+                        * If we haven't already done so, arrange
+                        * to have "pcap_close_all()" called when
+                        * we exit.
+                        */
+                       if (!pcap_do_addexit(handle)) {
+                               /*
+                                * "atexit()" failed; don't put
+                                * the interface in promiscuous
+                                * mode, just give up.
+                                */
+                               return PCAP_ERROR;
+                       }
+
+                       ifr.ifr_flags |= IFF_PROMISC;
+                       if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                        "SIOCSIFFLAGS: %s",
+                                        pcap_strerror(errno));
+                               return PCAP_ERROR;
+                       }
+                       handle->md.must_do_on_close |= MUST_CLEAR_PROMISC;
+
+                       /*
+                        * Add this to the list of pcaps
+                        * to close when we exit.
+                        */
+                       pcap_add_to_pcaps_to_close(handle);
+               }
+       }
+
+       /*
+        * Compute the buffer size.
+        *
+        * We're using SOCK_PACKET, so this might be a 2.0[.x]
+        * kernel, and might require special handling - check.
+        */
+       if (uname(&utsname) < 0 ||
+           strncmp(utsname.release, "2.0", 3) == 0) {
+               /*
+                * Either we couldn't find out what kernel release
+                * this is, or it's a 2.0[.x] kernel.
+                *
+                * In the 2.0[.x] kernel, a "recvfrom()" on
+                * a SOCK_PACKET socket, with MSG_TRUNC set, will
+                * return the number of bytes read, so if we pass
+                * a length based on the snapshot length, it'll
+                * return the number of bytes from the packet
+                * copied to userland, not the actual length
+                * of the packet.
+                *
+                * This means that, for example, the IP dissector
+                * in tcpdump will get handed a packet length less
+                * than the length in the IP header, and will
+                * complain about "truncated-ip".
+                *
+                * So we don't bother trying to copy from the
+                * kernel only the bytes in which we're interested,
+                * but instead copy them all, just as the older
+                * versions of libpcap for Linux did.
+                *
+                * The buffer therefore needs to be big enough to
+                * hold the largest packet we can get from this
+                * device.  Unfortunately, we can't get the MRU
+                * of the network; we can only get the MTU.  The
+                * MTU may be too small, in which case a packet larger
+                * than the buffer size will be truncated *and* we
+                * won't get the actual packet size.
+                *
+                * However, if the snapshot length is larger than
+                * the buffer size based on the MTU, we use the
+                * snapshot length as the buffer size, instead;
+                * this means that with a sufficiently large snapshot
+                * length we won't artificially truncate packets
+                * to the MTU-based size.
+                *
+                * This mess just one of many problems with packet
+                * capture on 2.0[.x] kernels; you really want a
+                * 2.2[.x] or later kernel if you want packet capture
+                * to work well.
+                */
+               mtu = iface_get_mtu(handle->fd, device, handle->errbuf);
+               if (mtu == -1)
+                       return PCAP_ERROR;
+               handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
+               if (handle->bufsize < handle->snapshot)
+                       handle->bufsize = handle->snapshot;
+       } else {
+               /*
+                * This is a 2.2[.x] or later kernel.
+                *
+                * We can safely pass "recvfrom()" a byte count
+                * based on the snapshot length.
+                */
+               handle->bufsize = handle->snapshot;
+       }
+
+       /*
+        * Default value for offset to align link-layer payload
+        * on a 4-byte boundary.
+        */
+       handle->offset   = 0;
+
+       return 1;
+}
+
+/*
+ *  Bind the socket associated with FD to the given device using the
+ *  interface of the old kernels.
+ */
+static int
+iface_bind_old(int fd, const char *device, char *ebuf)
+{
+       struct sockaddr saddr;
+       int             err;
+       socklen_t       errlen = sizeof(err);
+
+       memset(&saddr, 0, sizeof(saddr));
+       strncpy(saddr.sa_data, device, sizeof(saddr.sa_data));
+       if (bind(fd, &saddr, sizeof(saddr)) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                        "bind: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       /* Any pending errors, e.g., network is down? */
+
+       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                       "getsockopt: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       if (err > 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                       "bind: %s", pcap_strerror(err));
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* ===== System calls available on all supported kernels ============== */
+
+/*
+ *  Query the kernel for the MTU of the given interface.
+ */
+static int
+iface_get_mtu(int fd, const char *device, char *ebuf)
+{
+       struct ifreq    ifr;
+
+       if (!device)
+               return BIGGER_THAN_ALL_MTUS;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+       if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                        "SIOCGIFMTU: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       return ifr.ifr_mtu;
+}
+
+/*
+ *  Get the hardware type of the given interface as ARPHRD_xxx constant.
+ */
+static int
+iface_get_arptype(int fd, const char *device, char *ebuf)
+{
+       struct ifreq    ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+       if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                        "SIOCGIFHWADDR: %s", pcap_strerror(errno));
+               if (errno == ENODEV) {
+                       /*
+                        * No such device.
+                        */
+                       return PCAP_ERROR_NO_SUCH_DEVICE;
+               }
+               return PCAP_ERROR;
+       }
+
+       return ifr.ifr_hwaddr.sa_family;
+}
+
+#ifdef SO_ATTACH_FILTER
+static int
+fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
+{
+       size_t prog_size;
+       register int i;
+       register struct bpf_insn *p;
+       struct bpf_insn *f;
+       int len;
+
+       /*
+        * Make a copy of the filter, and modify that copy if
+        * necessary.
+        */
+       prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len;
+       len = handle->fcode.bf_len;
+       f = (struct bpf_insn *)malloc(prog_size);
+       if (f == NULL) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "malloc: %s", pcap_strerror(errno));
+               return -1;
+       }
+       memcpy(f, handle->fcode.bf_insns, prog_size);
+       fcode->len = len;
+       fcode->filter = (struct sock_filter *) f;
+
+       for (i = 0; i < len; ++i) {
+               p = &f[i];
+               /*
+                * What type of instruction is this?
+                */
+               switch (BPF_CLASS(p->code)) {
+
+               case BPF_RET:
+                       /*
+                        * It's a return instruction; are we capturing
+                        * in memory-mapped mode?
+                        */
+                       if (!is_mmapped) {
+                               /*
+                                * No; is the snapshot length a constant,
+                                * rather than the contents of the
+                                * accumulator?
+                                */
+                               if (BPF_MODE(p->code) == BPF_K) {
+                                       /*
+                                        * Yes - if the value to be returned,
+                                        * i.e. the snapshot length, is
+                                        * anything other than 0, make it
+                                        * 65535, so that the packet is
+                                        * truncated by "recvfrom()",
+                                        * not by the filter.
+                                        *
+                                        * XXX - there's nothing we can
+                                        * easily do if it's getting the
+                                        * value from the accumulator; we'd
+                                        * have to insert code to force
+                                        * non-zero values to be 65535.
+                                        */
+                                       if (p->k != 0)
+                                               p->k = 65535;
+                               }
+                       }
+                       break;
+
+               case BPF_LD:
+               case BPF_LDX:
+                       /*
+                        * It's a load instruction; is it loading
+                        * from the packet?
+                        */
+                       switch (BPF_MODE(p->code)) {
+
+                       case BPF_ABS:
+                       case BPF_IND:
+                       case BPF_MSH:
+                               /*
+                                * Yes; are we in cooked mode?
+                                */
+                               if (handle->md.cooked) {
+                                       /*
+                                        * Yes, so we need to fix this
+                                        * instruction.
+                                        */
+                                       if (fix_offset(p) < 0) {
+                                               /*
+                                                * We failed to do so.
+                                                * Return 0, so our caller
+                                                * knows to punt to userland.
+                                                */
+                                               return 0;
+                                       }
+                               }
+                               break;
+                       }
+                       break;
+               }
+       }
+       return 1;       /* we succeeded */
+}
+
+static int
+fix_offset(struct bpf_insn *p)
+{
+       /*
+        * What's the offset?
+        */
+       if (p->k >= SLL_HDR_LEN) {
+               /*
+                * It's within the link-layer payload; that starts at an
+                * offset of 0, as far as the kernel packet filter is
+                * concerned, so subtract the length of the link-layer
+                * header.
+                */
+               p->k -= SLL_HDR_LEN;
+       } else if (p->k == 0) {
+               /*
+                * It's the packet type field; map it to the special magic
+                * kernel offset for that field.
+                */
+               p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+       } else if (p->k == 14) {
+               /*
+                * It's the protocol field; map it to the special magic
+                * kernel offset for that field.
+                */
+               p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+       } else if ((bpf_int32)(p->k) > 0) {
+               /*
+                * It's within the header, but it's not one of those
+                * fields; we can't do that in the kernel, so punt
+                * to userland.
+                */
+               return -1;
+       }
+       return 0;
+}
+
+static int
+set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
+{
+       int total_filter_on = 0;
+       int save_mode;
+       int ret;
+       int save_errno;
+
+       /*
+        * The socket filter code doesn't discard all packets queued
+        * up on the socket when the filter is changed; this means
+        * that packets that don't match the new filter may show up
+        * after the new filter is put onto the socket, if those
+        * packets haven't yet been read.
+        *
+        * This means, for example, that if you do a tcpdump capture
+        * with a filter, the first few packets in the capture might
+        * be packets that wouldn't have passed the filter.
+        *
+        * We therefore discard all packets queued up on the socket
+        * when setting a kernel filter.  (This isn't an issue for
+        * userland filters, as the userland filtering is done after
+        * packets are queued up.)
+        *
+        * To flush those packets, we put the socket in read-only mode,
+        * and read packets from the socket until there are no more to
+        * read.
+        *
+        * In order to keep that from being an infinite loop - i.e.,
+        * to keep more packets from arriving while we're draining
+        * the queue - we put the "total filter", which is a filter
+        * that rejects all packets, onto the socket before draining
+        * the queue.
+        *
+        * This code deliberately ignores any errors, so that you may
+        * get bogus packets if an error occurs, rather than having
+        * the filtering done in userland even if it could have been
+        * done in the kernel.
+        */
+       if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
+                      &total_fcode, sizeof(total_fcode)) == 0) {
+               char drain[1];
+
+               /*
+                * Note that we've put the total filter onto the socket.
+                */
+               total_filter_on = 1;
+
+               /*
+                * Save the socket's current mode, and put it in
+                * non-blocking mode; we drain it by reading packets
+                * until we get an error (which is normally a
+                * "nothing more to be read" error).
+                */
+               save_mode = fcntl(handle->fd, F_GETFL, 0);
+               if (save_mode != -1 &&
+                   fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) {
+                       while (recv(handle->fd, &drain, sizeof drain,
+                              MSG_TRUNC) >= 0)
+                               ;
+                       save_errno = errno;
+                       fcntl(handle->fd, F_SETFL, save_mode);
+                       if (save_errno != EAGAIN) {
+                               /* Fatal error */
+                               reset_kernel_filter(handle);
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                "recv: %s", pcap_strerror(save_errno));
+                               return -2;
+                       }
+               }
+       }
+
+       /*
+        * Now attach the new filter.
+        */
+       ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
+                        fcode, sizeof(*fcode));
+       if (ret == -1 && total_filter_on) {
+               /*
+                * Well, we couldn't set that filter on the socket,
+                * but we could set the total filter on the socket.
+                *
+                * This could, for example, mean that the filter was
+                * too big to put into the kernel, so we'll have to
+                * filter in userland; in any case, we'll be doing
+                * filtering in userland, so we need to remove the
+                * total filter so we see packets.
+                */
+               save_errno = errno;
+
+               /*
+                * XXX - if this fails, we're really screwed;
+                * we have the total filter on the socket,
+                * and it won't come off.  What do we do then?
+                */
+               reset_kernel_filter(handle);
+
+               errno = save_errno;
+       }
+       return ret;
+}
+
+static int
+reset_kernel_filter(pcap_t *handle)
+{
+       /*
+        * setsockopt() barfs unless it get a dummy parameter.
+        * valgrind whines unless the value is initialized,
+        * as it has no idea that setsockopt() ignores its
+        * parameter.
+        */
+       int dummy = 0;
+
+       return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
+                                  &dummy, sizeof(dummy));
+}
+#endif
diff --git a/pcap-namedb.h b/pcap-namedb.h
new file mode 100644 (file)
index 0000000..d0b2231
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006-10-04 18:13:32 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Some applications
+ * might expect to be able to include <pcap-namedb.h>.
+ */
+#include <pcap/namedb.h>
diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c
new file mode 100644 (file)
index 0000000..f9c6bef
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * Copyright (c) 2011 Jakub Zawadzki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <time.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+
+#include "pcap-netfilter-linux.h"
+
+#define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
+
+#define NFLOG_IFACE "nflog"
+
+static int
+nflog_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       const unsigned char *buf;
+       int count = 0;
+       int len;
+
+       /* ignore interrupt system call error */
+       do {
+               len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
+               if (handle->break_loop) {
+                       handle->break_loop = 0;
+                       return -2;
+               }
+       } while ((len == -1) && (errno == EINTR));
+
+       if (len < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
+               return -1;
+       }
+
+       buf = handle->buffer;
+       while (len >= NLMSG_SPACE(0)) {
+               const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
+               u_int32_t msg_len;
+
+               if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
+                       return -1;
+               }
+
+               if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && 
+                       NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) 
+               {
+                       const unsigned char *payload = NULL;
+                       struct pcap_pkthdr pkth;
+
+                       if (handle->linktype != DLT_NFLOG) {
+                               const struct nfattr *payload_attr = NULL;
+
+                               if (nlh->nlmsg_len < HDR_LENGTH) {
+                                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
+                                       return -1;
+                               }
+
+                               if (nlh->nlmsg_len > HDR_LENGTH) {
+                                       struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
+                                       int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);
+
+                                       while (NFA_OK(attr, attr_len)) {
+                                               switch (NFA_TYPE(attr)) {
+                                                       case NFULA_PAYLOAD:
+                                                               payload_attr = attr;
+                                                               break;
+                                               }
+                                               attr = NFA_NEXT(attr, attr_len);
+                                       }
+                               }
+
+                               if (payload_attr) {
+                                       payload = NFA_DATA(payload_attr);
+                                       pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr);
+                               }
+
+                       } else {
+                               payload = NLMSG_DATA(nlh);
+                               pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr));
+                       }
+
+                       if (payload) {
+                               /* pkth.caplen = min (payload_len, handle->snapshot); */
+
+                               gettimeofday(&pkth.ts, NULL);
+                               if (handle->fcode.bf_insns == NULL ||
+                                               bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) 
+                               {
+                                       handle->md.packets_read++;
+                                       callback(user, &pkth, payload);
+                                       count++;
+                               }
+                       }
+               }
+
+               msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
+               if (msg_len > len)
+                       msg_len = len;
+
+               len -= msg_len;
+               buf += msg_len;
+       }
+       return count;
+}
+
+static int
+netfilter_set_datalink(pcap_t *handle, int dlt)
+{
+       handle->linktype = dlt;
+       return 0;
+}
+
+static int
+netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+       stats->ps_recv = handle->md.packets_read;
+       stats->ps_drop = 0;
+       stats->ps_ifdrop = 0;
+       return 0;
+}
+
+static int
+netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
+       return (-1);
+}                           
+
+struct my_nfattr {
+       u_int16_t nfa_len;
+       u_int16_t nfa_type;
+       void *data;
+};
+
+static int
+nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
+{
+       char buf[1024] __attribute__ ((aligned));
+
+       struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
+       struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr));
+
+       struct sockaddr_nl snl;
+       static unsigned int seq_id;
+       
+       if (!seq_id)
+               seq_id = time(NULL);
+       ++seq_id;
+
+       nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
+       nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
+       nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+       nlh->nlmsg_pid = 0;     /* to kernel */
+       nlh->nlmsg_seq = seq_id;
+
+       nfg->nfgen_family = family;
+       nfg->version = NFNETLINK_V0;
+       nfg->res_id = htons(res_id);
+
+       if (mynfa) {
+               struct nfattr *nfa = (struct nfattr *) (buf + NLMSG_ALIGN(nlh->nlmsg_len));
+
+               nfa->nfa_type = mynfa->nfa_type;
+               nfa->nfa_len = NFA_LENGTH(mynfa->nfa_len);
+               memcpy(NFA_DATA(nfa), mynfa->data, mynfa->nfa_len);
+               nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + NFA_ALIGN(nfa->nfa_len);
+       }
+
+       memset(&snl, 0, sizeof(snl));
+       snl.nl_family = AF_NETLINK;
+
+       if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1)
+               return -1;
+
+       /* waiting for reply loop */
+       do {
+               socklen_t addrlen = sizeof(snl);
+               int len;
+
+               /* ignore interrupt system call error */
+               do {
+                       len = recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen);
+               } while ((len == -1) && (errno == EINTR));
+
+               if (len <= 0)
+                       return len;
+
+               if (addrlen != sizeof(snl) || snl.nl_family != AF_NETLINK) {
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               nlh = (struct nlmsghdr *) buf;
+               if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq)        /* if not from kernel or wrong sequence skip */
+                       continue;
+
+               while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
+                       if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) {
+                               if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
+                                       errno = EBADMSG;
+                                       return -1;
+                               }
+                               errno = -(*((int *)NLMSG_DATA(nlh)));
+                               return (errno == 0) ? 0 : -1;
+                       }
+                       nlh = NLMSG_NEXT(nlh, len);
+               }
+       } while (1);
+
+       return -1; /* never here */
+}
+
+static int
+nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int8_t family)
+{
+       struct nfulnl_msg_config_cmd msg;
+       struct my_nfattr nfa;
+
+       msg.command = cmd;
+
+       nfa.data = &msg;
+       nfa.nfa_type = NFULA_CFG_CMD;
+       nfa.nfa_len = sizeof(msg);
+
+       return nflog_send_config_msg(handle, family, group_id, &nfa);
+}
+
+static int 
+nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
+{
+       struct nfulnl_msg_config_mode msg;
+       struct my_nfattr nfa;
+
+       msg.copy_range = htonl(copy_range);
+       msg.copy_mode = copy_mode;
+
+       nfa.data = &msg;
+       nfa.nfa_type = NFULA_CFG_MODE;
+       nfa.nfa_len = sizeof(msg);
+
+       return nflog_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
+}
+
+static int
+nflog_activate(pcap_t* handle)
+{
+       const char *dev = handle->opt.source;
+       unsigned short groups[32];
+       int group_count = 0;
+       int i;
+
+       if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) {
+               dev += strlen(NFLOG_IFACE);
+
+               /* nflog:30,33,42 looks nice, allow it */
+               if (*dev == ':')
+                       dev++;
+
+               while (*dev) {
+                       long int group_id;
+                       char *end_dev;
+
+                       if (group_count == 32) {
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                               "Maximum 32 netfilter groups! dev: %s", 
+                                               handle->opt.source);
+                               return PCAP_ERROR;
+                       }
+
+                       group_id = strtol(dev, &end_dev, 0);
+                       if (end_dev != dev) {
+                               if (group_id < 0 || group_id > 65535) {
+                                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                                       "Netfilter group range from 0 to 65535 (got %ld)",
+                                                       group_id);
+                                       return PCAP_ERROR;
+                               }
+
+                               groups[group_count++] = (unsigned short) group_id;
+                               dev = end_dev;
+                       }
+                       if (*dev != ',')
+                               break;
+                       dev++;
+               }
+       }
+
+       if (*dev) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "Can't get netfilter group(s) index from %s", 
+                               handle->opt.source);
+               return PCAP_ERROR;
+       }
+
+       /* if no groups, add default: 0 */
+       if (!group_count) {
+               groups[0] = 0;
+               group_count = 1;
+       }
+
+       /* Initialize some components of the pcap structure. */
+       handle->bufsize = 128 + handle->snapshot;
+       handle->offset = 0;
+       handle->linktype = DLT_NFLOG;
+       handle->read_op = nflog_read_linux;
+       handle->inject_op = netfilter_inject_linux;
+       handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+       handle->setdirection_op = NULL;
+       handle->set_datalink_op = NULL;
+       handle->set_datalink_op = netfilter_set_datalink;
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->stats_op = netfilter_stats_linux;
+
+       /* Create netlink socket */
+       handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+       if (handle->fd < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno));
+               return PCAP_ERROR;
+       }
+
+       handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+       if (handle->dlt_list != NULL) {
+               handle->dlt_list[0] = DLT_NFLOG;
+               handle->dlt_list[1] = DLT_IPV4;
+               handle->dlt_count = 2;
+       }
+
+       handle->buffer = malloc(handle->bufsize);
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno));
+               goto close_fail;
+       }
+
+       if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
+               goto close_fail;
+       }
+
+       if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
+               goto close_fail;
+       }
+
+       /* Bind socket to the nflog groups */
+       for (i = 0; i < group_count; i++) {
+               if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
+                       goto close_fail;
+               }
+
+               if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
+                       goto close_fail;
+               }
+       }
+
+       if (handle->opt.rfmon) {
+               /*
+                * Monitor mode doesn't apply to netfilter devices.
+                */
+               pcap_cleanup_live_common(handle);
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       if (handle->opt.buffer_size != 0) {
+               /*
+                * Set the socket buffer size to the specified value.
+                */
+               if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
+                       goto close_fail;
+               }
+       }
+
+       handle->selectable_fd = handle->fd;
+       return 0;
+
+close_fail:
+       pcap_cleanup_live_common(handle);
+       return PCAP_ERROR;
+}
+
+pcap_t *
+nflog_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = nflog_activate;
+       return (p);
+}
+
+int 
+netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+       pcap_if_t *found_dev = *alldevsp;
+       int sock;
+       
+       sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+       if (sock < 0) {
+               /* if netlink is not supported this is not fatal */
+               if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
+                       return 0;
+               snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
+                       errno, pcap_strerror(errno));
+               return -1;
+       }
+       close(sock);
+
+       if (pcap_add_if(&found_dev, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0)
+               return -1;
+       return 0;
+}
+
diff --git a/pcap-netfilter-linux.h b/pcap-netfilter-linux.h
new file mode 100644 (file)
index 0000000..dd76b8a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Jakub Zawadzki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Prototypes for netlink-related functions
+ */
+int netfilter_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *nflog_create(const char *device, char *ebuf);
diff --git a/pcap-nit.c b/pcap-nit.c
new file mode 100644 (file)
index 0000000..b799549
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.62 2008-04-14 20:40:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/nit.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * The chunk size for NIT.  This is the amount of buffering
+ * done for read calls.
+ */
+#define CHUNKSIZE (2*1024)
+
+/*
+ * The total buffer space used by NIT.
+ */
+#define BUFSPACE (4*CHUNKSIZE)
+
+/* Forwards */
+static int nit_setflags(int, int, int, char *);
+
+static int
+pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
+{
+
+       /*
+        * "ps_recv" counts packets handed to the filter, not packets
+        * that passed the filter.  As filtering is done in userland,
+        * this does not include packets dropped because we ran out
+        * of buffer space.
+        *
+        * "ps_drop" presumably counts packets dropped by the socket
+        * because of flow control requirements or resource exhaustion;
+        * it doesn't count packets dropped by the interface driver.
+        * As filtering is done in userland, it counts packets regardless
+        * of whether they would've passed the filter.
+        *
+        * These statistics don't include packets not yet read from the
+        * kernel by libpcap or packets not yet read from libpcap by the
+        * application.
+        */
+       *ps = p->md.stat;
+       return (0);
+}
+
+static int
+pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc, n;
+       register u_char *bp, *cp, *ep;
+       register struct nit_hdr *nh;
+       register int caplen;
+
+       cc = p->cc;
+       if (cc == 0) {
+               cc = read(p->fd, (char *)p->buffer, p->bufsize);
+               if (cc < 0) {
+                       if (errno == EWOULDBLOCK)
+                               return (0);
+                       snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+                               pcap_strerror(errno));
+                       return (-1);
+               }
+               bp = p->buffer;
+       } else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.  The increment expression
+        * rounds up to the next int boundary past the end of
+        * the previous packet.
+        */
+       n = 0;
+       ep = bp + cc;
+       while (bp < ep) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else {
+                               p->cc = ep - bp;
+                               p->bp = bp;
+                               return (n);
+                       }
+               }
+
+               nh = (struct nit_hdr *)bp;
+               cp = bp + sizeof(*nh);
+
+               switch (nh->nh_state) {
+
+               case NIT_CATCH:
+                       break;
+
+               case NIT_NOMBUF:
+               case NIT_NOCLUSTER:
+               case NIT_NOSPACE:
+                       p->md.stat.ps_drop = nh->nh_dropped;
+                       continue;
+
+               case NIT_SEQNO:
+                       continue;
+
+               default:
+                       snprintf(p->errbuf, sizeof(p->errbuf),
+                           "bad nit state %d", nh->nh_state);
+                       return (-1);
+               }
+               ++p->md.stat.ps_recv;
+               bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
+                   sizeof(int) - 1) & ~(sizeof(int) - 1));
+
+               caplen = nh->nh_wirelen;
+               if (caplen > p->snapshot)
+                       caplen = p->snapshot;
+               if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
+                       struct pcap_pkthdr h;
+                       h.ts = nh->nh_timestamp;
+                       h.len = nh->nh_wirelen;
+                       h.caplen = caplen;
+                       (*callback)(user, &h, cp);
+                       if (++n >= cnt && cnt > 0) {
+                               p->cc = ep - bp;
+                               p->bp = bp;
+                               return (n);
+                       }
+               }
+       }
+       p->cc = 0;
+       return (n);
+}
+
+static int
+pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
+{
+       struct sockaddr sa;
+       int ret;
+
+       memset(&sa, 0, sizeof(sa));
+       strncpy(sa.sa_data, device, sizeof(sa.sa_data));
+       ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (ret);
+}                           
+
+static int
+nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
+{
+       struct nit_ioc nioc;
+
+       memset(&nioc, 0, sizeof(nioc));
+       nioc.nioc_bufspace = BUFSPACE;
+       nioc.nioc_chunksize = CHUNKSIZE;
+       nioc.nioc_typetomatch = NT_ALLTYPES;
+       nioc.nioc_snaplen = p->snapshot;
+       nioc.nioc_bufalign = sizeof(int);
+       nioc.nioc_bufoffset = 0;
+
+       if (to_ms != 0) {
+               nioc.nioc_flags |= NF_TIMEOUT;
+               nioc.nioc_timeout.tv_sec = to_ms / 1000;
+               nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
+       }
+       if (promisc)
+               nioc.nioc_flags |= NF_PROMISC;
+
+       if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+static int
+pcap_activate_nit(pcap_t *p)
+{
+       int fd;
+       struct sockaddr_nit snit;
+
+       if (p->opt.rfmon) {
+               /*
+                * No monitor mode on SunOS 3.x or earlier (no
+                * Wi-Fi *devices* for the hardware that supported
+                * them!).
+                */
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+       if (p->snapshot < 96)
+               /*
+                * NIT requires a snapshot length of at least 96.
+                */
+               p->snapshot = 96;
+
+       memset(p, 0, sizeof(*p));
+       p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
+       if (fd < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "socket: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       snit.snit_family = AF_NIT;
+       (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ);
+
+       if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
+               goto bad;
+       }
+       nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf);
+
+       /*
+        * NIT supports only ethernets.
+        */
+       p->linktype = DLT_EN10MB;
+
+       p->bufsize = BUFSPACE;
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+               goto bad;
+       }
+
+       /*
+        * "p->fd" is a socket, so "select()" should work on it.
+        */
+       p->selectable_fd = p->fd;
+
+       /*
+        * This is (presumably) a real Ethernet capture; give it a
+        * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+        * that an application can let you choose it, in case you're
+        * capturing DOCSIS traffic that a Cisco Cable Modem
+        * Termination System is putting out onto an Ethernet (it
+        * doesn't put an Ethernet header onto the wire, it puts raw
+        * DOCSIS frames out on the wire inside the low-level
+        * Ethernet framing).
+        */
+       p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+       /*
+        * If that fails, just leave the list empty.
+        */
+       if (p->dlt_list != NULL) {
+               p->dlt_list[0] = DLT_EN10MB;
+               p->dlt_list[1] = DLT_DOCSIS;
+               p->dlt_count = 2;
+       }
+
+       p->read_op = pcap_read_nit;
+       p->inject_op = pcap_inject_nit;
+       p->setfilter_op = install_bpf_program;  /* no kernel filtering */
+       p->setdirection_op = NULL;      /* Not implemented. */
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_nit;
+
+       return (0);
+ bad:
+       pcap_cleanup_live_common(p);
+       return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_nit;
+       return (p);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
diff --git a/pcap-null.c b/pcap-null.c
new file mode 100644 (file)
index 0000000..2d271eb
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.22 2008-04-04 19:37:45 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+
+#include <string.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+static char nosup[] = "live packet capture not supported on this system";
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
+       return (NULL);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
diff --git a/pcap-pf.c b/pcap-pf.c
new file mode 100644 (file)
index 0000000..d8326df
--- /dev/null
+++ b/pcap-pf.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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.
+ *
+ * packet filter subroutines for tcpdump
+ *     Extraction/creation by Jeffrey Mogul, DECWRL
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.97 2008-04-14 20:40:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <net/pfilt.h>
+
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we need various BPF ioctls from it.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <net/bpf.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
+
+/*
+ * BUFSPACE is the size in bytes of the packet read buffer.  Most tcpdump
+ * applications aren't going to need more than 200 bytes of packet header
+ * and the read shouldn't return more packets than packetfilter's internal
+ * queue limit (bounded at 256).
+ */
+#define BUFSPACE (200 * 256)
+
+static int
+pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
+{
+       register u_char *p, *bp;
+       register int cc, n, buflen, inc;
+       register struct enstamp *sp;
+#ifdef LBL_ALIGN
+       struct enstamp stamp;
+#endif
+#ifdef PCAP_FDDIPAD
+       register int pad;
+#endif
+
+ again:
+       cc = pc->cc;
+       if (cc == 0) {
+               cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize);
+               if (cc < 0) {
+                       if (errno == EWOULDBLOCK)
+                               return (0);
+                       if (errno == EINVAL &&
+                           lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) {
+                               /*
+                                * Due to a kernel bug, after 2^31 bytes,
+                                * the kernel file offset overflows and
+                                * read fails with EINVAL. The lseek()
+                                * to 0 will fix things.
+                                */
+                               (void)lseek(pc->fd, 0L, SEEK_SET);
+                               goto again;
+                       }
+                       snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
+                               pcap_strerror(errno));
+                       return (-1);
+               }
+               bp = pc->buffer + pc->offset;
+       } else
+               bp = pc->bp;
+       /*
+        * Loop through each packet.
+        */
+       n = 0;
+#ifdef PCAP_FDDIPAD
+       pad = pc->fddipad;
+#endif
+       while (cc > 0) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (pc->break_loop) {
+                       if (n == 0) {
+                               pc->break_loop = 0;
+                               return (-2);
+                       } else {
+                               pc->cc = cc;
+                               pc->bp = bp;
+                               return (n);
+                       }
+               }
+               if (cc < sizeof(*sp)) {
+                       snprintf(pc->errbuf, sizeof(pc->errbuf),
+                           "pf short read (%d)", cc);
+                       return (-1);
+               }
+#ifdef LBL_ALIGN
+               if ((long)bp & 3) {
+                       sp = &stamp;
+                       memcpy((char *)sp, (char *)bp, sizeof(*sp));
+               } else
+#endif
+                       sp = (struct enstamp *)bp;
+               if (sp->ens_stamplen != sizeof(*sp)) {
+                       snprintf(pc->errbuf, sizeof(pc->errbuf),
+                           "pf short stamplen (%d)",
+                           sp->ens_stamplen);
+                       return (-1);
+               }
+
+               p = bp + sp->ens_stamplen;
+               buflen = sp->ens_count;
+               if (buflen > pc->snapshot)
+                       buflen = pc->snapshot;
+
+               /* Calculate inc before possible pad update */
+               inc = ENALIGN(buflen + sp->ens_stamplen);
+               cc -= inc;
+               bp += inc;
+               pc->md.TotPkts++;
+               pc->md.TotDrops += sp->ens_dropped;
+               pc->md.TotMissed = sp->ens_ifoverflows;
+               if (pc->md.OrigMissed < 0)
+                       pc->md.OrigMissed = pc->md.TotMissed;
+
+               /*
+                * Short-circuit evaluation: if using BPF filter
+                * in kernel, no need to do it now - we already know
+                * the packet passed the filter.
+                *
+#ifdef PCAP_FDDIPAD
+                * Note: the filter code was generated assuming
+                * that pc->fddipad was the amount of padding
+                * before the header, as that's what's required
+                * in the kernel, so we run the filter before
+                * skipping that padding.
+#endif
+                */
+               if (pc->md.use_bpf ||
+                   bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
+                       struct pcap_pkthdr h;
+                       pc->md.TotAccepted++;
+                       h.ts = sp->ens_tstamp;
+#ifdef PCAP_FDDIPAD
+                       h.len = sp->ens_count - pad;
+#else
+                       h.len = sp->ens_count;
+#endif
+#ifdef PCAP_FDDIPAD
+                       p += pad;
+                       buflen -= pad;
+#endif
+                       h.caplen = buflen;
+                       (*callback)(user, &h, p);
+                       if (++n >= cnt && cnt > 0) {
+                               pc->cc = cc;
+                               pc->bp = bp;
+                               return (n);
+                       }
+               }
+       }
+       pc->cc = 0;
+       return (n);
+}
+
+static int
+pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
+{
+       int ret;
+
+       ret = write(p->fd, buf, size);
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (ret);
+}                           
+
+static int
+pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
+{
+
+       /*
+        * If packet filtering is being done in the kernel:
+        *
+        *      "ps_recv" counts only packets that passed the filter.
+        *      This does not include packets dropped because we
+        *      ran out of buffer space.  (XXX - perhaps it should,
+        *      by adding "ps_drop" to "ps_recv", for compatibility
+        *      with some other platforms.  On the other hand, on
+        *      some platforms "ps_recv" counts only packets that
+        *      passed the filter, and on others it counts packets
+        *      that didn't pass the filter....)
+        *
+        *      "ps_drop" counts packets that passed the kernel filter
+        *      (if any) but were dropped because the input queue was
+        *      full.
+        *
+        *      "ps_ifdrop" counts packets dropped by the network
+        *      inteface (regardless of whether they would have passed
+        *      the input filter, of course).
+        *
+        * If packet filtering is not being done in the kernel:
+        *
+        *      "ps_recv" counts only packets that passed the filter.
+        *
+        *      "ps_drop" counts packets that were dropped because the
+        *      input queue was full, regardless of whether they passed
+        *      the userland filter.
+        *
+        *      "ps_ifdrop" counts packets dropped by the network
+        *      inteface (regardless of whether they would have passed
+        *      the input filter, of course).
+        *
+        * These statistics don't include packets not yet read from
+        * the kernel by libpcap, but they may include packets not
+        * yet read from libpcap by the application.
+        */
+       ps->ps_recv = p->md.TotAccepted;
+       ps->ps_drop = p->md.TotDrops;
+       ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
+       return (0);
+}
+
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS     143
+#endif
+
+static int
+pcap_activate_pf(pcap_t *p)
+{
+       short enmode;
+       int backlog = -1;       /* request the most */
+       struct enfilter Filter;
+       struct endevp devparams;
+
+       /*
+        * Initially try a read/write open (to allow the inject
+        * method to work).  If that fails due to permission
+        * issues, fall back to read-only.  This allows a
+        * non-root user to be granted specific access to pcap
+        * capabilities via file permissions.
+        *
+        * XXX - we should have an API that has a flag that
+        * controls whether to open read-only or read-write,
+        * so that denial of permission to send (or inability
+        * to send, if sending packets isn't supported on
+        * the device in question) can be indicated at open
+        * time.
+        *
+        * XXX - we assume here that "pfopen()" does not, in fact, modify
+        * its argument, even though it takes a "char *" rather than a
+        * "const char *" as its first argument.  That appears to be
+        * the case, at least on Digital UNIX 4.0.
+        */
+       p->fd = pfopen(p->opt.source, O_RDWR);
+       if (p->fd == -1 && errno == EACCES)
+               p->fd = pfopen(p->opt.source, O_RDONLY);
+       if (p->fd < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
+your system may not be properly configured; see the packetfilter(4) man page\n",
+                       p->opt.source, pcap_strerror(errno));
+               goto bad;
+       }
+       p->md.OrigMissed = -1;
+       enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
+       if (p->opt.promisc)
+               enmode |= ENPROMISC;
+       if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+#ifdef ENCOPYALL
+       /* Try to set COPYALL mode so that we see packets to ourself */
+       enmode = ENCOPYALL;
+       (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */
+#endif
+       /* set the backlog */
+       if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       /* discover interface type */
+       if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       /* HACK: to compile prior to Ultrix 4.2 */
+#ifndef        ENDT_FDDI
+#define        ENDT_FDDI       4
+#endif
+       switch (devparams.end_dev_type) {
+
+       case ENDT_10MB:
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+               break;
+
+       case ENDT_FDDI:
+               p->linktype = DLT_FDDI;
+               break;
+
+#ifdef ENDT_SLIP
+       case ENDT_SLIP:
+               p->linktype = DLT_SLIP;
+               break;
+#endif
+
+#ifdef ENDT_PPP
+       case ENDT_PPP:
+               p->linktype = DLT_PPP;
+               break;
+#endif
+
+#ifdef ENDT_LOOPBACK
+       case ENDT_LOOPBACK:
+               /*
+                * It appears to use Ethernet framing, at least on
+                * Digital UNIX 4.0.
+                */
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               break;
+#endif
+
+#ifdef ENDT_TRN
+       case ENDT_TRN:
+               p->linktype = DLT_IEEE802;
+               break;
+#endif
+
+       default:
+               /*
+                * XXX - what about ENDT_IEEE802?  The pfilt.h header
+                * file calls this "IEEE 802 networks (non-Ethernet)",
+                * but that doesn't specify a specific link layer type;
+                * it could be 802.4, or 802.5 (except that 802.5 is
+                * ENDT_TRN), or 802.6, or 802.11, or....  That's why
+                * DLT_IEEE802 was hijacked to mean Token Ring in various
+                * BSDs, and why we went along with that hijacking.
+                *
+                * XXX - what about ENDT_HDLC and ENDT_NULL?
+                * Presumably, as ENDT_OTHER is just "Miscellaneous
+                * framing", there's not much we can do, as that
+                * doesn't specify a particular type of header.
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "unknown data-link type %u", devparams.end_dev_type);
+               goto bad;
+       }
+       /* set truncation */
+#ifdef PCAP_FDDIPAD
+       if (p->linktype == DLT_FDDI) {
+               p->fddipad = PCAP_FDDIPAD;
+
+               /* packetfilter includes the padding in the snapshot */
+               p->snapshot += PCAP_FDDIPAD;
+       } else
+               p->fddipad = 0;
+#endif
+       if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       /* accept all packets */
+       memset(&Filter, 0, sizeof(Filter));
+       Filter.enf_Priority = 37;       /* anything > 2 */
+       Filter.enf_FilterLen = 0;       /* means "always true" */
+       if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       if (p->md.timeout != 0) {
+               struct timeval timeout;
+               timeout.tv_sec = p->md.timeout / 1000;
+               timeout.tv_usec = (p->md.timeout * 1000) % 1000000;
+               if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
+                               pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+
+       p->bufsize = BUFSPACE;
+       p->buffer = (u_char*)malloc(p->bufsize + p->offset);
+       if (p->buffer == NULL) {
+               strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+               goto bad;
+       }
+
+       /*
+        * "select()" and "poll()" work on packetfilter devices.
+        */
+       p->selectable_fd = p->fd;
+
+       p->read_op = pcap_read_pf;
+       p->inject_op = pcap_inject_pf;
+       p->setfilter_op = pcap_setfilter_pf;
+       p->setdirection_op = NULL;      /* Not implemented. */
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_pf;
+
+       return (0);
+ bad:
+       pcap_cleanup_live_common(p);
+       return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_pf;
+       return (p);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
+
+static int
+pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
+{
+       struct bpf_version bv;
+
+       /*
+        * See if BIOCVERSION works.  If not, we assume the kernel doesn't
+        * support BPF-style filters (it's not documented in the bpf(7)
+        * or packetfiler(7) man pages, but the code used to fail if
+        * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do
+        * kernel filtering in DU 4.0, so presumably BIOCVERSION works
+        * there, at least).
+        */
+       if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) {
+               /*
+                * OK, we have the version of the BPF interpreter;
+                * is it the same major version as us, and the same
+                * or better minor version?
+                */
+               if (bv.bv_major == BPF_MAJOR_VERSION &&
+                   bv.bv_minor >= BPF_MINOR_VERSION) {
+                       /*
+                        * Yes.  Try to install the filter.
+                        */
+                       if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
+                               snprintf(p->errbuf, sizeof(p->errbuf),
+                                   "BIOCSETF: %s", pcap_strerror(errno));
+                               return (-1);
+                       }
+
+                       /*
+                        * OK, that succeeded.  We're doing filtering in
+                        * the kernel.  (We assume we don't have a
+                        * userland filter installed - that'd require
+                        * a previous version check to have failed but
+                        * this one to succeed.)
+                        *
+                        * XXX - this message should be supplied to the
+                        * application as a warning of some sort,
+                        * except that if it's a GUI application, it's
+                        * not clear that it should be displayed in
+                        * a window to annoy the user.
+                        */
+                       fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
+                       p->md.use_bpf = 1;
+
+                       /*
+                        * Discard any previously-received packets,
+                        * as they might have passed whatever filter
+                        * was formerly in effect, but might not pass
+                        * this filter (BIOCSETF discards packets buffered
+                        * in the kernel, so you can lose packets in any
+                        * case).
+                        */
+                       p->cc = 0;
+                       return (0);
+               }
+
+               /*
+                * We can't use the kernel's BPF interpreter; don't give
+                * up, just log a message and be inefficient.
+                *
+                * XXX - this should really be supplied to the application
+                * as a warning of some sort.
+                */
+               fprintf(stderr,
+           "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n",
+                   BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+                   bv.bv_major, bv.bv_minor);
+       }
+
+       /*
+        * We couldn't do filtering in the kernel; do it in userland.
+        */
+       if (install_bpf_program(p, fp) < 0)
+               return (-1);
+
+       /*
+        * XXX - this message should be supplied by the application as
+        * a warning of some sort.
+        */
+       fprintf(stderr, "tcpdump: Filtering in user process\n");
+       p->md.use_bpf = 0;
+       return (0);
+}
diff --git a/pcap-savefile.manfile.in b/pcap-savefile.manfile.in
new file mode 100644 (file)
index 0000000..907559c
--- /dev/null
@@ -0,0 +1,127 @@
+'\" t
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-savefile.manfile.in,v 1.2 2008-10-24 07:33:50 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "21 October 2008"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles. 
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header.  The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version  Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file.  The first field in the per-file header is a 4-byte
+magic number, with the value 0xa1b2c3d4.  The magic number, when read by
+a host with the same byte order as the host that wrote the file, will
+have the value 0xa1b2c3d4, and, when read by a host with the opposite
+byte order as the host that wrote the file, will have the value
+0xd4c3b2a1.  That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (@MAN_MISC_INFO@)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data.  The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file.  The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds since that second.  Following that are a 4-byte value
+giving the number of bytes of captured data that follow the per-packet
+header and a 4-byte value giving the number of bytes that would have
+been present had the packet not been truncated by the snapshot length. 
+The two lengths will be equal if the number of bytes of packet data are
+less than or equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/pcap-septel.c b/pcap-septel.c
new file mode 100644 (file)
index 0000000..8cc2403
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * pcap-septel.c: Packet capture interface for Intel/Septel card.
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible.  This code is compiled in several different ways depending on
+ * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined.  If HAVE_SEPTEL_API is
+ * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is
+ * defined then the 'septel_' function calls are renamed to 'pcap_'
+ * equivalents.  If SEPTEL_ONLY is not defined then nothing is altered - the
+ * septel_ functions will be called as required from their
+ * pcap-linux/equivalents.
+ *
+ * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
+ * (+961 3 485243)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.4 2008-04-14 20:40:58 guy Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_SEPTEL_API
+#include <msg.h>
+#include <ss7_inc.h>
+#include <sysgct.h>
+#include <pack.h>
+#include <system.h>
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef SEPTEL_ONLY
+/* This code is required when compiling for a Septel device only. */
+#include "pcap-septel.h"
+
+/* Replace septel function names with pcap equivalent. */
+#define septel_create pcap_create
+#define septel_platform_finddevs pcap_platform_finddevs
+#endif /* SEPTEL_ONLY */
+
+static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
+static int septel_stats(pcap_t *p, struct pcap_stat *ps);
+static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+
+/*
+ *  Read at most max_packets from the capture queue and call the callback
+ *  for each of them. Returns the number of packets handled, -1 if an
+ *  error occured, or -2 if we were told to break out of the loop.
+ */
+static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
+
+  HDR *h;
+  MSG *m;
+  int processed = 0 ;
+  int t = 0 ;
+
+  /* identifier for the message queue of the module(upe) from which we are capturing
+   * packets.These IDs are defined in system.txt . By default it is set to 0x2d
+   * so change it to 0xdd for technical reason and therefore the module id for upe becomes:
+   * LOCAL        0xdd           * upe - Example user part task */
+  unsigned int id = 0xdd;
+
+  /* process the packets */
+  do  {
+
+    unsigned short packet_len = 0;
+    int caplen = 0;
+    int counter = 0;
+    struct pcap_pkthdr   pcap_header;
+    u_char *dp ;
+
+    /*
+     * Has "pcap_breakloop()" been called?
+     */
+loop:
+    if (p->break_loop) {
+      /*
+       * Yes - clear the flag that indicates that
+       * it has, and return -2 to indicate that
+       * we were told to break out of the loop.
+       */
+      p->break_loop = 0;
+      return -2;
+    }
+
+    /*repeat until a packet is read
+     *a NULL message means :
+     * when no packet is in queue or all packets in queue already read */
+    do  {
+      /* receive packet in non-blocking mode
+       * GCT_grab is defined in the septel library software */
+      h = GCT_grab(id);
+
+      m = (MSG*)h;
+      /* a couter is added here to avoid an infinite loop
+       * that will cause our capture program GUI to freeze while waiting
+       * for a packet*/
+      counter++ ;
+
+    }
+    while  ((m == NULL)&& (counter< 100)) ;
+
+    if (m != NULL) {
+
+      t = h->type ;
+
+      /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/
+      /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND
+       * for 0x8f01? */
+      if ((t != 0xcf00) && (t != 0x8f01)) {
+        relm(h);
+        goto loop ;
+      }
+
+      /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */
+      dp = get_param(m);/* get pointer to MSG parameter area (m->param) */
+      packet_len = m->len;
+      caplen =  p->snapshot ;
+
+
+      if (caplen > packet_len) {
+
+        caplen = packet_len;
+      }
+      /* Run the packet filter if there is one. */
+      if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+
+
+        /*  get a time stamp , consisting of :
+         *
+         *  pcap_header.ts.tv_sec:
+         *  ----------------------
+         *   a UNIX format time-in-seconds when he packet was captured,
+         *   i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT)
+         *
+         *  pcap_header.ts.tv_usec :
+         *  ------------------------
+         *   the number of microseconds since that second
+         *   when the packet was captured
+         */
+
+        (void)gettimeofday(&pcap_header.ts, NULL);
+
+        /* Fill in our own header data */
+        pcap_header.caplen = caplen;
+        pcap_header.len = packet_len;
+
+        /* Count the packet. */
+        p->md.stat.ps_recv++;
+
+        /* Call the user supplied callback function */
+        callback(user, &pcap_header, dp);
+
+        processed++ ;
+
+      }
+      /* after being processed the packet must be
+       *released in order to receive another one */
+      relm(h);
+    }else
+      processed++;
+
+  }
+  while (processed < cnt) ;
+
+  return processed ;
+}
+
+
+static int
+septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+  strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
+          PCAP_ERRBUF_SIZE);
+  return (-1);
+}
+
+/*
+ *  Activate a handle for a live capture from the given Septel device.  Always pass a NULL device
+ *  The promisc flag is ignored because Septel cards have built-in tracing.
+ *  The timeout is also ignored as it is not supported in hardware.
+ *
+ *  See also pcap(3).
+ */
+static pcap_t *septel_activate(pcap_t* handle) {
+  /* Initialize some components of the pcap structure. */  
+  handle->linktype = DLT_MTP2;
+  
+  handle->bufsize = 0;
+
+  /*
+   * "select()" and "poll()" don't work on Septel queues
+   */
+  handle->selectable_fd = -1;
+
+  handle->read_op = septel_read;
+  handle->inject_op = septel_inject;
+  handle->setfilter_op = septel_setfilter;
+  handle->set_datalink_op = NULL; /* can't change data link type */
+  handle->getnonblock_op = pcap_getnonblock_fd;
+  handle->setnonblock_op = septel_setnonblock;
+  handle->stats_op = septel_stats;
+
+  return 0;
+}
+
+pcap_t *septel_create(const char *device, char *ebuf) {
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return NULL;
+
+       p->activate_op = septel_activate;
+       return p;
+}
+
+static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
+  /*p->md.stat.ps_recv = 0;*/
+  /*p->md.stat.ps_drop = 0;*/
+  
+  *ps = p->md.stat;
+  return 0;
+}
+
+
+int
+septel_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
+{
+unsigned char *p;
+  const char description[512]= "Intel/Septel device";
+  char name[512]="septel" ;
+  int ret = 0;
+  pcap_add_if(devlistp,name,0,description,errbuf);
+
+  return (ret); 
+}
+
+
+/*
+ * Installs the given bpf filter program in the given pcap structure.  There is
+ * no attempt to store the filter in kernel memory as that is not supported
+ * with Septel cards.
+ */
+static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
+  if (!p)
+    return -1;
+  if (!fp) {
+    strncpy(p->errbuf, "setfilter: No filter specified",
+           sizeof(p->errbuf));
+    return -1;
+  }
+
+  /* Make our private copy of the filter */
+
+  if (install_bpf_program(p, fp) < 0) {
+    snprintf(p->errbuf, sizeof(p->errbuf),
+            "malloc: %s", pcap_strerror(errno));
+    return -1;
+  }
+
+  p->md.use_bpf = 0;
+
+  return (0);
+}
+
+
+static int
+septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+  return (0);
+}
diff --git a/pcap-septel.h b/pcap-septel.h
new file mode 100644 (file)
index 0000000..227d056
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * pcap-septel.c: Packet capture interface for Intel Septel card
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible.  This code is only needed when compiling in the Intel/Septel
+ * card code at the same time as another type of device.
+ *
+ * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
+ * (+961 3 485343);
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.2 2008-04-04 19:37:45 guy Exp $
+ */
+
+pcap_t *septel_create(const char *device, char *ebuf);
+
diff --git a/pcap-sita.c b/pcap-sita.c
new file mode 100644 (file)
index 0000000..971f8b0
--- /dev/null
@@ -0,0 +1,980 @@
+/*
+ *  pcap-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ *  Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ *  License: BSD
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of the authors may not be used to endorse or promote
+ *     products derived from this software without specific prior
+ *     written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: pcap-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "pcap-int.h"
+
+#include "pcap-sita.h"
+
+       /* non-configureable manifests follow */
+
+#define IOP_SNIFFER_PORT       49152                   /* TCP port on the IOP used for 'distributed pcap' usage */
+#define MAX_LINE_SIZE          255                             /* max size of a buffer/line in /etc/hosts we allow */
+#define MAX_CHASSIS                    8                               /* number of chassis in an ACN site */
+#define MAX_GEOSLOT                    8                               /* max number of access units in an ACN site */
+
+#define FIND                   0
+#define LIVE                   1
+
+typedef struct iface {
+       struct iface    *next;                                  /* a pointer to the next interface */
+       char                    *name;                                  /* this interface's name on Wireshark */
+       char                    *IOPname;                               /* this interface's name on an IOP */
+       uint32_t                iftype;                                 /* the type of interface (DLT values) */
+} iface_t;
+
+typedef struct unit {
+       char                            *ip;                            /* this unit's IP address (as extracted from /etc/hosts) */
+       int                                     fd;                                     /* the connection to this unit (if it exists) */
+       int                                     find_fd;                        /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
+       int                                     first_time;                     /* 0 = just opened via acn_open_live(),  ie. the first time, NZ = nth time */
+       struct sockaddr_in      *serv_addr;                     /* the address control block for comms to this unit */
+       int                                     chassis;
+       int                                     geoslot;
+       iface_t                         *iface;                         /* a pointer to a linked list of interface structures */
+       char                            *imsg;                          /* a pointer to an inbound message */
+       int                                     len;                            /* the current size of the inbound message */
+} unit_t;
+
+static char                    *errorString;
+static unit_t          units[MAX_CHASSIS+1][MAX_GEOSLOT+1];    /* we use indexes of 1 through 8, but we reserve/waste index 0 */
+static fd_set          readfds;                                                                /* a place to store the file descriptors for the connections to the IOPs */
+static fd_set          working_set;
+static int                     max_fs;
+static char                    static_buf[32];
+
+pcap_if_t                      *acn_if_list;                                                   /* pcap's list of available interfaces */
+
+static void dump_interface_list(void) {
+       pcap_if_t               *iff;
+       pcap_addr_t             *addr;
+       int                             longest_name_len = 0;
+       char                    *n, *d, *f;
+       int                             if_number = 0;
+
+       iff = acn_if_list;
+       while (iff) {
+               if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name);
+               iff = iff->next;
+       }
+       iff = acn_if_list;
+       printf("Interface List:\n");
+       while (iff) {
+               n = (iff->name)                                                 ? iff->name                     : "";
+               d = (iff->description)                                  ? iff->description      : "";
+               f = (iff->flags == PCAP_IF_LOOPBACK)    ? "L"                           : "";
+               printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d);
+               addr = iff->addresses;
+               while (addr) {
+                       printf("%*s ", (5 + longest_name_len), "");             /* add some indentation */
+                       printf("%15s  ", (addr->addr)           ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr)               : "");
+                       printf("%15s  ", (addr->netmask)        ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr)    : "");
+                       printf("%15s  ", (addr->broadaddr)      ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr)  : "");
+                       printf("%15s  ", (addr->dstaddr)        ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr)    : "");
+                       printf("\n");
+                       addr = addr->next;
+               }
+               iff = iff->next;
+       }
+}
+
+static void dump(unsigned char *ptr, int i, int indent) {
+       fprintf(stderr, "%*s", indent, " ");
+       for (; i > 0; i--) {
+               fprintf(stderr, "%2.2x ", *ptr++);
+       }
+       fprintf(stderr, "\n");
+}
+
+static void dump_interface_list_p(void) {
+       pcap_if_t               *iff;
+       pcap_addr_t             *addr;
+       int                             if_number = 0;
+
+       iff = acn_if_list;
+       printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff);
+       while (iff) {
+               printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next);
+               dump((unsigned char *)iff, sizeof(pcap_if_t), 5);
+               addr = iff->addresses;
+               while (addr) {
+                       printf("          %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next);
+                       dump((unsigned char *)addr, sizeof(pcap_addr_t), 10);
+                       addr = addr->next;
+               }
+               iff = iff->next;
+       }
+}
+
+static void dump_unit_table(void) {
+       int             chassis, geoslot;
+       iface_t *p;
+
+       printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address");
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+                       if (units[chassis][geoslot].ip != NULL)
+                               printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip);
+                       p = units[chassis][geoslot].iface;
+                       while (p) {
+                               char *n = (p->name)                     ? p->name                       : "";
+                               char *i = (p->IOPname)          ? p->IOPname            : "";
+                               p = p->next;
+                               printf("   %12s    -> %12s\n", i, n);
+                       }
+               }
+       }
+}
+
+static int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) {
+       int             c, s;
+
+       for (c = 0; c <= MAX_CHASSIS; c++) {
+               for (s = 0; s <= MAX_GEOSLOT; s++) {
+                       if (units[c][s].fd == fd || units[c][s].find_fd == fd) {
+                               if (chassis)    *chassis = c;
+                               if (geoslot)    *geoslot = s;
+                               if (unit_ptr)   *unit_ptr = &units[c][s];
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int read_client_nbytes(int fd, int count, unsigned char *buf) {
+       unit_t                  *u;
+       int                             chassis, geoslot;
+       int                             len;
+
+       find_unit_by_fd(fd, &chassis, &geoslot, &u);
+       while (count) {
+               if ((len = recv(fd, buf, count, 0)) <= 0)       return -1;      /* read in whatever data was sent to us */
+               count -= len;   
+               buf += len;
+       }                                                                                                                       /* till we have everything we are looking for */
+       return 0;
+}
+
+static void empty_unit_iface(unit_t *u) {
+       iface_t *p, *cur;
+
+       cur = u->iface;
+       while (cur) {                                                                                   /* loop over all the interface entries */
+               if (cur->name)                  free(cur->name);                        /* throwing away the contents if they exist */
+               if (cur->IOPname)               free(cur->IOPname);
+               p = cur->next;
+               free(cur);                                                                                      /* then throw away the structure itself */
+               cur = p;
+       }
+       u->iface = 0;                                                                                   /* and finally remember that there are no remaining structure */
+}
+
+static void empty_unit(int chassis, int geoslot) {
+       unit_t  *u = &units[chassis][geoslot];
+
+       empty_unit_iface(u);
+       if (u->imsg) {                                                                                  /* then if an inbound message buffer exists */
+               u->imsg = (char *)realloc(u->imsg, 1);                          /* and re-allocate the old large buffer into a new small one */
+       }
+}
+
+static void empty_unit_table(void) {
+       int             chassis, geoslot;
+
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+                       if (units[chassis][geoslot].ip != NULL) {
+                               free(units[chassis][geoslot].ip);                       /* get rid of the malloc'ed space that holds the IP address */
+                               units[chassis][geoslot].ip = 0;                         /* then set the pointer to NULL */
+                       }
+                       empty_unit(chassis, geoslot);
+               }
+       }
+}
+
+static char *find_nth_interface_name(int n) {
+       int             chassis, geoslot;
+       iface_t *p;
+       char    *last_name = 0;
+
+       if (n < 0) n = 0;                                                                                               /* ensure we are working with a valid number */
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {                  /* scan the table... */
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+                       if (units[chassis][geoslot].ip != NULL) {
+                               p = units[chassis][geoslot].iface;
+                               while (p) {                                                                                     /* and all interfaces... */
+                                       if (p->IOPname) last_name = p->name;                    /* remembering the last name found */
+                                       if (n-- == 0) return last_name;                                 /* and if we hit the instance requested */
+                                       p = p->next;
+                               }
+                       }
+               }
+       }
+                                                                                       /* if we couldn't fine the selected entry */
+       if (last_name)  return last_name;               /* ... but we did have at least one entry... return the last entry found */
+       return "";                                                              /* ... but if there wasn't any entry... return an empty string instead */
+}
+
+int acn_parse_hosts_file(char *errbuf) {                               /* returns: -1 = error, 0 = OK */
+       FILE    *fp;
+       char    buf[MAX_LINE_SIZE];
+       char    *ptr, *ptr2;
+       int             pos;
+       int             chassis, geoslot;
+       unit_t  *u;
+
+       empty_unit_table();
+       if ((fp = fopen("/etc/hosts", "r")) == NULL) {                                                                          /* try to open the hosts file and if it fails */
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading.");    /* return the nohostsfile error response */
+               return -1;
+       }
+       while (fgets(buf, MAX_LINE_SIZE-1, fp)) {                       /* while looping over the file */
+
+               pos = strcspn(buf, "#\n\r");                                    /* find the first comment character or EOL */
+               *(buf + pos) = '\0';                                                    /* and clobber it and anything that follows it */
+
+               pos = strspn(buf, " \t");                                               /* then find the first non-white space */
+               if (pos == strlen(buf))                                                 /* if there is nothing but white space on the line */
+                       continue;                                                                       /* ignore that empty line */
+               ptr = buf + pos;                                                                /* and skip over any of that leading whitespace */
+
+               if ((ptr2 = strstr(ptr, "_I_")) == NULL)                /* skip any lines that don't have names that look like they belong to IOPs */
+                       continue;
+               if (*(ptr2 + 4) != '_')                                                 /* and skip other lines that have names that don't look like ACN components */
+                       continue;
+               *(ptr + strcspn(ptr, " \t")) = '\0';                    /* null terminate the IP address so its a standalone string */
+
+               chassis = *(ptr2 + 3) - '0';                                    /* extract the chassis number */
+               geoslot = *(ptr2 + 5) - '0';                                    /* and geo-slot number */
+               if (chassis < 1 || chassis > MAX_CHASSIS ||
+                       geoslot < 1 || geoslot > MAX_GEOSLOT) {         /* if the chassis and/or slot numbers appear to be bad... */
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'.");        /* warn the user */
+                       continue;                                                                                                                                       /* and ignore the entry */
+               }
+               if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                       continue;
+               }
+               strcpy(ptr2, ptr);                                                              /* copy the IP address into our malloc'ed memory */
+               u = &units[chassis][geoslot];
+               u->ip = ptr2;                                                                   /* and remember the whole shebang */
+               u->chassis = chassis;
+               u->geoslot = geoslot;
+       }
+       fclose(fp);
+       if (*errbuf)    return -1;
+       else                    return 0;
+}
+
+static int open_with_IOP(unit_t  *u, int flag) {
+       int                                     sockfd;
+       char                            *ip;
+
+       if (u->serv_addr == NULL) {
+               u->serv_addr = malloc(sizeof(struct sockaddr_in));
+       }
+       ip = u->ip;
+       bzero((char *)u->serv_addr, sizeof(struct sockaddr_in));
+       u->serv_addr->sin_family                = AF_INET;
+       u->serv_addr->sin_addr.s_addr   = inet_addr(ip);
+       u->serv_addr->sin_port                  = htons(IOP_SNIFFER_PORT);
+
+       if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip);
+               return 0;
+       }
+       if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) {
+               fprintf(stderr, "pcap can't connect to IOP at %s\n", ip);
+               return 0;
+       }
+       if (flag == LIVE)       u->fd = sockfd;
+       else                            u->find_fd = sockfd;
+       u->first_time = 0;
+       return sockfd;                  /* return the non-zero file descriptor as a 'success' indicator */
+}
+
+static void close_with_IOP(int chassis, int geoslot, int flag) {
+       int             *id;
+
+       if (flag == LIVE)       id = &units[chassis][geoslot].fd;
+       else                            id = &units[chassis][geoslot].find_fd;
+
+       if (*id) {                                                                              /* this was the last time, so... if we are connected... */
+               close(*id);                                                                     /* disconnect us */
+               *id = 0;                                                                        /* and forget that the descriptor exists because we are not open */
+       }
+}
+
+static void pcap_cleanup_acn(pcap_t *handle) {
+       int             chassis, geoslot;
+       unit_t  *u;
+
+       if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0)
+               return;
+       close_with_IOP(chassis, geoslot, LIVE);
+       if (u)
+               u->first_time = 0;
+       pcap_cleanup_live_common(handle);
+}
+
+static void send_to_fd(int fd, int len, unsigned char *str) {
+       int             nwritten;
+       int             chassis, geoslot;
+
+       while (len > 0) {
+               if ((nwritten = write(fd, str, len)) <= 0) {
+                       find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+                       if (units[chassis][geoslot].fd == fd)                   close_with_IOP(chassis, geoslot, LIVE);
+                       else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND);
+                       empty_unit(chassis, geoslot);
+                       return;
+               }
+               len -= nwritten;
+               str += nwritten;
+       }
+}
+
+static void acn_freealldevs(void) {
+
+       pcap_if_t       *iff, *next_iff;
+       pcap_addr_t     *addr, *next_addr;
+
+       for (iff = acn_if_list; iff != NULL; iff = next_iff) {
+               next_iff = iff->next;
+               for (addr = iff->addresses; addr != NULL; addr = next_addr) {
+                       next_addr = addr->next;
+                       if (addr->addr)                 free(addr->addr);
+                       if (addr->netmask)              free(addr->netmask);
+                       if (addr->broadaddr)    free(addr->broadaddr);
+                       if (addr->dstaddr)              free(addr->dstaddr);
+                       free(addr);
+               }
+               if (iff->name)                  free(iff->name);
+               if (iff->description)   free(iff->description);
+               free(iff);
+       }
+}
+
+static char *nonUnified_port_num(unit_t *u, int IOPportnum) {
+
+       sprintf(static_buf, "%d_%d", u->chassis, u->geoslot);
+       return static_buf;
+}
+
+static char *unified_port_num(unit_t *u, int IOPportnum) {
+       int                     portnum;
+
+       portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
+       sprintf(static_buf, "%d", portnum);
+       return static_buf;
+}
+
+static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
+       iface_t         *iface_ptr, *iface;
+       char            *name;
+       char            buf[32];
+       char            *proto;
+       char            *port;
+       int                     IOPportnum = 0;
+
+       iface = malloc(sizeof(iface_t));                /* get memory for a structure */
+       bzero((char *)iface, sizeof(iface_t));
+
+       iface->iftype = iftype;                                 /* remember the interface type of this interface */
+
+       name = malloc(strlen(IOPname) + 1);             /* get memory for the IOP's name */
+       strcpy(name, IOPname);                                  /* and copy it in */
+       iface->IOPname = name;                                  /* and stick it into the structure */
+
+       if (strncmp(IOPname, "lo", 2) == 0) {
+               IOPportnum = atoi(&IOPname[2]);
+               switch (iftype) {
+                       case DLT_EN10MB:        proto = "lo";           port = nonUnified_port_num(u, IOPportnum);      break;
+                       default:                        proto = "???";          port = unified_port_num(u, IOPportnum);         break;
+               }
+       } else if (strncmp(IOPname, "eth", 3) == 0) {
+               IOPportnum = atoi(&IOPname[3]);
+               switch (iftype) {
+                       case DLT_EN10MB:        proto = "eth";          port = nonUnified_port_num(u, IOPportnum);      break;
+                       default:                        proto = "???";          port = unified_port_num(u, IOPportnum);         break;
+               }
+       } else if (strncmp(IOPname, "wan", 3) == 0) {
+               IOPportnum = atoi(&IOPname[3]);
+               switch (iftype) {
+                       case DLT_SITA:          proto = "wan";          port = unified_port_num(u, IOPportnum);         break;
+                       default:                        proto = "???";          port = unified_port_num(u, IOPportnum);         break;
+               }
+       }
+
+       sprintf(buf, "%s_%s", proto, port);             /* compose the user's name for that IOP port name */
+       name = malloc(strlen(buf) + 1);                 /* get memory for that name */
+       strcpy(name, buf);                                              /* and copy it in */
+       iface->name = name;                                             /* and stick it into the structure */
+
+       if (u->iface == 0) {                                    /* if this is the first name */
+               u->iface = iface;                                       /* stick this entry at the head of the list */
+       } else {
+               iface_ptr = u->iface;
+               while (iface_ptr->next) {                       /* othewise scan the list */
+                       iface_ptr = iface_ptr->next;    /* till we're at the last entry */
+               }
+               iface_ptr->next = iface;                        /* then tack this entry on the end of the list */
+       }
+       return iface->name;
+}
+
+static int if_sort(char *s1, char *s2) {
+       char    *s1_p2, *s2_p2;
+       char    str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE];
+       int             s1_p1_len, s2_p1_len;
+       int             retval;
+
+       if ((s1_p2 = strchr(s1, '_'))) {        /* if an underscore is found... */
+               s1_p1_len = s1_p2 - s1;                 /* the prefix length is the difference in pointers */
+               s1_p2++;                                                /* the suffix actually starts _after_ the underscore */
+       } else {                                                        /* otherwise... */
+               s1_p1_len = strlen(s1);                 /* the prefix length is the length of the string itself */
+               s1_p2 = 0;                                              /* and there is no suffix */
+       }
+       if ((s2_p2 = strchr(s2, '_'))) {        /* now do the same for the second string */
+               s2_p1_len = s2_p2 - s2;
+               s2_p2++;
+       } else {
+               s2_p1_len = strlen(s2);
+               s2_p2 = 0;
+       }
+       strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1));   *(str1 + s1_p1_len) = 0;
+       strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2));   *(str2 + s2_p1_len) = 0;
+       retval = strcmp(str1, str2);
+       if (retval != 0) return retval;         /* if they are not identical, then we can quit now and return the indication */
+       return strcmp(s1_p2, s2_p2);            /* otherwise we return the result of comparing the 2nd half of the string */
+}
+
+static void sort_if_table(void) {
+       pcap_if_t       *p1, *p2, *prev, *temp;
+       int                     has_swapped;
+
+       if (!acn_if_list) return;                               /* nothing to do if the list is empty */
+
+       while (1) {
+               p1 = acn_if_list;                                       /* start at the head of the list */
+               prev = 0;
+               has_swapped = 0;
+               while ((p2 = p1->next)) {
+                       if (if_sort(p1->name, p2->name) > 0) {
+                               if (prev) {                                     /* we are swapping things that are _not_ at the head of the list */
+                                       temp = p2->next;
+                                       prev->next = p2;
+                                       p2->next = p1;
+                                       p1->next = temp;
+                               } else {                                        /* special treatment if we are swapping with the head of the list */
+                                       temp = p2->next;
+                                       acn_if_list= p2;
+                                       p2->next = p1;
+                                       p1->next = temp;
+                               }
+                               p1 = p2;
+                               prev = p1;
+                               has_swapped = 1;
+                       }
+                       prev = p1;
+                       p1 = p1->next;
+               }
+               if (has_swapped == 0)
+                       return;
+       }       
+       return;
+}
+       
+static int process_client_data (char *errbuf) {                                                                /* returns: -1 = error, 0 = OK */
+       int                                     chassis, geoslot;
+       unit_t                          *u;
+       pcap_if_t                       *iff, *prev_iff;
+       pcap_addr_t                     *addr, *prev_addr;
+       char                            *ptr;
+       int                                     address_count;
+       struct sockaddr_in      *s;
+       char                            *newname;
+       bpf_u_int32                             interfaceType;
+       unsigned char           flags;
+
+       prev_iff = 0;
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {                          /* now loop over all the devices */
+                       u = &units[chassis][geoslot];
+                       empty_unit_iface(u);
+                       ptr = u->imsg;                                                                                                  /* point to the start of the msg for this IOP */
+                       while (ptr < (u->imsg + u->len)) {
+                               if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
+                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                       return -1;
+                               }
+                               bzero((char *)iff, sizeof(pcap_if_t));
+                               if (acn_if_list == 0)   acn_if_list = iff;                                      /* remember the head of the list */
+                               if (prev_iff)                   prev_iff->next = iff;                           /* insert a forward link */
+
+                               if (*ptr) {                                                                                                     /* if there is a count for the name */
+                                       if ((iff->name = malloc(*ptr + 1)) == NULL) {                   /* get that amount of space */
+                                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                               return -1;
+                                       }
+                                       memcpy(iff->name, (ptr + 1), *ptr);                                             /* copy the name into the malloc'ed space */
+                                       *(iff->name + *ptr) = 0;                                                                /* and null terminate the string */
+                                       ptr += *ptr;                                                                                    /* now move the pointer forwards by the length of the count plus the length of the string */
+                               }
+                               ptr++;
+
+                               if (*ptr) {                                                                                                     /* if there is a count for the description */
+                                       if ((iff->description = malloc(*ptr + 1)) == NULL) {    /* get that amount of space */
+                                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                               return -1;
+                                       }
+                                       memcpy(iff->description, (ptr + 1), *ptr);                              /* copy the name into the malloc'ed space */
+                                       *(iff->description + *ptr) = 0;                                                 /* and null terminate the string */
+                                       ptr += *ptr;                                                                                    /* now move the pointer forwards by the length of the count plus the length of the string */
+                               }
+                               ptr++;
+
+                               interfaceType = ntohl(*(bpf_u_int32 *)ptr);
+                               ptr += 4;                                                                                                       /* skip over the interface type */
+
+                               flags = *ptr++;
+                               if (flags) iff->flags = PCAP_IF_LOOPBACK;                                       /* if this is a loopback style interface, lets mark it as such */
+
+                               address_count = *ptr++;
+
+                               prev_addr = 0;
+                               while (address_count--) {
+                                       if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
+                                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                               return -1;
+                                       }
+                                       bzero((char *)addr, sizeof(pcap_addr_t));
+                                       if (iff->addresses == 0) iff->addresses = addr;
+                                       if (prev_addr) prev_addr->next = addr;                                                  /* insert a forward link */
+                                       if (*ptr) {                                                                                                             /* if there is a count for the address */
+                                               if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {         /* get that amount of space */
+                                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                                       return -1;
+                                               }
+                                               bzero((char *)s, sizeof(struct sockaddr_in));
+                                               addr->addr = (struct sockaddr *)s;
+                                               s->sin_family           = AF_INET;
+                                               s->sin_addr.s_addr      = *(bpf_u_int32 *)(ptr + 1);                    /* copy the address in */
+                                               ptr += *ptr;                                                                            /* now move the pointer forwards according to the specified length of the address */
+                                       }
+                                       ptr++;                                                                                                  /* then forwards one more for the 'length of the address' field */
+                                       if (*ptr) {                                                                                             /* process any netmask */
+                                               if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+                                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                                       return -1;
+                                               }
+                                               bzero((char *)s, sizeof(struct sockaddr_in));
+                                               addr->netmask = (struct sockaddr *)s;
+                                               s->sin_family           = AF_INET;
+                                               s->sin_addr.s_addr      = *(bpf_u_int32*)(ptr + 1);
+                                               ptr += *ptr;
+                                       }
+                                       ptr++;
+                                       if (*ptr) {                                                                                             /* process any broadcast address */
+                                               if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+                                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                                       return -1;
+                                               }
+                                               bzero((char *)s, sizeof(struct sockaddr_in));
+                                               addr->broadaddr = (struct sockaddr *)s;
+                                               s->sin_family           = AF_INET;
+                                               s->sin_addr.s_addr      = *(bpf_u_int32*)(ptr + 1);
+                                               ptr += *ptr;
+                                       }
+                                       ptr++;
+                                       if (*ptr) {                                                                                             /* process any destination address */
+                                               if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+                                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                                                       return -1;
+                                               }
+                                               bzero((char *)s, sizeof(struct sockaddr_in));
+                                               addr->dstaddr = (struct sockaddr *)s;
+                                               s->sin_family           = AF_INET;
+                                               s->sin_addr.s_addr      = *(bpf_u_int32*)(ptr + 1);
+                                               ptr += *ptr;
+                                       }
+                                       ptr++;
+                                       prev_addr = addr;
+                               }
+                               prev_iff = iff;
+
+                               newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType);              /* add a translation entry and get a point to the mangled name */
+                               if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) {    /* we now re-write the name stored in the interface list */
+                                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+                                       return -1;
+                               }
+                               strcpy(iff->name, newname);                                                                                             /* to this new name */
+                       }
+               }
+       }
+       return 0;
+}
+
+static int read_client_data (int fd) {
+       unsigned char   buf[256];
+       int                             chassis, geoslot;
+       unit_t                  *u;
+       int                             len;
+
+       find_unit_by_fd(fd, &chassis, &geoslot, &u);
+
+       if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0;       /* read in whatever data was sent to us */
+
+       if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL)       /* extend the buffer for the new data */
+               return 0;
+       memcpy((u->imsg + u->len), buf, len);                                           /* append the new data */
+       u->len += len;
+       return 1;
+}
+
+static void wait_for_all_answers(void) {
+       int             retval;
+       struct  timeval tv;
+       int             fd;
+       int             chassis, geoslot;
+
+       tv.tv_sec = 2;
+       tv.tv_usec = 0;
+
+       while (1) {
+               int flag = 0;
+               for (fd = 0; fd <= max_fs; fd++) {                                                              /* scan the list of descriptors we may be listening to */
+                       if (FD_ISSET(fd, &readfds)) flag = 1;                                           /* and see if there are any still set */
+               }
+               if (flag == 0) return;                                                                                  /* we are done, when they are all gone */
+
+               memcpy(&working_set, &readfds, sizeof(readfds));                                /* otherwise, we still have to listen for more stuff, till we timeout */
+               retval = select(max_fs + 1, &working_set, NULL, NULL, &tv);
+               if (retval == -1) {                                                                                             /* an error occured !!!!! */
+                       return;
+               } else if (retval == 0) {                                                                               /* timeout occured, so process what we've got sofar and return */
+                       printf("timeout\n");
+                       return;
+               } else {
+                       for (fd = 0; fd <= max_fs; fd++) {                                                      /* scan the list of things to do, and do them */
+                               if (FD_ISSET(fd, &working_set)) {
+                                       if (read_client_data(fd) == 0) {                                        /* if the socket has closed */
+                                               FD_CLR(fd, &readfds);                                                   /* and descriptors we listen to for errors */
+                                               find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+                                               close_with_IOP(chassis, geoslot, FIND);                 /* and close out connection to him */
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+static char *get_error_response(int fd, char *errbuf) {                /* return a pointer on error, NULL on no error */
+       char    byte;
+       int             len = 0;
+
+       while (1) {
+               recv(fd, &byte, 1, 0);                                                  /* read another byte in */
+               if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) {             /* and if there is still room in the buffer */
+                       *errbuf++ = byte;                                                       /* stick it in */
+                       *errbuf = '\0';                                                         /* ensure the string is null terminated just in case we might exceed the buffer's size */
+               }
+               if (byte == '\0') {
+                       if (len > 1)    { return errbuf;        }
+                       else                    { return NULL;          }
+               }
+       }
+}
+
+int acn_findalldevs(char *errbuf) {                                                            /* returns: -1 = error, 0 = OK */
+       int             chassis, geoslot;
+       unit_t  *u;
+
+       FD_ZERO(&readfds);
+       max_fs = 0;
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+                       u = &units[chassis][geoslot];
+                       if (u->ip && (open_with_IOP(u, FIND))) {                        /* connect to the remote IOP */
+                               send_to_fd(u->find_fd, 1, (unsigned char *)"\0");
+                               if (get_error_response(u->find_fd, errbuf))
+                                       close_with_IOP(chassis, geoslot, FIND);
+                               else {
+                                       if (u->find_fd > max_fs)
+                                               max_fs = u->find_fd;                                                            /* remember the highest number currently in use */
+                                       FD_SET(u->find_fd, &readfds);                                           /* we are going to want to read this guy's response to */
+                                       u->len = 0;
+                                       send_to_fd(u->find_fd, 1, (unsigned char *)"Q");                /* this interface query request */
+                               }
+                       }
+               }
+       }
+       wait_for_all_answers();
+       if (process_client_data(errbuf))
+               return -1;
+       sort_if_table();
+       return 0;
+}
+
+static int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) {
+       unsigned char   buf[12];
+
+       send_to_fd(handle->fd, 1, (unsigned char *)"S");                                                /* send the get_stats command to the IOP */
+
+       if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1;  /* try reading the required bytes */
+
+       ps->ps_recv             = ntohl(*(uint32_t *)&buf[0]);                                                  /* break the buffer into its three 32 bit components */
+       ps->ps_drop             = ntohl(*(uint32_t *)&buf[4]);
+       ps->ps_ifdrop   = ntohl(*(uint32_t *)&buf[8]);
+
+       return 0;
+}
+
+static int acn_open_live(const char *name, char *errbuf, int *linktype) {              /* returns 0 on error, else returns the file descriptor */
+       int                     chassis, geoslot;
+       unit_t          *u;
+       iface_t         *p;
+       pcap_if_t       *alldevsp;
+
+       pcap_findalldevs(&alldevsp, errbuf);
+       for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {                                                                          /* scan the table... */
+               for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+                       u = &units[chassis][geoslot];
+                       if (u->ip != NULL) {
+                               p = u->iface;
+                               while (p) {                                                                                                                                             /* and all interfaces... */
+                                       if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) {                            /* and if we found the interface we want... */
+                                               *linktype = p->iftype;
+                                               open_with_IOP(u, LIVE);                                                                                                 /* start a connection with that IOP */
+                                               send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname);   /* send the IOP's interface name, and a terminating null */
+                                               if (get_error_response(u->fd, errbuf)) {
+                                                       return -1;
+                                               }
+                                               return u->fd;                                                                                                                   /* and return that open descriptor */
+                                       }
+                                       p = p->next;
+                               }
+                       }
+               }
+       }
+       return -1;                                                                                                                                                              /* if the interface wasn't found, return an error */
+}
+
+static void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) {
+       unsigned char   buf[8];
+       unit_t                  *u;
+
+       //printf("acn_start_monitor()\n");                              // fulko
+       find_unit_by_fd(fd, NULL, NULL, &u);
+       if (u->first_time == 0) {
+               buf[0]                                  = 'M';
+               *(uint32_t *)&buf[1]    = htonl(snaplen);
+               buf[5]                                  = timeout;
+               buf[6]                                  = promiscuous;
+               buf[7]                                  = direction;
+       //printf("acn_start_monitor() first time\n");                           // fulko
+               send_to_fd(fd, 8, buf);                                                         /* send the start monitor command with its parameters to the IOP */
+               u->first_time = 1;
+       }
+       //printf("acn_start_monitor() complete\n");                             // fulko
+}
+
+static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) {
+       strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
+           PCAP_ERRBUF_SIZE);
+       return (-1);
+}
+
+static int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) {
+       int                             fd = handle->fd;
+       int                             count;
+       struct bpf_insn *p;
+       uint16_t                shortInt;
+       uint32_t                longInt;
+
+       send_to_fd(fd, 1, (unsigned char *)"F");                        /* BPF filter follows command */
+       count = bpf->bf_len;
+       longInt = htonl(count);
+       send_to_fd(fd, 4, (unsigned char *)&longInt);           /* send the instruction sequence count */
+       p = bpf->bf_insns;
+       while (count--) {                                                                       /* followed by the list of instructions */
+               shortInt = htons(p->code);
+               longInt = htonl(p->k);
+               send_to_fd(fd, 2, (unsigned char *)&shortInt);
+               send_to_fd(fd, 1, (unsigned char *)&p->jt);
+               send_to_fd(fd, 1, (unsigned char *)&p->jf);
+               send_to_fd(fd, 4, (unsigned char *)&longInt);
+               p++;
+       }
+       if (get_error_response(fd, NULL))
+               return -1;
+       return 0;
+}
+
+static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
+       snprintf(handle->errbuf, sizeof(handle->errbuf),
+           "Setting direction is not supported on ACN adapters");
+       return -1;
+}
+
+static int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) {
+       struct          timeval tv;
+       int                     retval, fd;
+       fd_set          r_fds;
+       fd_set          w_fds;
+       u_char          *bp;
+       int                     len = 0;
+       int                     offset = 0;
+
+       tv.tv_sec = 5;
+       tv.tv_usec = 0;
+
+       fd = handle->fd;
+       FD_ZERO(&r_fds);
+       FD_SET(fd, &r_fds);
+       memcpy(&w_fds, &r_fds, sizeof(r_fds));
+       bp = handle->bp;
+       while (count) {
+               retval = select(fd + 1, &w_fds, NULL, NULL, &tv);
+               if (retval == -1) {                                                                                     /* an error occured !!!!! */
+//                     fprintf(stderr, "error during packet data read\n");
+                       return -1;                                                                                              /* but we need to return a good indication to prevent unneccessary popups */
+               } else if (retval == 0) {                                                                       /* timeout occured, so process what we've got sofar and return */
+//                     fprintf(stderr, "timeout during packet data read\n");
+                       return -1;
+               } else {
+                       if ((len = recv(fd, (bp + offset), count, 0)) <= 0) {
+//                             fprintf(stderr, "premature exit during packet data rx\n");
+                               return -1;
+                       }
+                       count -= len;
+                       offset += len;
+               }
+       }
+       return 0;
+}
+
+static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) {
+       #define HEADER_SIZE (4 * 4)
+       unsigned char           packet_header[HEADER_SIZE];
+       struct pcap_pkthdr      pcap_header;
+
+       //printf("pcap_read_acn()\n");                  // fulko
+       acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction);       /* maybe tell him to start monitoring */
+       //printf("pcap_read_acn() after start monitor\n");                      // fulko
+
+       handle->bp = packet_header;
+       if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0;                 /* try to read a packet header in so we can get the sizeof the packet data */
+
+       pcap_header.ts.tv_sec   = ntohl(*(uint32_t *)&packet_header[0]);                                /* tv_sec */
+       pcap_header.ts.tv_usec  = ntohl(*(uint32_t *)&packet_header[4]);                                /* tv_usec */
+       pcap_header.caplen              = ntohl(*(uint32_t *)&packet_header[8]);                                /* caplen */
+       pcap_header.len                 = ntohl(*(uint32_t *)&packet_header[12]);                               /* len */
+
+       handle->bp = handle->buffer + handle->offset;                                                                   /* start off the receive pointer at the right spot */
+       if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0;  /* then try to read in the rest of the data */
+
+       callback(user, &pcap_header, handle->bp);                                                                               /* call the user supplied callback function */
+       return 1;
+}
+
+static int pcap_activate_sita(pcap_t *handle) {
+       int             fd;
+
+       if (handle->opt.rfmon) {
+               /*
+                * No monitor mode on SITA devices (they're not Wi-Fi
+                * devices).
+                */
+               return PCAP_ERROR_RFMON_NOTSUP;
+       }
+
+       /* Initialize some components of the pcap structure. */
+
+       handle->inject_op = pcap_inject_acn;
+       handle->setfilter_op = pcap_setfilter_acn;
+       handle->setdirection_op = pcap_setdirection_acn;
+       handle->set_datalink_op = NULL; /* can't change data link type */
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->cleanup_op = pcap_cleanup_acn;
+       handle->read_op = pcap_read_acn;
+       handle->stats_op = pcap_stats_acn;
+
+       fd = acn_open_live(handle->opt.source, handle->errbuf,
+           &handle->linktype);
+       if (fd == -1)
+               return PCAP_ERROR;
+       handle->md.clear_promisc = handle->md.promisc;
+       handle->fd = fd;
+       handle->bufsize = handle->snapshot;
+
+       /* Allocate the buffer */
+
+       handle->buffer   = malloc(handle->bufsize + handle->offset);
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "malloc: %s", pcap_strerror(errno));
+               pcap_cleanup_acn(handle);
+               return PCAP_ERROR;
+       }
+
+       /*
+        * "handle->fd" is a socket, so "select()" and "poll()"
+        * should work on it.
+        */
+       handle->selectable_fd = handle->fd;
+
+       return 0;
+}
+
+pcap_t *pcap_create(const char *device, char *ebuf) {
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_sita;
+       return (p);
+}
diff --git a/pcap-sita.h b/pcap-sita.h
new file mode 100644 (file)
index 0000000..b232ee2
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * pcap-sita.h: Packet capture interface for SITA WAN devices
+ *
+ * Authors: Fulko Hew (fulko.hew@sita.aero) (+1 905 6815570);
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-sita.h
+ */
+
+extern int acn_parse_hosts_file(char *errbuf);
+extern int acn_findalldevs(char *errbuf);
diff --git a/pcap-sita.html b/pcap-sita.html
new file mode 100644 (file)
index 0000000..97408d8
--- /dev/null
@@ -0,0 +1,943 @@
+<HTML><HEAD>
+<STYLE type="text/css">
+<!--
+A { text-decoration:none }
+-->
+</STYLE>
+</HEAD>
+<BODY>
+
+<TABLE WIDTH=100%><TR>
+       <TD ALIGN=LEFT VALIGN=TOP>
+               <FONT SIZE=+0 FACE="COURIER"><B>A "Distributed Pcap" for<BR>Remote Monitoring LANs & WANs</B><BR>
+                                                                               (Design Notes for the SITA ACN device)</FONT>
+       </TD>
+       <TD ALIGN=RIGHT VALIGN=TOP>
+               Fulko Hew<BR>SITA INC Canada, Inc.<BR>Revised: October 2, 2007
+       </TD>
+</TR></TABLE>
+
+
+<H3>SUMMARY</H3>
+<UL>
+       <STRONG>Note:</STRONG> This document is part of the libpcap Git and was derived from 'pcap.3' (circa Aug/07).
+       <P>
+       The ACN provides a customized/distributed version of this library that alows SMPs to
+       interact with the various IOPs within the site providing a standard mechanism
+       to capture LAN and WAN message traffic.
+       <P>
+       <CENTER>
+               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3 WIDTH=75%>
+                       <TR>
+                               <TH VALIGN=TOP>SMP</TH>
+                               <TD VALIGN=TOP>The Supervisory Management Processor where Wireshark (or equivalent)
+                                                               runs in conjuction with a libpcap front-end.</TD>
+                       </TR>
+                       <TR>
+                               <TH VALIGN=TOP>IOP</TH>
+                               <TD VALIGN=TOP>I/O Processors where the monitored ports exist in conjunction
+                                                               with a custom device driver/libpcap back-end.</TD>
+                       </TR>
+               </TABLE>
+       </CENTER>
+       <P>
+       Each IOP will be capable of supporting multiple connections from an SMP
+       enabling monitoring of more than one interface at a time, each through
+       its own seperate connection.  The IOP is responsible to ensure and report
+       an error if any attempt is made to monitor the same interface more than once.
+       <P>
+       There are three applications that will be supported by the ACN version of libpcap.
+       They each use a slightly different mode for looping/capturing and termination
+       as summarized in the following table:
+       <P>
+       <CENTER>
+       <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+       <TR><TH>Application</TH>        <TH>Capture</TH>        <TH>Termination</TH></TR>
+       <TR><TH VALIGN=TOP NOWRAP>wireshark</TH>
+                       <TD VALIGN=TOP>pcap_dispatch(all packets in one buffer of capture only)</TD>
+                       <TD VALIGN=TOP>pcap_breakloop()</TD>
+               </TR>
+       <TR><TH VALIGN=TOP NOWRAP>tshark</TH>
+                       <TD VALIGN=TOP>pcap_dispatch(one buffer of capture only)</TD>
+                       <TD VALIGN=TOP>Since a CTRL-C was used to terminate the application, pcap_breakloop() is never called.</TD>
+               </TR>
+       <TR><TH VALIGN=TOP NOWRAP>tcpdump</TH>
+                       <TD VALIGN=TOP>pcap_loop(all packets in the next buffer, and loop forever)</TD>
+                       <TD VALIGN=TOP>pcap_breakloop()</TD>
+               </TR>
+       </TABLE>
+       </CENTER>
+       <P>
+       <B>Note: </B>In all cases, the termination of capturing is always (apparently) followed by
+       pcap_close().  Pcap_breakloop() is only used to stop/suspend looping/processing,
+       and upon close interpretation of the function definitions, it is possible to resume
+       capturing following a pcap_breakloop() without any re-initialization.
+       <P>
+       <H4>ACN Limitations</H4>
+       <OL>
+               <LI>Monitoring of backup IOPs is not currently supported.
+               <LI>Ethernet interfaces cannot be monitored in promiscuous mode.
+       </OL>
+
+</UL>
+
+<H3>ROUTINES</H3>
+<UL>
+               The following list of functions is the sub-set of Pcap functions that have been
+               altered/enhanced to support the ACN remote monitoring facility.  The remainder of the Pcap
+               functions continue to perform their duties un-altered.  Libpcap only supports this
+               mode of operation if it has been configured/compiled for SITA/ACN support.
+               <P>
+               <UL><FONT FACE=COURIER>
+                       pcap_findalldevs<BR>
+                       pcap_freealldevs<BR>
+                       pcap_open_live<BR>
+                       pcap_close<BR>
+                       pcap_setfilter<BR>
+                       pcap_dispatch<BR>
+                       pcap_loop<BR>
+                       pcap_next<BR>
+                       pcap_next_ex<BR>
+                       pcap_stats<BR>
+               </FONT></UL>
+
+       These subroutines have been modified for the ACN specific distributed and remote monitoring
+       ability perform the following basic functions.  More detail is provided in the
+       "SMP/IOP Inter-Process Communication Protocol" section.
+       <P>
+<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_open_live()</B></TD>
+               <TD VALIGN=TOP>Used to obtain a packet capture descriptor to look at packets on the network.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP will open a connection to the selected IOP on its 'sniffer' port
+                       to ensure it is available.  It sends a null terminated string identifying
+                       the interface to be monitored.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       After any required processing is complete, the IOP will return a
+                       null terminated string containing an error message if one occured.
+                       If no error occured, a empty string is still returned.
+                       Errors are:
+                       <UL>
+                       <LI>"Interface (xxx) does not exist."
+                       <LI>"Interface (xxx) not configured."
+                       <LI>"Interface (xxx) already being monitored."
+                       </UL>
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_findalldevs()</B></TD>
+               <TD VALIGN=TOP>It constructs a list of network devices that can be opened with pcap_open_live().</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       It obtains a list of IOPs currently available (via /etc/hosts).
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure
+                       the IOP is available.
+                       It sends a null terminated empty interface ID followed by the query request command.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>The IOP returns an error response and its list of devices.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP closes the TCP connection with each IOP.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP adds the received information to its internal structure.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_freealldevs()</B></TD>
+               <TD VALIGN=TOP>Used to free a list allocated by pcap_findalldevs().</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP frees the structure it built as a result of the previous
+                       invocation of pcap_findalldevs().
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_dispatch()</B></TD>
+               <TD VALIGN=TOP>Used to collect and process packets.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+                       the SMP will pass down the monitor start command and various parameters the IOP should use.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP now sends a stream of captured data.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP will read the reverse channel of the connection between the SMP and the
+                       IOP that provides the captured data (via 'p->read_op' which is 'pcap_read_linux()'
+                       until the select() call returns a 'no more data' indication.
+                       It will the process (at most) the next 'cnt' packets and invoke the specified
+                       callback function for each packet processed.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+                       <TD>
+                       The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_loop()</B></TD>
+               <TD VALIGN=TOP>
+                               Is similar to pcap_dispatch() except it keeps reading packets until
+                               the requested number of packets are processed or an error occurs.
+               </TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+                       the SMP will pass down the monitor start command and various parameters the IOP should use.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP now sends a stream of captured data.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP continuously reads the next packet from the reverse channel of the connection
+                       between the SMP and the IOP that provides the captured data (via 'p->read_op'
+                       which is 'pcap_read_linux()' until 'cnt' packets have been received.
+                       The specified callback function will be invoked for each packet received.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+                       <TD>
+                       The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_next()</B></TD>
+               <TD VALIGN=TOP>
+                       It reads the next packet (by calling pcap_dispatch() with a count of 1)
+                       and returns a pointer to the data in that packet.
+               </TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+                       the SMP will pass down the monitor start command and various parameters the IOP should use.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP now sends a stream of captured data.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP reads only the next packet from the reverse channel of the connection
+                       between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+                       with a count of 1) and returns a pointer to that data by invoking an internal callback.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+                       <TD>
+                       The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_next_ex()</B></TD>
+               <TD VALIGN=TOP>Reads the next packet and returns a success/failure indication.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+                       the SMP will pass down the monitor start command and various parameters the IOP should use.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP now sends a stream of captured data.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP reads only the next packet from the reverse channel of the connection
+                       between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+                       with a count of 1) and returns seperate pointers to both the
+                       packet header and packet data by invoking an internal callback.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+                       <TD>
+                       The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_setfilter()</B></TD>
+        <TD VALIGN=TOP>Used to specify a filter program.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP sends a 'set filter' command followed by the BPF commands.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP returns a null terminated error string if it failed to accept the filter.
+                       If no error occured, then a NULL terminated empty string is returned instead.
+                       Errors are:
+                       <UL>
+                       <LI>"Invalid BPF."
+                       <LI>"Insufficient resources for BPF."
+                       </UL>
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_stats()</B></TD>
+        <TD VALIGN=TOP>Fills in a pcap_stat struct with packet statistics.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP sends a message to the IOP requesting its statistics.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+                       <TD>
+                       The IOP returns the statistics.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+                       <TD>
+                       The SMP fills in the structure provided with the information retrieved from the IOP.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+
+       <TR>
+               <TD VALIGN=TOP ROWSPAN=2><B>pcap_close()</B></TD>
+        <TD VALIGN=TOP>Closes the file and deallocates resources.</TD>
+       </TR>
+       <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+               <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+                       <TD>
+                       The SMP closes the file descriptor, and if the descriptor is that of
+                       the comminucation session with an IOP, it too is terminated.
+                       </TD>
+               </TR>
+               <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+                       <TD>
+                       If the IOP detects that its communication session with an SMP
+                       has closed, it will terminate any monitoring in progress,
+                       release any resources and close its end of the session.
+                       It will not maintain persistance of any information or prior mode of operation.
+                       </TD>
+               </TR>
+       </TABLE></TD></TR>
+</TABLE>
+</UL>
+
+<P>
+<H3>SMP/IOP Inter-Process Communication Protocol</H3>
+
+<UL>
+       <LI><P>Communications between an SMP and an IOP consists of a TCP session
+                       between an ephemeral port on the SMP and the well known port of 49152
+                       (which is the first available port in the 'dynamic and/or private port'
+                       range) on an IOP.
+       <LI><P>Following a TCP open operation the IOP receives a null terminated
+                       'interface ID' string to determine the type of operation that follows:
+       <LI><P>Every command received by an IOP implies a 'stop trace/stop forwarding' operation must
+                       occur before executing the received command.
+       <LI><P>A session is closed when the SMP closes the TCP session with the IOP.
+                       Obviously monitoring and forwarding is also stopped at that time.
+
+       <B>Note: </B>All multi-octet entities are sent in network neutral order.
+       <P>
+
+       <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP ROWSPAN=6>pcap_findalldevs()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>Open socket (to each IOP), and sends:
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>Interface ID</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>A NULL to indicate an an empty 'interface ID'.</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>Send its (possibly empty) NULL terminated error response string.</TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>Sends the 'interface query request':
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>Interface ID</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>A 'Q' (indicating 'interface query request').</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>The IOP returns a list of sequences of information as
+                               defined by the return parameter of this function call (as shown in the following table).
+                               Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                               <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Notes:</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                               </TR>
+                               <TR>
+                                       <TD ROWSPAN=7>&nbsp;</TD>
+                                       <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the name field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Name</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+                                       <TD VALIGN=TOP>The name of the interface. The format of the name is an alphabetic string (indicating
+                                                                       the type of interface) followed by an optional numeric string (indicating the interface's
+                                                                       sequence number).
+                                                                       Sequence numbers (if needed) will begin at zero and progress monotonically upwards.
+                                                                       (i.e. 'eth0', 'lo', 'wan0', etc.)
+                                                                       <P>
+                                                                       For an IOP, the alphabetic string will be one of: 'eth', 'wan', and 'lo'
+                                                                       for Ethernet, WAN ports and the IP loopback device respectively.
+                                                                       An IOP currently supports: 'eth0', 'eth1', 'lo', 'wan0' ... 'wan7'.
+                                                                       <P>
+                                               <B>Note:</B> IOPs and ACNs will not currently support the concept of 'any' interface.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the interface description field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Description</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+                                       <TD VALIGN=TOP>A description of the interface or it may be an empty string. (i.e. 'ALC')</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Type</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                       <TD VALIGN=TOP>The type of interface as defined in the description for pcap_datalink() (in network neutral order).</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Loopback Flag</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>1 = if the interface is a loopback interface, zero = otherwise.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=RIGHT>count</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP># of address entries that follow.
+                                               Each entry is a series of bytes in network neutral order.
+                                               See the parameter definition above for more details.</TD>
+                               </TR>
+                               <TR>
+                                       <TD ALIGN=CENTER ROWSPAN=8 WIDTH=1%>Repeated 'count' number of times.</TD>
+                                       <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the address field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Address</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+                                       <TD VALIGN=TOP>The address of this interface (in network neutral order).</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the netmask field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Network Mask</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+                                       <TD VALIGN=TOP>The network mask used on this interface (if applicable) (in network neutral order).</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the broadcast address field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Broadcast Address</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+                                       <TD VALIGN=TOP>The broadcast address of this interface (if applicable) (in network neutral order).</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                       <TD VALIGN=TOP>The number of octets in the destination address field that follows.</TD>
+                               </TR>
+                               <TR><TD VALIGN=TOP ALIGN=LEFT>Destination Address</TD>
+                                       <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+                                       <TD VALIGN=TOP>The destination address of this interface (if applicable) (in network neutral order).</TD>
+                               </TR>
+                               </TABLE>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>Close the socket.</TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>Close the socket.</TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP ROWSPAN=2>pcap_open_live()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>Open socket, and sends:
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>Interface ID</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+                                               <TD VALIGN=TOP>'n' octets containing a NULL terminated interface name string.</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>Send its NULL terminated error response string.</TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP NOWRAP ROWSPAN=2>pcap_dispatch()<BR>pcap_loop()<BR>pcap_next()<BR>pcap_next_ex()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>On the first invocation following a pcap_open_live() or pcap_breakloop() additional information is sent:
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>command</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>'M' (indicating 'monitor start')</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>snaplen</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                               <TD VALIGN=TOP>snaplen</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>timeout</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>timeout value (in milliseconds)</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>promiscuous</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>A flag indicating that the interface being monitored show operate
+                                                       in promiscuous mode. [off(0) / on(NZ)]</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>direction</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>A flag indicating the direction of traffic that should be captuted [both(0) / in(1) / out(2)]</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>Sends captured packets.</TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP ROWSPAN=2>pcap_setfilter()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>At any time, the SMP can issue a set filter command which contains
+                                                       an indicator, a count of the number of statements in the filter,
+                                                       followed by the sequence of filter commands represented as a sequence
+                                                       of C-style structures.
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>command</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>'F' (indicating 'filter')</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>count</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                               <TD VALIGN=TOP>The number of command in the Berkeley Packet Filter that follow.</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>BPF program</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+                                               <TD VALIGN=TOP>8 bytes of each command (repeated 'n' times).<BR>
+                                                                       Each command consists of that C-style structure which contains:
+                                                       <P>
+                                                       <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                                               <TR>
+                                                               <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                                               <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                                               <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                                               </TR>
+                                                               <TR>
+                                                                       <TD VALIGN=TOP>opcode</TD>
+                                                                       <TD VALIGN=TOP ALIGN=CENTER>2</TD>
+                                                                       <TD VALIGN=TOP>The command's opcode.</TD>
+                                                               </TR>
+                                                               <TR>
+                                                                       <TD VALIGN=TOP>'jt'</TD>
+                                                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                                                       <TD VALIGN=TOP>The 'jump if true' program counter offset.</TD>
+                                                               </TR>
+                                                               <TR>
+                                                                       <TD VALIGN=TOP>'jf'</TD>
+                                                                       <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                                                       <TD VALIGN=TOP>The 'jump if false' program counter offset.</TD>
+                                                               </TR>
+                                                               <TR>
+                                                                       <TD VALIGN=TOP>'k'</TD>
+                                                                       <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                                                       <TD VALIGN=TOP>The 'other' data field.</TD>
+                                                               </TR>
+                                                       </TABLE>
+                                                       <P>
+                                                       Refer to the bpf(4) man page for more details.
+                                               </TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>In return the IOP will send its (possibly empty) NULL terminated error response string.</TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP ROWSPAN=2>pcap_stats()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>At any time, the SMP can issue a 'retrieve statistics' command which contains:<BR>
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>command</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+                                               <TD VALIGN=TOP>'S' (indicating 'request statistics')</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+                       <TD VALIGN=TOP>In return the IOP will send:
+                               <P>
+                               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                                       <TR>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+                                       <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>ps_recv</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                               <TD VALIGN=TOP>The number of packets that passed the filter.</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>ps_drop</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                               <TD VALIGN=TOP>The number of packets that were dropped because the input queue was full,
+                                                       regardless of whether they passed the filter.</TD>
+                                       </TR>
+                                       <TR>
+                                               <TD VALIGN=TOP>ps_ifdrop</TD>
+                                               <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+                                               <TD VALIGN=TOP>The number of packets dropped by the network inteface
+                                                       (regardless of whether they would have passed the input filter).</TD>
+                                       </TR>
+                               </TABLE>
+                       </TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+               <TR>
+                       <TD VALIGN=TOP ROWSPAN=1>pcap_close()</TD>
+                       <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+                       <TD VALIGN=TOP>At any time, the SMP can close the TCP session with the IOP.</TD>
+               </TR>
+               <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+       </TABLE>
+</UL>
+
+<H3>Interface ID Naming Convention</H3>
+<UL>
+       Each interface within an IOP will be referred to uniquely.  Since an currently contains
+       8 monitorable WAN ports and a monitorable Ethernet port, the naming convention is:
+       <P>
+       <CENTER>
+       <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+               <TR><TH>Interface #</TH>                <TH>Type</TH>                                   <TH>Name</TH></TR>
+               <TR><TD ALIGN=CENTER>1</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan0</TD></TR>
+               <TR><TD ALIGN=CENTER>2</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan1</TD></TR>
+               <TR><TD ALIGN=CENTER>3</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan2</TD></TR>
+               <TR><TD ALIGN=CENTER>4</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan3</TD></TR>
+               <TR><TD ALIGN=CENTER>5</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan4</TD></TR>
+               <TR><TD ALIGN=CENTER>6</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan5</TD></TR>
+               <TR><TD ALIGN=CENTER>7</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan6</TD></TR>
+               <TR><TD ALIGN=CENTER>8</TD>             <TD ALIGN=CENTER>WAN</TD>               <TD ALIGN=CENTER>wan7</TD></TR>
+               <TR><TD ALIGN=CENTER>9</TD>             <TD ALIGN=CENTER>Ethernet</TD>  <TD ALIGN=CENTER>eth0</TD></TR>
+               <TR><TD ALIGN=CENTER>10</TD>    <TD ALIGN=CENTER>Ethernet</TD>  <TD ALIGN=CENTER>eth1</TD></TR>
+       </TABLE>
+       </CENTER>
+</UL>
+
+<H3>Packet Trace Data Format</H3>
+<UL>
+       The format of the trace data that is sent to the SMP follows a portion of the libpcap file format
+       and is summarized here.  This format specifies the generic requirements needed to
+       be able to decode packets, but does not cover ACN specifics such as custom MAC addressing
+       and WAN protocol support.
+       <P>
+
+       Although a libpcap file begins with a global header followed by zero or
+       more records for each captured packet, trace data sent to the SMP does NOT begin with a global header.
+       A trace sequence looks like this:
+       <P>
+       <TABLE>
+               <TR>
+                       <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Header]&nbsp;</TD>
+                       <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Data]&nbsp;</TD>
+                       <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Header]&nbsp;</TD>
+                       <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Data]&nbsp;</TD>
+                       <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Header]&nbsp;</TD>
+                       <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Data]&nbsp;</TD>
+                       <TD>...</TD>
+               </TR>
+       </TABLE>
+
+<H4>Packet Header</H4>
+       <UL>
+               Each captured packet starts with a header that contains the following values
+               (in network neutral order):
+
+               <FONT SIZE=-1>
+               <PRE>
+ uint32 tv_sec;  /* timestamp seconds */
+ uint32 tv_usec; /* timestamp microseconds */
+ uint32 caplen;  /* number of octets in the following packet */
+ uint32 len;     /* original length of packet on the wire */
+               </PRE>
+               </FONT>
+
+               <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+                       <TR>
+                               <TD VALIGN=TOP>tv_sec</TD>
+                               <TD>The date and time when this packet was captured.
+                                       This value is in seconds since January 1, 1970 00:00:00 GMT;
+                                       this is also known as a UN*X time_t. You can use the ANSI C
+                                       <em>time()</em> function from <em>time.h</em> to get this value,
+                                       but you might use a more optimized way to get this timestamp value.
+                                       If this timestamp isn't based on GMT (UTC), use <em>thiszone</em>
+                                       from the global header for adjustments.</TD>
+                       </TR>
+                       <TR>
+                               <TD VALIGN=TOP>tv_usec</TD>
+                               <TD>The microseconds when this packet was captured, as an offset to <em>ts_sec</em>.
+                                       <B>Beware: </B>this value must never reach 1 second (1,000,000),
+                                       in this case <em>ts_sec</em> must be increased instead!</TD>
+                       </TR>
+                       <TR>
+                               <TD VALIGN=TOP>caplen</TD>
+                               <TD>The number of bytes actually provided in the capture record.
+                                       This value should never become larger than <em>len</em> or the
+                                       <em>snaplen</em> value specified during the capture.</TD>
+                       </TR>
+                       <TR>
+                               <TD VALIGN=TOP>len</TD>
+                               <TD>The length of the packet "on the wire" when it was captured.
+                                       If <em>caplen</em> and <em>len</em> differ, the actually
+                                       saved packet size was limited by the value of <em>snaplen</em> specified
+                                       during one of the capture directives such as pcap_dispatch().</TD>
+                       </TR>
+               </TABLE>
+       </UL>
+
+<H4>Packet Data</H4>
+       <UL>
+       The actual packet data will immediately follow the packet header as a sequence of <em>caplen</em> octets.
+       Depending on the DLT encoding number assigned to the interface, the packet data will contain an additional
+       custom header used to convey WAN port related information.
+       </UL>
+
+<H4>ACN Custom Packet Header</H4>
+       <UL>
+       PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support
+       monitoring of its ports, however each of these facilities were focused on capturing
+       and displaying traffic from LAN interfaces.  The SITA extentions to these facilities
+       are used to also provide the ability to capture, filter, and display information from
+       an ACN's WAN ports.
+       <P>
+       Although each packet follows the standard libpcap format, since there are
+       two types of interfaces that can be monitored, the format of the data
+       packet varies slightly.
+       <P>
+       <UL TYPE=DISC>
+               <LI>For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format.
+               <LI>For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data
+                       described by the following table:
+       </UL>
+       <P>
+       <CENTER>
+       <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+       <TR>    <TH>Octet</TH>
+                       <TH>Name</TH>
+                       <TH>Mask/Value</TH>
+                       <TH COLSPAN=2>Definition</TH>           </TR>
+
+       <TR>    <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>0</TH>
+                       <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>Control / Status</TH>
+
+                       <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx0</FONT></TD>
+                       <TD>Transmitted by capture device</TD>
+                       <TD ROWSPAN=2 ALIGN=CENTER>(see 'Errors' octets)</TD>                                                   </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>
+                       <TD>Received by capture device</TD>                                                                                             </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>
+                       <TD COLSPAN=2>No buffer was available during capture of previous packet.</TD>   </TR>
+
+       <TR>    <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>1</TH>
+                       <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>Signals</TH>
+
+                       <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>   <TD COLSPAN=2>DSR asserted</TD>         </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>   <TD COLSPAN=2>DTR asserted</TD>         </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>   <TD COLSPAN=2>CTS asserted</TD>         </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>   <TD COLSPAN=2>RTS asserted</TD>         </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>   <TD COLSPAN=2>DCD asserted</TD>         </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>   <TD COLSPAN=2>Undefined</TD>            </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>   <TD COLSPAN=2>Undefined</TD>            </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>   <TD COLSPAN=2>Undefined</TD>            </TR>
+
+       <TR>    <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>2</TH>
+                       <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 1)</TH>
+
+                       <TH>&nbsp;</TH>                                                                                                                 <TH>Tx</TH>                                             <TH>Rx</TH>                             </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>   <TD>Underrun</TD>                               <TD>Framing</TD>                </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>   <TD>CTS Lost</TD>                               <TD>Parity</TD>                 </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>   <TD>UART Error</TD>                             <TD>Collision</TD>              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>   <TD>Re-Tx Limit Reached</TD>    <TD>Long Frame</TD>             </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>   <TD>Undefined</TD>                              <TD>Short Frame</TD>    </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>   <TD>Undefined</TD>                              <TD>Undefined</TD>              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>   <TD>Undefined</TD>                              <TD>Undefined</TD>              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>   <TD>Undefined</TD>                              <TD>Undefined</TD>              </TR>
+
+       <TR>    <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>3</TH>
+                       <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 2)</TH>
+
+                       <TH>&nbsp;</TH>                                                                                                                 <TH>Tx</TH>                     <TH>Rx</TH>                                             </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>   <TD>Undefined</TD>      <TD>Non-Octet Aligned</TD>              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD>   <TD>Undefined</TD>      <TD>Abort Received</TD>                 </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD>   <TD>Undefined</TD>      <TD>CD Lost</TD>                                </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD>   <TD>Undefined</TD>      <TD>Digital PLL Error</TD>              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD>   <TD>Undefined</TD>      <TD>Overrun</TD>                                </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD>   <TD>Undefined</TD>      <TD>Frame Length Violation</TD> </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD>   <TD>Undefined</TD>      <TD>CRC Error</TD>                              </TR>
+       <TR>    <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>   <TD>Undefined</TD>      <TD>Break Received</TD>                 </TR>
+
+       <TR>    <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=12>4</TH>
+                       <TH VALIGN=TOP ALIGN=CENTER>Protocol</TH>
+
+                       <TD COLSPAN=3>
+                               <CENTER>
+                               <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x01</TD>    <TD>-</TD>      <TD>LAPB (BOP)                          <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x02</TD>    <TD>-</TD>      <TD>Ethernet                            <SUP>1</SUP>            </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x03</TD>    <TD>-</TD>      <TD>Async (Interrupt IO)        <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x04</TD>    <TD>-</TD>      <TD>Async (Block IO)            <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x05</TD>    <TD>-</TD>      <TD>IPARS                                       <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x06</TD>    <TD>-</TD>      <TD>UTS                                         <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x07</TD>    <TD>-</TD>      <TD>PPP (HDLC)                          <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x08</TD>    <TD>-</TD>      <TD>SDLC                                        <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x09</TD>    <TD>-</TD>      <TD>Token Ring                          <SUP>1</SUP>            </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x10</TD>    <TD>-</TD>      <TD>I2C                                         <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x11</TD>    <TD>-</TD>      <TD>DPM Link                            <SUP>&nbsp;</SUP>       </TD>   </TR>
+                                       <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x12</TD>    <TD>-</TD>      <TD>Frame Relay (BOP)           <SUP>&nbsp;</SUP>       </TD>   </TR>
+                               </TABLE>
+                               </CENTER>
+                               <P>
+                               <STRONG>Note 1:</STRONG>
+                               Ethernet and Token Ring frames will never be sent as DLT_SITA (with the 5 octet header),
+                               but will be sent as their corresponding DLT types instead.
+                       </TD>
+       </TR>
+       </TABLE>
+       </CENTER>
+</UL>
+<P>
+</UL>
+</UL>
diff --git a/pcap-snf.c b/pcap-snf.c
new file mode 100644 (file)
index 0000000..96781bd
--- /dev/null
@@ -0,0 +1,306 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "snf.h"
+#include "pcap-int.h"
+
+#ifdef SNF_ONLY
+#define snf_create pcap_create
+#define snf_platform_finddevs pcap_platform_finddevs
+#endif
+
+static int
+snf_set_datalink(pcap_t *p, int dlt)
+{
+       p->linktype = dlt;
+       return (0);
+}
+
+static int
+snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       struct snf_ring_stats stats;
+       int rc;
+
+       if ((rc = snf_ring_getstats(p->md.snf_ring, &stats))) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
+                        pcap_strerror(rc));
+               return -1;
+       }
+       ps->ps_recv = stats.ring_pkt_recv + stats.ring_pkt_overflow;
+       ps->ps_drop = stats.ring_pkt_overflow;
+       ps->ps_ifdrop = stats.nic_pkt_overflow + stats.nic_pkt_bad;
+       return 0;
+}
+
+static void
+snf_platform_cleanup(pcap_t *p)
+{
+       if (p == NULL)
+               return;
+
+       snf_ring_close(p->md.snf_ring);
+       snf_close(p->md.snf_handle);
+       pcap_cleanup_live_common(p);
+}
+
+static int
+snf_getnonblock(pcap_t *p, char *errbuf)
+{
+       return (p->md.snf_timeout == 0);
+}
+
+static int
+snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+       if (nonblock)
+               p->md.snf_timeout = 0;
+       else {
+               if (p->md.timeout <= 0)
+                       p->md.snf_timeout = -1; /* forever */
+               else
+                       p->md.snf_timeout = p->md.timeout;
+       }
+       return (0);
+}
+
+#define _NSEC_PER_SEC 1000000000
+
+static inline
+struct timeval
+snf_timestamp_to_timeval(const int64_t ts_nanosec)
+{
+       struct timeval tv;
+       int32_t rem;
+       if (ts_nanosec == 0)
+               return (struct timeval) { 0, 0 };
+       tv.tv_sec = ts_nanosec / _NSEC_PER_SEC;
+       tv.tv_usec = (ts_nanosec % _NSEC_PER_SEC) / 1000;
+       return tv;
+}
+
+static int
+snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       struct pcap_pkthdr hdr;
+       int i, flags, err, caplen, n;
+       struct snf_recv_req req;
+
+       if (!p || cnt == 0)
+               return -1;
+
+       n = 0;
+       while (n < cnt || cnt < 0) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else {
+                               return (n);
+                       }
+               }
+
+               err = snf_ring_recv(p->md.snf_ring, p->md.snf_timeout, &req);
+
+               if (err) {
+                       if (err == EBUSY || err == EAGAIN)
+                               return (0);
+                       if (err == EINTR)
+                               continue;
+                       if (err != 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
+                                        pcap_strerror(err));
+                               return -1;
+                       }
+               }
+
+               caplen = req.length;
+               if (caplen > p->snapshot)
+                       caplen = p->snapshot;
+
+               if ((p->fcode.bf_insns == NULL) ||
+                    bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
+                       hdr.ts = snf_timestamp_to_timeval(req.timestamp);
+                       hdr.caplen = caplen;
+                       hdr.len = req.length;
+                       callback(user, &hdr, req.pkt_addr);
+               }
+               n++;
+       }
+       return (n);
+}
+
+static int
+snf_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       if (!p)
+               return -1;
+       if (!fp) {
+               strncpy(p->errbuf, "setfilter: No filter specified",
+                       sizeof(p->errbuf));
+               return -1;
+       }
+
+       /* Make our private copy of the filter */
+
+       if (install_bpf_program(p, fp) < 0)
+               return -1;
+
+       p->md.use_bpf = 0;
+
+       return (0);
+}
+
+static int
+snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+       strlcpy(p->errbuf, "Sending packets isn't supported with snf",
+           PCAP_ERRBUF_SIZE);
+       return (-1);
+}
+
+static int
+snf_activate(pcap_t* p)
+{
+       char *device = p->opt.source;
+       const char *nr = NULL;
+       int err;
+       int flags = 0;
+
+       if (device == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        "device is NULL: %s", pcap_strerror(errno));
+               return -1;
+       }
+
+       /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1.
+        * Since libpcap isn't thread-safe */
+       if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1)
+               flags |= SNF_F_PSHARED;
+       else
+               nr = NULL;
+
+       err = snf_open(p->md.snf_boardnum,
+                       0, /* let SNF API parse SNF_NUM_RINGS, if set */
+                       NULL, /* default RSS, or use SNF_RSS_FLAGS env */
+                       0, /* default to SNF_DATARING_SIZE from env */
+                       flags, /* may want pshared */
+                       &p->md.snf_handle);
+       if (err != 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        "snf_open failed: %s", pcap_strerror(err));
+               return -1;
+       }
+
+       err = snf_ring_open(p->md.snf_handle, &p->md.snf_ring);
+       if (err != 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        "snf_ring_open failed: %s", pcap_strerror(err));
+               return -1;
+       }
+
+       if (p->md.timeout <= 0)
+               p->md.snf_timeout = -1;
+       else
+               p->md.snf_timeout = p->md.timeout;
+
+       err = snf_start(p->md.snf_handle);
+       if (err != 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        "snf_start failed: %s", pcap_strerror(err));
+               return -1;
+       }
+
+       /*
+        * "select()" and "poll()" don't work on snf descriptors.
+        */
+       p->selectable_fd = -1;
+       p->linktype = DLT_EN10MB;
+       p->read_op = snf_read;
+       p->inject_op = snf_inject;
+       p->setfilter_op = snf_setfilter;
+       p->setdirection_op = NULL; /* Not implemented.*/
+       p->set_datalink_op = snf_set_datalink;
+       p->getnonblock_op = snf_getnonblock;
+       p->setnonblock_op = snf_setnonblock;
+       p->stats_op = snf_pcap_stats;
+       p->cleanup_op = snf_platform_cleanup;
+       p->md.stat.ps_recv = 0;
+       p->md.stat.ps_drop = 0;
+       p->md.stat.ps_ifdrop = 0;
+       return 0;
+}
+
+int
+snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
+{
+       /*
+        * There are no platform-specific devices since each device
+        * exists as a regular Ethernet device.
+        */
+       return 0;
+}
+
+pcap_t *
+snf_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+       int boardnum = -1;
+       struct snf_ifaddrs *ifaddrs, *ifa;
+       size_t devlen;
+
+       if (snf_init(SNF_VERSION_API))
+               return NULL;
+
+       /*
+        * Match a given interface name to our list of interface names, from
+        * which we can obtain the intended board number
+        */
+       if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
+               return NULL;
+       devlen = strlen(device) + 1;
+       ifa = ifaddrs;
+       while (ifa) {
+               if (!strncmp(device, ifa->snf_ifa_name, devlen)) {
+                       boardnum = ifa->snf_ifa_boardnum;
+                       break;
+               }
+               ifa = ifa->snf_ifa_next;
+       }
+       snf_freeifaddrs(ifaddrs);
+
+       if (ifa == NULL) {
+               /*
+                * If we can't find the device by name, support the name "snfX"
+                * and "snf10gX" where X is the board number.
+                */
+               if (sscanf(device, "snf10g%d", &boardnum) != 1 &&
+                   sscanf(device, "snf%d", &boardnum) != 1)
+                       return NULL;
+       }
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return NULL;
+
+       p->activate_op = snf_activate;
+       p->md.snf_boardnum = boardnum;
+       return p;
+}
diff --git a/pcap-snf.h b/pcap-snf.h
new file mode 100644 (file)
index 0000000..8c19755
--- /dev/null
@@ -0,0 +1,2 @@
+pcap_t *snf_create(const char *, char *);
+int snf_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
diff --git a/pcap-snit.c b/pcap-snit.c
new file mode 100644 (file)
index 0000000..fa0c4ef
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * 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.
+ *
+ * Modifications made to accommodate the new SunOS4.0 NIT facility by
+ * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
+ * This module now handles the STREAMS based NIT.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.77 2008-04-14 20:40:58 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/dir.h>
+#include <sys/fcntlcom.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stropts.h>
+
+#include <net/if.h>
+#include <net/nit.h>
+#include <net/nit_if.h>
+#include <net/nit_pf.h>
+#include <net/nit_buf.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * The chunk size for NIT.  This is the amount of buffering
+ * done for read calls.
+ */
+#define CHUNKSIZE (2*1024)
+
+/*
+ * The total buffer space used by NIT.
+ */
+#define BUFSPACE (4*CHUNKSIZE)
+
+/* Forwards */
+static int nit_setflags(int, int, int, char *);
+
+static int
+pcap_stats_snit(pcap_t *p, struct pcap_stat *ps)
+{
+
+       /*
+        * "ps_recv" counts packets handed to the filter, not packets
+        * that passed the filter.  As filtering is done in userland,
+        * this does not include packets dropped because we ran out
+        * of buffer space.
+        *
+        * "ps_drop" counts packets dropped inside the "/dev/nit"
+        * device because of flow control requirements or resource
+        * exhaustion; it doesn't count packets dropped by the
+        * interface driver, or packets dropped upstream.  As filtering
+        * is done in userland, it counts packets regardless of whether
+        * they would've passed the filter.
+        *
+        * These statistics don't include packets not yet read from the
+        * kernel by libpcap or packets not yet read from libpcap by the
+        * application.
+        */
+       *ps = p->md.stat;
+       return (0);
+}
+
+static int
+pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc, n;
+       register u_char *bp, *cp, *ep;
+       register struct nit_bufhdr *hdrp;
+       register struct nit_iftime *ntp;
+       register struct nit_iflen *nlp;
+       register struct nit_ifdrops *ndp;
+       register int caplen;
+
+       cc = p->cc;
+       if (cc == 0) {
+               cc = read(p->fd, (char *)p->buffer, p->bufsize);
+               if (cc < 0) {
+                       if (errno == EWOULDBLOCK)
+                               return (0);
+                       snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+                               pcap_strerror(errno));
+                       return (-1);
+               }
+               bp = p->buffer;
+       } else
+               bp = p->bp;
+
+       /*
+        * loop through each snapshot in the chunk
+        */
+       n = 0;
+       ep = bp + cc;
+       while (bp < ep) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else {
+                               p->bp = bp;
+                               p->cc = ep - bp;
+                               return (n);
+                       }
+               }
+
+               ++p->md.stat.ps_recv;
+               cp = bp;
+
+               /* get past NIT buffer  */
+               hdrp = (struct nit_bufhdr *)cp;
+               cp += sizeof(*hdrp);
+
+               /* get past NIT timer   */
+               ntp = (struct nit_iftime *)cp;
+               cp += sizeof(*ntp);
+
+               ndp = (struct nit_ifdrops *)cp;
+               p->md.stat.ps_drop = ndp->nh_drops;
+               cp += sizeof *ndp;
+
+               /* get past packet len  */
+               nlp = (struct nit_iflen *)cp;
+               cp += sizeof(*nlp);
+
+               /* next snapshot        */
+               bp += hdrp->nhb_totlen;
+
+               caplen = nlp->nh_pktlen;
+               if (caplen > p->snapshot)
+                       caplen = p->snapshot;
+
+               if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) {
+                       struct pcap_pkthdr h;
+                       h.ts = ntp->nh_timestamp;
+                       h.len = nlp->nh_pktlen;
+                       h.caplen = caplen;
+                       (*callback)(user, &h, cp);
+                       if (++n >= cnt && cnt > 0) {
+                               p->cc = ep - bp;
+                               p->bp = bp;
+                               return (n);
+                       }
+               }
+       }
+       p->cc = 0;
+       return (n);
+}
+
+static int
+pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
+{
+       struct strbuf ctl, data;
+       
+       /*
+        * XXX - can we just do
+        *
+       ret = write(pd->f, buf, size);
+        */
+       ctl.len = sizeof(*sa);  /* XXX - what was this? */
+       ctl.buf = (char *)sa;
+       data.buf = buf;
+       data.len = size;
+       ret = putmsg(p->fd, &ctl, &data);
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (ret);
+}
+
+static int
+nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
+{
+       bpf_u_int32 flags;
+       struct strioctl si;
+       struct timeval timeout;
+
+       si.ic_timout = INFTIM;
+       if (to_ms != 0) {
+               timeout.tv_sec = to_ms / 1000;
+               timeout.tv_usec = (to_ms * 1000) % 1000000;
+               si.ic_cmd = NIOCSTIME;
+               si.ic_len = sizeof(timeout);
+               si.ic_dp = (char *)&timeout;
+               if (ioctl(fd, I_STR, (char *)&si) < 0) {
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
+                           pcap_strerror(errno));
+                       return (-1);
+               }
+       }
+       flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
+       if (promisc)
+               flags |= NI_PROMISC;
+       si.ic_cmd = NIOCSFLAGS;
+       si.ic_len = sizeof(flags);
+       si.ic_dp = (char *)&flags;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+static int
+pcap_activate_snit(pcap_t *p)
+{
+       struct strioctl si;             /* struct for ioctl() */
+       struct ifreq ifr;               /* interface request struct */
+       int chunksize = CHUNKSIZE;
+       int fd;
+       static char dev[] = "/dev/nit";
+
+       if (p->opt.rfmon) {
+               /*
+                * No monitor mode on SunOS 4.x (no Wi-Fi devices on
+                * hardware supported by SunOS 4.x).
+                */
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+       if (p->snapshot < 96)
+               /*
+                * NIT requires a snapshot length of at least 96.
+                */
+               p->snapshot = 96;
+
+       /*
+        * Initially try a read/write open (to allow the inject
+        * method to work).  If that fails due to permission
+        * issues, fall back to read-only.  This allows a
+        * non-root user to be granted specific access to pcap
+        * capabilities via file permissions.
+        *
+        * XXX - we should have an API that has a flag that
+        * controls whether to open read-only or read-write,
+        * so that denial of permission to send (or inability
+        * to send, if sending packets isn't supported on
+        * the device in question) can be indicated at open
+        * time.
+        */
+       p->fd = fd = open(dev, O_RDWR);
+       if (fd < 0 && errno == EACCES)
+               p->fd = fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* arrange to get discrete messages from the STREAM and use NIT_BUF */
+       if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       if (ioctl(fd, I_PUSH, "nbuf") < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       /* set the chunksize */
+       si.ic_cmd = NIOCSCHUNK;
+       si.ic_timout = INFTIM;
+       si.ic_len = sizeof(chunksize);
+       si.ic_dp = (char *)&chunksize;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* request the interface */
+       strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+       ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+       si.ic_cmd = NIOCBIND;
+       si.ic_len = sizeof(ifr);
+       si.ic_dp = (char *)&ifr;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
+                       ifr.ifr_name, pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* set the snapshot length */
+       si.ic_cmd = NIOCSSNAP;
+       si.ic_len = sizeof(p->snapshot);
+       si.ic_dp = (char *)&p->snapshot;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0)
+               goto bad;
+
+       (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
+       /*
+        * NIT supports only ethernets.
+        */
+       p->linktype = DLT_EN10MB;
+
+       p->bufsize = BUFSPACE;
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+               goto bad;
+       }
+
+       /*
+        * "p->fd" is an FD for a STREAMS device, so "select()" and
+        * "poll()" should work on it.
+        */
+       p->selectable_fd = p->fd;
+
+       /*
+        * This is (presumably) a real Ethernet capture; give it a
+        * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+        * that an application can let you choose it, in case you're
+        * capturing DOCSIS traffic that a Cisco Cable Modem
+        * Termination System is putting out onto an Ethernet (it
+        * doesn't put an Ethernet header onto the wire, it puts raw
+        * DOCSIS frames out on the wire inside the low-level
+        * Ethernet framing).
+        */
+       p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+       /*
+        * If that fails, just leave the list empty.
+        */
+       if (p->dlt_list != NULL) {
+               p->dlt_list[0] = DLT_EN10MB;
+               p->dlt_list[1] = DLT_DOCSIS;
+               p->dlt_count = 2;
+       }
+
+       p->read_op = pcap_read_snit;
+       p->inject_op = pcap_inject_snit;
+       p->setfilter_op = install_bpf_program;  /* no kernel filtering */
+       p->setdirection_op = NULL;      /* Not implemented. */
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_snit;
+
+       return (0);
+ bad:
+       pcap_cleanup_live_common(p);
+       return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_snit;
+       return (p);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
diff --git a/pcap-snoop.c b/pcap-snoop.c
new file mode 100644 (file)
index 0000000..330e01d
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.59 2008-12-02 16:25:14 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/raw.h>
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static int
+pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       register struct snoopheader *sh;
+       register u_int datalen;
+       register u_int caplen;
+       register u_char *cp;
+
+again:
+       /*
+        * Has "pcap_breakloop()" been called?
+        */
+       if (p->break_loop) {
+               /*
+                * Yes - clear the flag that indicates that it
+                * has, and return -2 to indicate that we were
+                * told to break out of the loop.
+                */
+               p->break_loop = 0;
+               return (-2);
+       }
+       cc = read(p->fd, (char *)p->buffer, p->bufsize);
+       if (cc < 0) {
+               /* Don't choke when we get ptraced */
+               switch (errno) {
+
+               case EINTR:
+                       goto again;
+
+               case EWOULDBLOCK:
+                       return (0);                     /* XXX */
+               }
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                   "read: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       sh = (struct snoopheader *)p->buffer;
+       datalen = sh->snoop_packetlen;
+
+       /*
+        * XXX - Sigh, snoop_packetlen is a 16 bit quantity.  If we
+        * got a short length, but read a full sized snoop pakcet,
+        * assume we overflowed and add back the 64K...
+        */
+       if (cc == (p->snapshot + sizeof(struct snoopheader)) &&
+           (datalen < p->snapshot))
+               datalen += (64 * 1024);
+
+       caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
+       cp = (u_char *)(sh + 1) + p->offset;            /* XXX */
+
+       /* 
+        * XXX unfortunately snoop loopback isn't exactly like
+        * BSD's.  The address family is encoded in the first 2
+        * bytes rather than the first 4 bytes!  Luckily the last
+        * two snoop loopback bytes are zeroed.
+        */
+       if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) {
+               u_int *uip = (u_int *)cp;
+               *uip >>= 16;
+       }
+
+       if (p->fcode.bf_insns == NULL ||
+           bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
+               struct pcap_pkthdr h;
+               ++p->md.stat.ps_recv;
+               h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
+               h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
+               h.len = datalen;
+               h.caplen = caplen;
+               (*callback)(user, &h, cp);
+               return (1);
+       }
+       return (0);
+}
+
+static int
+pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
+{
+       int ret;
+
+       /*
+        * XXX - libnet overwrites the source address with what I
+        * presume is the interface's address; is that required?
+        */
+       ret = write(p->fd, buf, size);
+       if (ret == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (ret);
+}                           
+
+static int
+pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
+{
+       register struct rawstats *rs;
+       struct rawstats rawstats;
+
+       rs = &rawstats;
+       memset(rs, 0, sizeof(*rs));
+       if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                   "SIOCRAWSTATS: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       /*
+        * "ifdrops" are those dropped by the network interface
+        * due to resource shortages or hardware errors.
+        *
+        * "sbdrops" are those dropped due to socket buffer limits.
+        *
+        * As filter is done in userland, "sbdrops" counts packets
+        * regardless of whether they would've passed the filter.
+        *
+        * XXX - does this count *all* Snoop or Drain sockets,
+        * rather than just this socket?  If not, why does it have
+        * both Snoop and Drain statistics?
+        */
+       p->md.stat.ps_drop =
+           rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
+           rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
+
+       /*
+        * "ps_recv" counts only packets that passed the filter.
+        * As filtering is done in userland, this does not include
+        * packets dropped because we ran out of buffer space.
+        */
+       *ps = p->md.stat;
+       return (0);
+}
+
+/* XXX can't disable promiscuous */
+static int
+pcap_activate_snoop(pcap_t *p)
+{
+       int fd;
+       struct sockaddr_raw sr;
+       struct snoopfilter sf;
+       u_int v;
+       int ll_hdrlen;
+       int snooplen;
+       struct ifreq ifr;
+
+       fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
+       if (fd < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       p->fd = fd;
+       memset(&sr, 0, sizeof(sr));
+       sr.sr_family = AF_RAW;
+       (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
+       if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       memset(&sf, 0, sizeof(sf));
+       if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       if (p->opt.buffer_size != 0)
+               v = p->opt.buffer_size;
+       else
+               v = 64 * 1024;  /* default to 64K buffer size */
+       (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
+       /*
+        * XXX hack - map device name to link layer type
+        */
+       if (strncmp("et", p->opt.source, 2) == 0 ||     /* Challenge 10 Mbit */
+           strncmp("ec", p->opt.source, 2) == 0 ||     /* Indigo/Indy 10 Mbit,
+                                                          O2 10/100 */
+           strncmp("ef", p->opt.source, 2) == 0 ||     /* O200/2000 10/100 Mbit */
+           strncmp("eg", p->opt.source, 2) == 0 ||     /* Octane/O2xxx/O3xxx Gigabit */
+           strncmp("gfe", p->opt.source, 3) == 0 ||    /* GIO 100 Mbit */
+           strncmp("fxp", p->opt.source, 3) == 0 ||    /* Challenge VME Enet */
+           strncmp("ep", p->opt.source, 2) == 0 ||     /* Challenge 8x10 Mbit EPLEX */
+           strncmp("vfe", p->opt.source, 3) == 0 ||    /* Challenge VME 100Mbit */
+           strncmp("fa", p->opt.source, 2) == 0 ||
+           strncmp("qaa", p->opt.source, 3) == 0 ||
+           strncmp("cip", p->opt.source, 3) == 0 ||
+           strncmp("el", p->opt.source, 2) == 0) {
+               p->linktype = DLT_EN10MB;
+               p->offset = RAW_HDRPAD(sizeof(struct ether_header));
+               ll_hdrlen = sizeof(struct ether_header);
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                *
+                * XXX - are there any sorts of "fake Ethernet" that have
+                * Ethernet link-layer headers but that *shouldn't offer
+                * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it
+                * or get traffic bridged onto it?  "el" is for ATM LANE
+                * Ethernet devices, so that might be the case for them;
+                * the same applies for "qaa" classical IP devices.  If
+                * "fa" devices are for FORE SPANS, that'd apply to them
+                * as well; what are "cip" devices - some other ATM
+                * Classical IP devices?
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+       } else if (strncmp("ipg", p->opt.source, 3) == 0 ||
+                  strncmp("rns", p->opt.source, 3) == 0 ||     /* O2/200/2000 FDDI */
+                  strncmp("xpi", p->opt.source, 3) == 0) {
+               p->linktype = DLT_FDDI;
+               p->offset = 3;                          /* XXX yeah? */
+               ll_hdrlen = 13;
+       } else if (strncmp("ppp", p->opt.source, 3) == 0) {
+               p->linktype = DLT_RAW;
+               ll_hdrlen = 0;  /* DLT_RAW meaning "no PPP header, just the IP packet"? */
+       } else if (strncmp("qfa", p->opt.source, 3) == 0) {
+               p->linktype = DLT_IP_OVER_FC;
+               ll_hdrlen = 24;
+       } else if (strncmp("pl", p->opt.source, 2) == 0) {
+               p->linktype = DLT_RAW;
+               ll_hdrlen = 0;  /* Cray UNICOS/mp pseudo link */
+       } else if (strncmp("lo", p->opt.source, 2) == 0) {
+               p->linktype = DLT_NULL;
+               ll_hdrlen = 4;
+       } else {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "snoop: unknown physical layer type");
+               goto bad;
+       }
+
+       if (p->opt.rfmon) {
+               /*
+                * No monitor mode on Irix (no Wi-Fi devices on
+                * hardware supported by Irix).
+                */
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+#ifdef SIOCGIFMTU
+       /*
+        * XXX - IRIX appears to give you an error if you try to set the
+        * capture length to be greater than the MTU, so let's try to get
+        * the MTU first and, if that succeeds, trim the snap length
+        * to be no greater than the MTU.
+        */
+       (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       /*
+        * OK, we got it.
+        *
+        * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an
+        * "ifru_metric" member of the "ifr_ifru" union in an "ifreq"
+        * structure, others don't.
+        *
+        * I've no idea what's going on, so, if "ifr_mtu" isn't defined,
+        * we define it as "ifr_metric", as using that field appears to
+        * work on the versions that lack "ifr_mtu" (and, on those that
+        * don't lack it, "ifru_metric" and "ifru_mtu" are both "int"
+        * members of the "ifr_ifru" union, which suggests that they
+        * may be interchangeable in this case).
+        */
+#ifndef ifr_mtu
+#define ifr_mtu        ifr_metric
+#endif
+       if (p->snapshot > ifr.ifr_mtu + ll_hdrlen)
+               p->snapshot = ifr.ifr_mtu + ll_hdrlen;
+#endif
+
+       /*
+        * The argument to SIOCSNOOPLEN is the number of link-layer
+        * payload bytes to capture - it doesn't count link-layer
+        * header bytes.
+        */
+       snooplen = p->snapshot - ll_hdrlen;
+       if (snooplen < 0)
+               snooplen = 0;
+       if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+       v = 1;
+       if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       p->bufsize = 4096;                              /* XXX */
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                   pcap_strerror(errno));
+               goto bad;
+       }
+
+       /*
+        * "p->fd" is a socket, so "select()" should work on it.
+        */
+       p->selectable_fd = p->fd;
+
+       p->read_op = pcap_read_snoop;
+       p->inject_op = pcap_inject_snoop;
+       p->setfilter_op = install_bpf_program;  /* no kernel filtering */
+       p->setdirection_op = NULL;      /* Not implemented. */
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_stats_snoop;
+
+       return (0);
+ bad:
+       pcap_cleanup_live_common(p);
+       return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_snoop;
+       return (p);
+}
+
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
diff --git a/pcap-stdinc.h b/pcap-stdinc.h
new file mode 100644 (file)
index 0000000..f1c736e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL)
+ */
+#ifndef pcap_stdinc_h
+#define pcap_stdinc_h
+
+/*
+ * Avoids a compiler warning in case this was already defined      
+ * (someone defined _WINSOCKAPI_ when including 'windows.h', in order
+ * to prevent it from including 'winsock.h')
+ */
+#ifdef _WINSOCKAPI_
+#undef _WINSOCKAPI_
+#endif
+#include <winsock2.h>
+
+#include <fcntl.h>
+
+#include "bittypes.h"
+#include <time.h>
+#include <io.h>
+
+#ifndef __MINGW32__
+#include "IP6_misc.h"
+#endif
+
+#define caddr_t char*
+
+#if _MSC_VER < 1500
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define strdup _strdup
+#endif
+
+#define inline __inline 
+
+#ifdef __MINGW32__
+#include <stdint.h>
+#else /*__MINGW32__*/
+/* MSVC compiler */
+#ifndef _UINTPTR_T_DEFINED
+#ifdef  _WIN64
+typedef unsigned __int64    uintptr_t;
+#else
+typedef _W64 unsigned int   uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+
+#ifndef _INTPTR_T_DEFINED
+#ifdef  _WIN64
+typedef __int64    intptr_t;
+#else
+typedef _W64 int   intptr_t;
+#endif
+#define _INTPTR_T_DEFINED
+#endif 
+
+#endif /*__MINGW32__*/
+#endif /* pcap_stdinc_h */
diff --git a/pcap-tstamp.manmisc.in b/pcap-tstamp.manmisc.in
new file mode 100644 (file)
index 0000000..2cd32c6
--- /dev/null
@@ -0,0 +1,132 @@
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-TSTAMP @MAN_MISC_INFO@ "22 August 2010"
+.SH NAME
+pcap-tstamp \- packet time stamps in libpcap
+.SH DESCRIPTION
+When capturing traffic, each packet is given a time stamp representing,
+for incoming packets, the arrival time of the packet and, for outgoing
+packets, the transmission time of the packet.  This time is an
+approximation of the arrival or transmission time.  If it is supplied by
+the operating system running on the host on which the capture is being
+done, there are several reasons why it might not precisely represent the
+arrival or transmission time:
+.IP
+if the time stamp is applied to the packet when the networking stack
+receives the packet, the networking stack might not see the packet until
+an interrupt is delivered for the packet or a timer event causes the
+networking device driver to poll for packets, and the time stamp might
+not be applied until the packet has had some processing done by other
+code in the networking stack, so there might be a significant delay
+between the time when the last bit of the packet is received by the
+capture device and when the networking stack time-stamps the packet;
+.IP
+the timer used to generate the time stamps might have low resolution,
+for example, it might be a timer updated once per host operating system
+timer tick, with the host operating system timer ticking once every few
+milliseconds;
+.IP
+a high-resolution timer might use a counter that runs at a rate
+dependent on the processor clock speed, and that clock speed might be
+adjusted upwards or downwards over time and the timer might not be able
+to compensate for all those adjustments;
+.IP
+the host operating system's clock might be adjusted over time to match a
+time standard to which the host is being synchronized, which might be
+done by temporarily slowing down or speeding up the clock or by making a
+single adjustment;
+.IP
+different CPU cores on a multi-core or multi-processor system might be
+running at different speeds, or might not have time counters all
+synchronized, so packets time-stamped by different cores might not have
+consistent time stamps.
+.LP
+In addition, packets time-stamped by different cores might be
+time-stamped in one order and added to the queue of packets for libpcap
+to read in another order, so time stamps might not be monotonically
+increasing.
+.LP
+Some capture devices on some platforms can provide time stamps for
+packets; those time stamps are usually high-resolution time stamps, and
+are usually applied to the packet when the first or last bit of the
+packet arrives, and are thus more accurate than time stamps provided by
+the host operating system.  Those time stamps might not, however, be
+synchronized with the host operating system's clock, so that, for
+example, the time stamp of a packet might not correspond to the time
+stamp of an event on the host triggered by the arrival of that packet.
+.LP
+Depending on the capture device and the software on the host, libpcap
+might allow different types of time stamp to be used.  The
+.BR pcap_list_tstamp_types (3PCAP)
+routine provides, for a packet capture handle created by
+.BR pcap_create (3PCAP)
+but not yet activated by
+.BR pcap_activate (3PCAP),
+a list of time stamp types supported by the capture device for that
+handle.
+The list might be empty, in which case no choice of time stamp type is
+offered for that capture device.  If the list is not empty, the
+.BR pcap_set_tstamp_type (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and before a
+.B pcap_activate()
+call to specify the type of time stamp to be used on the device.
+The time stamp types are listed here; the first value is the #define to
+use in code, the second value is the value returned by
+.B pcap_tstamp_type_val_to_name()
+and accepted by
+.BR pcap_tstamp_name_to_val() .
+.RS 5
+.TP 5
+.BR PCAP_TSTAMP_HOST " - " host
+Time stamp provided by the host on which the capture is being done.  The
+precision of this time stamp is unspecified; it might or might not be
+synchronized with the host operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_LOWPREC " - " host_lowprec
+Time stamp provided by the host on which the capture is being done. 
+This is a low-precision time stamp, synchronized with the host operating
+system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_HIPREC " - " host_hiprec
+Time stamp provided by the host on which the capture is being done. 
+This is a high-precision time stamp; it might or might not be
+synchronized with the host operating system's clock.  It might be more
+expensive to fetch than
+.BR PCAP_TSTAMP_HOST_LOWPREC .
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER " - " adapter
+Time stamp provided by the network adapter on which the capture is being
+done.  This is a high-precision time stamp, synchronized with the host
+operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER_UNSYNCED " - " adapter_unsynced
+Time stamp provided by the network adapter on which the capture is being
+done.  This is a high-precision time stamp; it is not synchronized with
+the host operating system's clock.
+.RE
+.SH SEE ALSO
+pcap_set_tstamp_type(3PCAP),
+pcap_list_tstamp_types(3PCAP),
+pcap_tstamp_type_val_to_name(3PCAP),
+pcap_tstamp_name_to_val(3PCAP)
diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c
new file mode 100644 (file)
index 0000000..f1b430c
--- /dev/null
@@ -0,0 +1,883 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ * Modifications: Kris Katterjohn <katterjohn@gmail.com>
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.33 2008-12-23 21:38:50 guy Exp $ (LBL)";
+#endif
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-usb-linux.h"
+#include "pcap/usb.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <byteswap.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#ifdef HAVE_LINUX_USBDEVICE_FS_H
+/*
+ * We might need <linux/compiler.h> to define __user for
+ * <linux/usbdevice_fs.h>.
+ */
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif /* HAVE_LINUX_COMPILER_H */
+#include <linux/usbdevice_fs.h>
+#endif /* HAVE_LINUX_USBDEVICE_FS_H */
+
+#define USB_IFACE "usbmon"
+#define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon"
+#define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon"
+#define SYS_USB_BUS_DIR "/sys/bus/usb/devices"
+#define PROC_USB_BUS_DIR "/proc/bus/usb"
+#define USB_LINE_LEN 4096
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htols(s) s
+#define htoll(l) l
+#define htol64(ll) ll
+#else
+#define htols(s) bswap_16(s)
+#define htoll(l) bswap_32(l)
+#define htol64(ll) bswap_64(ll)
+#endif
+
+struct mon_bin_stats {
+       u_int32_t queued;
+       u_int32_t dropped;
+};
+
+struct mon_bin_get {
+       pcap_usb_header *hdr;
+       void *data;
+       size_t data_len;   /* Length of data (can be zero) */
+};
+
+struct mon_bin_mfetch {
+       int32_t *offvec;   /* Vector of events fetched */
+       int32_t nfetch;    /* Number of events to fetch (out: fetched) */
+       int32_t nflush;    /* Number of events to flush */
+};
+
+#define MON_IOC_MAGIC 0x92
+
+#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
+#define MON_IOCX_URB  _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
+#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
+#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
+#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
+#define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
+#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
+#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+
+#define MON_BIN_SETUP  0x1 /* setup hdr is present*/
+#define MON_BIN_SETUP_ZERO     0x2 /* setup buffer is not available */
+#define MON_BIN_DATA_ZERO      0x4 /* data buffer is not available */
+#define MON_BIN_ERROR  0x8
+
+/* forward declaration */
+static int usb_activate(pcap_t *);
+static int usb_stats_linux(pcap_t *, struct pcap_stat *);
+static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
+static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
+static int usb_inject_linux(pcap_t *, const void *, size_t);
+static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
+static void usb_cleanup_linux_mmap(pcap_t *);
+
+/* facility to add an USB device to the device list*/
+static int 
+usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
+{
+       char dev_name[10];
+       char dev_descr[30]; 
+       snprintf(dev_name, 10, USB_IFACE"%d", n);
+       snprintf(dev_descr, 30, "USB bus number %d", n);
+
+       if (pcap_add_if(alldevsp, dev_name, 0, 
+           dev_descr, err_str) < 0)
+               return -1;
+       return 0; 
+}
+
+int 
+usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+       struct dirent* data;
+       int ret = 0;
+       DIR* dir;
+       int n;
+       char* name;
+       size_t len;
+
+       /* try scanning sysfs usb bus directory */
+       dir = opendir(SYS_USB_BUS_DIR);
+       if (dir != NULL) {
+               while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                       name = data->d_name;
+
+                       if (strncmp(name, "usb", 3) != 0)
+                               continue;
+
+                       if (sscanf(&name[3], "%d", &n) == 0) 
+                               continue;
+
+                       ret = usb_dev_add(alldevsp, n, err_str);
+               }
+
+               closedir(dir);
+               return ret;
+       }
+
+       /* that didn't work; try scanning procfs usb bus directory */
+       dir = opendir(PROC_USB_BUS_DIR);
+       if (dir != NULL) {
+               while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                       name = data->d_name;
+                       len = strlen(name);
+
+                       /* if this file name does not end with a number it's not of our interest */
+                       if ((len < 1) || !isdigit(name[--len]))
+                               continue;
+                       while (isdigit(name[--len]));
+                       if (sscanf(&name[len+1], "%d", &n) != 1) 
+                               continue;
+
+                       ret = usb_dev_add(alldevsp, n, err_str);
+               }
+
+               closedir(dir);
+               return ret;
+       }
+
+       /* neither of them worked */
+       return 0;
+}
+
+static 
+int usb_mmap(pcap_t* handle)
+{
+       int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
+       if (len < 0) 
+               return 0;
+
+       handle->md.mmapbuflen = len;
+       handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ,
+           MAP_SHARED, handle->fd, 0);
+       return handle->md.mmapbuf != MAP_FAILED;
+}
+
+#define CTRL_TIMEOUT    (5*1000)        /* milliseconds */
+
+#define USB_DIR_IN             0x80
+#define USB_TYPE_STANDARD      0x00
+#define USB_RECIP_DEVICE       0x00
+
+#define USB_REQ_GET_DESCRIPTOR 6
+
+#define USB_DT_DEVICE          1
+
+/* probe the descriptors of the devices attached to the bus */
+/* the descriptors will end up in the captured packet stream */
+/* and be decoded by external apps like wireshark */
+/* without these identifying probes packet data can't be fully decoded */
+static void
+probe_devices(int bus)
+{
+       struct usbdevfs_ctrltransfer ctrl;
+       struct dirent* data;
+       int ret = 0;
+       char buf[40];
+       DIR* dir;
+
+       /* scan usb bus directories for device nodes */
+       snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
+       dir = opendir(buf);
+       if (!dir)
+               return;
+
+       while ((ret >= 0) && ((data = readdir(dir)) != 0)) {
+               int fd;
+               char* name = data->d_name;
+
+               if (name[0] == '.')
+                       continue;
+
+               snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
+               
+               fd = open(buf, O_RDWR);
+               if (fd == -1)
+                       continue;
+
+               /*
+                * Sigh.  Different kernels have different member names
+                * for this structure.
+                */
+#ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+               ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+               ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+               ctrl.wValue = USB_DT_DEVICE << 8;
+               ctrl.wIndex = 0;
+               ctrl.wLength = sizeof(buf);
+#else
+               ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+               ctrl.request = USB_REQ_GET_DESCRIPTOR;
+               ctrl.value = USB_DT_DEVICE << 8;
+               ctrl.index = 0;
+               ctrl.length = sizeof(buf);
+#endif
+               ctrl.data = buf;
+               ctrl.timeout = CTRL_TIMEOUT;
+
+               ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+
+               close(fd);
+       }
+       closedir(dir);
+}
+
+pcap_t *
+usb_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(device, ebuf);
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = usb_activate;
+       return (p);
+}
+
+static int
+usb_activate(pcap_t* handle)
+{
+       char            full_path[USB_LINE_LEN];
+
+       /* Initialize some components of the pcap structure. */
+       handle->bufsize = handle->snapshot;
+       handle->offset = 0;
+       handle->linktype = DLT_USB_LINUX;
+
+       handle->inject_op = usb_inject_linux;
+       handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+       handle->setdirection_op = usb_setdirection_linux;
+       handle->set_datalink_op = NULL; /* can't change data link type */
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+
+       /*get usb bus index from device name */
+       if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't get USB bus index from %s", handle->opt.source);
+               return PCAP_ERROR;
+       }
+
+       /*now select the read method: try to open binary interface */
+       snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);  
+       handle->fd = open(full_path, O_RDONLY, 0);
+       if (handle->fd >= 0)
+       {
+               if (handle->opt.rfmon) {
+                       /*
+                        * Monitor mode doesn't apply to USB devices.
+                        */
+                       close(handle->fd);
+                       return PCAP_ERROR_RFMON_NOTSUP;
+               }
+
+               /* binary api is available, try to use fast mmap access */
+               if (usb_mmap(handle)) {
+                       handle->linktype = DLT_USB_LINUX_MMAPPED;
+                       handle->stats_op = usb_stats_linux_bin;
+                       handle->read_op = usb_read_linux_mmap;
+                       handle->cleanup_op = usb_cleanup_linux_mmap;
+                       probe_devices(handle->md.ifindex);
+
+                       /*
+                        * "handle->fd" is a real file, so "select()" and
+                        * "poll()" work on it.
+                        */
+                       handle->selectable_fd = handle->fd;
+                       return 0;
+               }
+
+               /* can't mmap, use plain binary interface access */
+               handle->stats_op = usb_stats_linux_bin;
+               handle->read_op = usb_read_linux_bin;
+               probe_devices(handle->md.ifindex);
+       }
+       else {
+               /*Binary interface not available, try open text interface */
+               snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex);  
+               handle->fd = open(full_path, O_RDONLY, 0);
+               if (handle->fd < 0)
+               {
+                       if (errno == ENOENT)
+                       {
+                               /*
+                                * Not found at the new location; try
+                                * the old location.
+                                */
+                               snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex);  
+                               handle->fd = open(full_path, O_RDONLY, 0);
+                       }
+                       if (handle->fd < 0) {
+                               /* no more fallback, give it up*/
+                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "Can't open USB bus file %s: %s", full_path, strerror(errno));
+                               return PCAP_ERROR;
+                       }
+               }
+
+               if (handle->opt.rfmon) {
+                       /*
+                        * Monitor mode doesn't apply to USB devices.
+                        */
+                       close(handle->fd);
+                       return PCAP_ERROR_RFMON_NOTSUP;
+               }
+
+               handle->stats_op = usb_stats_linux;
+               handle->read_op = usb_read_linux;
+       }
+
+       /*
+        * "handle->fd" is a real file, so "select()" and "poll()"
+        * work on it.
+        */
+       handle->selectable_fd = handle->fd;
+
+       /* for plain binary access and text access we need to allocate the read
+        * buffer */
+       handle->buffer = malloc(handle->bufsize);
+       if (!handle->buffer) {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                        "malloc: %s", pcap_strerror(errno));
+               close(handle->fd);
+               return PCAP_ERROR;
+       }
+       return 0;
+}
+
+static inline int 
+ascii_to_int(char c)
+{
+       return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 
+ * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string 
+ * format description
+ */
+static int
+usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       /* see:
+       * /usr/src/linux/Documentation/usb/usbmon.txt 
+       * for message format
+       */
+       unsigned timestamp;
+       int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
+       char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
+       char *string = line;
+       u_char * rawdata = handle->buffer;
+       struct pcap_pkthdr pkth;
+       pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
+       u_char urb_transfer=0;
+       int incoming=0;
+
+       /* ignore interrupt system call errors */
+       do {
+               ret = read(handle->fd, line, USB_LINE_LEN - 1);
+               if (handle->break_loop)
+               {
+                       handle->break_loop = 0;
+                       return -2;
+               }
+       } while ((ret == -1) && (errno == EINTR));
+       if (ret < 0)
+       {
+               if (errno == EAGAIN)
+                       return 0;       /* no data there */
+
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't read from fd %d: %s", handle->fd, strerror(errno));
+               return -1;
+       }
+
+       /* read urb header; %n argument may increment return value, but it's 
+       * not mandatory, so does not count on it*/
+       string[ret] = 0;
+       ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype, 
+               &pipeid1, &pipeid2, &dev_addr, &ep_num, status, 
+               &cnt);
+       if (ret < 8)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
+                   string, ret);
+               return -1;
+       }
+       uhdr->id = tag;
+       uhdr->device_address = dev_addr;
+       uhdr->bus_id = handle->md.ifindex;
+       uhdr->status = 0;
+       string += cnt;
+
+       /* don't use usbmon provided timestamp, since it have low precision*/
+       if (gettimeofday(&pkth.ts, NULL) < 0) 
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't get timestamp for message '%s' %d:%s", 
+                       string, errno, strerror(errno));
+               return -1;
+       }
+       uhdr->ts_sec = pkth.ts.tv_sec;
+       uhdr->ts_usec = pkth.ts.tv_usec;
+
+       /* parse endpoint information */
+       if (pipeid1 == 'C')
+               urb_transfer = URB_CONTROL;
+       else if (pipeid1 == 'Z')
+               urb_transfer = URB_ISOCHRONOUS;
+       else if (pipeid1 == 'I')
+               urb_transfer = URB_INTERRUPT;
+       else if (pipeid1 == 'B')
+               urb_transfer = URB_BULK;
+       if (pipeid2 == 'i') {
+               ep_num |= URB_TRANSFER_IN;
+               incoming = 1;
+       }
+       if (etype == 'C')
+               incoming = !incoming;
+
+       /* direction check*/
+       if (incoming)
+       {
+               if (handle->direction == PCAP_D_OUT)
+                       return 0;
+       }
+       else
+               if (handle->direction == PCAP_D_IN)
+                       return 0;
+       uhdr->event_type = etype;
+       uhdr->transfer_type = urb_transfer;
+       uhdr->endpoint_number = ep_num;
+       pkth.caplen = sizeof(pcap_usb_header);
+       rawdata += sizeof(pcap_usb_header);
+
+       /* check if this is a setup packet */
+       ret = sscanf(status, "%d", &dummy);
+       if (ret != 1)
+       {
+               /* this a setup packet, setup data can be filled with underscore if
+               * usbmon has not been able to read them, so we must parse this fields as 
+               * strings */
+               pcap_usb_setup* shdr;
+               char str1[3], str2[3], str3[5], str4[5], str5[5];
+               ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4, 
+               str5, &cnt);
+               if (ret < 5)
+               {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
+                               string, ret);
+                       return -1;
+               }
+               string += cnt;
+
+               /* try to convert to corresponding integer */
+               shdr = &uhdr->setup;
+               shdr->bmRequestType = strtoul(str1, 0, 16);
+               shdr->bRequest = strtoul(str2, 0, 16);
+               shdr->wValue = htols(strtoul(str3, 0, 16));
+               shdr->wIndex = htols(strtoul(str4, 0, 16));
+               shdr->wLength = htols(strtoul(str5, 0, 16));
+
+               uhdr->setup_flag = 0;
+       }
+       else 
+               uhdr->setup_flag = 1;
+
+       /* read urb data */
+       ret = sscanf(string, " %d%n", &urb_len, &cnt);
+       if (ret < 1)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                 "Can't parse urb length from '%s'", string);
+               return -1;
+       }
+       string += cnt;
+
+       /* urb tag is not present if urb length is 0, so we can stop here 
+        * text parsing */
+       pkth.len = urb_len+pkth.caplen;
+       uhdr->urb_len = urb_len;
+       uhdr->data_flag = 1;
+       data_len = 0;
+       if (uhdr->urb_len == 0)
+               goto got;
+
+       /* check for data presence; data is present if and only if urb tag is '=' */
+       if (sscanf(string, " %c", &urb_tag) != 1)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't parse urb tag from '%s'", string);
+               return -1;
+       }
+
+       if (urb_tag != '=') 
+               goto got;
+
+       /* skip urb tag and following space */
+       string += 3;
+
+       /* if we reach this point we got some urb data*/
+       uhdr->data_flag = 0;
+
+       /* read all urb data; if urb length is greater then the usbmon internal 
+        * buffer length used by the kernel to spool the URB, we get only
+        * a partial information.
+        * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
+        * length and default value is 130. */
+       while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
+       {
+               rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
+               rawdata++;
+               string+=2;
+               if (string[0] == ' ')
+                       string++;
+               pkth.caplen++;
+               data_len++;
+       }
+
+got:
+       uhdr->data_len = data_len;
+       if (pkth.caplen > handle->snapshot)
+               pkth.caplen = handle->snapshot;
+
+       if (handle->fcode.bf_insns == NULL ||
+           bpf_filter(handle->fcode.bf_insns, handle->buffer,
+             pkth.len, pkth.caplen)) {
+               handle->md.packets_read++;
+               callback(user, &pkth, handle->buffer);
+               return 1;
+       }
+       return 0;       /* didn't pass filter */
+}
+
+static int
+usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+               "USB devices");
+       return (-1);
+}
+
+static int 
+usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+       int dummy, ret, consumed, cnt;
+       char string[USB_LINE_LEN];
+       char token[USB_LINE_LEN];
+       char * ptr = string;
+       int fd;
+
+       snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex);
+       fd = open(string, O_RDONLY, 0);
+       if (fd < 0)
+       {
+               if (errno == ENOENT)
+               {
+                       /*
+                        * Not found at the new location; try the old
+                        * location.
+                        */
+                       snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex);
+                       fd = open(string, O_RDONLY, 0);
+               }
+               if (fd < 0) {
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "Can't open USB stats file %s: %s", 
+                               string, strerror(errno));
+                       return -1;
+               }
+       }
+
+       /* read stats line */
+       do {
+               ret = read(fd, string, USB_LINE_LEN-1);
+       } while ((ret == -1) && (errno == EINTR));
+       close(fd);
+
+       if (ret < 0)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't read stats from fd %d ", fd);
+               return -1;
+       }
+       string[ret] = 0;
+
+       /* extract info on dropped urbs */
+       for (consumed=0; consumed < ret; ) {
+               /* from the sscanf man page: 
+                * The C standard says: "Execution of a %n directive does 
+                * not increment the assignment count returned at the completion
+                * of  execution" but the Corrigendum seems to contradict this.
+                * Do not make any assumptions on the effect of %n conversions 
+                * on the return value and explicitly check for cnt assignmet*/
+               int ntok;
+
+               cnt = -1;
+               ntok = sscanf(ptr, "%s%n", token, &cnt);
+               if ((ntok < 1) || (cnt < 0))
+                       break;
+               consumed += cnt;
+               ptr += cnt;
+               if (strcmp(token, "nreaders") == 0)
+                       ret = sscanf(ptr, "%d", &stats->ps_drop);
+               else 
+                       ret = sscanf(ptr, "%d", &dummy);
+               if (ntok != 1)
+                       break;
+               consumed += cnt;
+               ptr += cnt;
+       }
+
+       stats->ps_recv = handle->md.packets_read;
+       stats->ps_ifdrop = 0;
+       return 0;
+}
+
+static int 
+usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+       p->direction = d;
+       return 0;
+}
+
+
+static int 
+usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
+{
+       int ret;
+       struct mon_bin_stats st;
+       ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
+       if (ret < 0)
+       {
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                       "Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
+               return -1;
+       }
+
+       stats->ps_recv = handle->md.packets_read + st.queued;
+       stats->ps_drop = st.dropped;
+       stats->ps_ifdrop = 0;
+       return 0;
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+static int
+usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       struct mon_bin_get info;
+       int ret;
+       struct pcap_pkthdr pkth;
+       int clen = handle->snapshot - sizeof(pcap_usb_header);
+
+       /* the usb header is going to be part of 'packet' data*/
+       info.hdr = (pcap_usb_header*) handle->buffer;
+       info.data = handle->buffer + sizeof(pcap_usb_header);
+       info.data_len = clen;
+
+       /* ignore interrupt system call errors */
+       do {
+               ret = ioctl(handle->fd, MON_IOCX_GET, &info);
+               if (handle->break_loop)
+               {
+                       handle->break_loop = 0;
+                       return -2;
+               }
+       } while ((ret == -1) && (errno == EINTR));
+       if (ret < 0)
+       {
+               if (errno == EAGAIN)
+                       return 0;       /* no data there */
+
+               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   "Can't read from fd %d: %s", handle->fd, strerror(errno));
+               return -1;
+       }
+
+       /* we can get less that than really captured from kernel, depending on
+        * snaplen, so adjust header accordingly */
+       if (info.hdr->data_len < clen)
+               clen = info.hdr->data_len;
+       info.hdr->data_len = clen;
+       pkth.caplen = clen + sizeof(pcap_usb_header);
+       pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
+       pkth.ts.tv_sec = info.hdr->ts_sec;
+       pkth.ts.tv_usec = info.hdr->ts_usec;
+
+       if (handle->fcode.bf_insns == NULL ||
+           bpf_filter(handle->fcode.bf_insns, handle->buffer,
+             pkth.len, pkth.caplen)) {
+               handle->md.packets_read++;
+               callback(user, &pkth, handle->buffer);
+               return 1;
+       }
+
+       return 0;       /* didn't pass filter */
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+#define VEC_SIZE 32
+static int
+usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       struct mon_bin_mfetch fetch;
+       int32_t vec[VEC_SIZE];
+       struct pcap_pkthdr pkth;
+       pcap_usb_header* hdr;
+       int nflush = 0;
+       int packets = 0;
+       int clen, max_clen;
+
+       max_clen = handle->snapshot - sizeof(pcap_usb_header);
+
+       for (;;) {
+               int i, ret;
+               int limit = max_packets - packets;
+               if (limit <= 0)
+                       limit = VEC_SIZE;
+               if (limit > VEC_SIZE)
+                       limit = VEC_SIZE;
+
+               /* try to fetch as many events as possible*/
+               fetch.offvec = vec;
+               fetch.nfetch = limit;
+               fetch.nflush = nflush;
+               /* ignore interrupt system call errors */
+               do {
+                       ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
+                       if (handle->break_loop)
+                       {
+                               handle->break_loop = 0;
+                               return -2;
+                       }
+               } while ((ret == -1) && (errno == EINTR));
+               if (ret < 0)
+               {
+                       if (errno == EAGAIN)
+                               return 0;       /* no data there */
+
+                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                           "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
+                       return -1;
+               }
+
+               /* keep track of processed events, we will flush them later */
+               nflush = fetch.nfetch;
+               for (i=0; i<fetch.nfetch; ++i) {
+                       /* discard filler */
+                       hdr = (pcap_usb_header*) &handle->md.mmapbuf[vec[i]];
+                       if (hdr->event_type == '@') 
+                               continue;
+
+                       /* we can get less that than really captured from kernel, depending on
+                       * snaplen, so adjust header accordingly */
+                       clen = max_clen;
+                       if (hdr->data_len < clen)
+                               clen = hdr->data_len;
+
+                       /* get packet info from header*/
+                       pkth.caplen = clen + sizeof(pcap_usb_header_mmapped);
+                       pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped);
+                       pkth.ts.tv_sec = hdr->ts_sec;
+                       pkth.ts.tv_usec = hdr->ts_usec;
+
+                       if (handle->fcode.bf_insns == NULL ||
+                           bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
+                             pkth.len, pkth.caplen)) {
+                               handle->md.packets_read++;
+                               callback(user, &pkth, (u_char*) hdr);
+                               packets++;
+                       }
+               }
+
+               /* with max_packets <= 0 we stop afer the first chunk*/
+               if ((max_packets <= 0) || (packets == max_packets))
+                       break;
+       }
+
+       /* flush pending events*/
+       ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
+       return packets;
+}
+
+static void
+usb_cleanup_linux_mmap(pcap_t* handle)
+{
+       /* if we have a memory-mapped buffer, unmap it */
+       if (handle->md.mmapbuf != NULL) {
+               munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
+               handle->md.mmapbuf = NULL;
+       }
+       pcap_cleanup_live_common(handle);
+}
diff --git a/pcap-usb-linux.h b/pcap-usb-linux.h
new file mode 100644 (file)
index 0000000..2d9638c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.h,v 1.5 2008-04-04 19:37:45 guy Exp $ (LBL)
+ */
+
+/*
+ * Prototypes for USB-related functions
+ */
+int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *usb_create(const char *device, char *ebuf);
diff --git a/pcap-win32.c b/pcap-win32.c
new file mode 100644 (file)
index 0000000..d8ed453
--- /dev/null
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies 
+ * nor the names of its contributors may be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.42 2008-05-21 22:15:25 gianluca Exp $ (LBL)";
+#endif
+
+#include <pcap-int.h>
+#include <Packet32.h>
+#ifdef __MINGW32__
+#ifdef __MINGW64__
+#include <ntddndis.h>
+#else  /*__MINGW64__*/
+#include <ddk/ntddndis.h>
+#include <ddk/ndis.h>
+#endif /*__MINGW64__*/
+#else /*__MINGW32__*/
+#include <ntddndis.h>
+#endif /*__MINGW32__*/
+#ifdef HAVE_DAG_API
+#include <dagnew.h>
+#include <dagapi.h>
+#endif /* HAVE_DAG_API */
+#ifdef __MINGW32__
+int* _errno();
+#define errno (*_errno())
+#endif /* __MINGW32__ */
+
+static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
+static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
+static int pcap_getnonblock_win32(pcap_t *, char *);
+static int pcap_setnonblock_win32(pcap_t *, int, char *);
+
+/*dimension of the buffer in the pcap_t structure*/
+#define        WIN32_DEFAULT_USER_BUFFER_SIZE 256000
+
+/*dimension of the buffer in the kernel driver NPF */
+#define        WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
+
+/* Equivalent to ntohs(), but a lot faster under Windows */
+#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
+
+/*
+ * Header that the WinPcap driver associates to the packets.
+ * Once was in bpf.h
+ */
+struct bpf_hdr {
+       struct timeval  bh_tstamp;      /* time stamp */
+       bpf_u_int32     bh_caplen;      /* length of captured portion */
+       bpf_u_int32     bh_datalen;     /* original length of packet */
+       u_short         bh_hdrlen;      /* length of bpf header (this struct
+                                          plus alignment padding) */
+};
+
+CRITICAL_SECTION g_PcapCompileCriticalSection;
+
+BOOL WINAPI DllMain(
+  HANDLE hinstDLL,
+  DWORD dwReason,
+  LPVOID lpvReserved
+)
+{
+       if (dwReason == DLL_PROCESS_ATTACH)
+       {
+               InitializeCriticalSection(&g_PcapCompileCriticalSection);
+       }
+
+       return TRUE;
+}
+
+/* Start winsock */
+int 
+wsockinit()
+{
+       WORD wVersionRequested;
+       WSADATA wsaData;
+       int err;
+       wVersionRequested = MAKEWORD( 1, 1); 
+       err = WSAStartup( wVersionRequested, &wsaData );
+       if ( err != 0 )
+       {
+               return -1;
+       }
+       return 0;
+}
+
+
+static int
+pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
+{
+
+       if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+pcap_setbuff_win32(pcap_t *p, int dim)
+{
+       if(PacketSetBuff(p->adapter,dim)==FALSE)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+               return -1;
+       }
+       return 0;
+}
+
+/* Set the driver working mode */
+static int
+pcap_setmode_win32(pcap_t *p, int mode)
+{
+       if(PacketSetMode(p->adapter,mode)==FALSE)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*set the minimum amount of data that will release a read call*/
+static int
+pcap_setmintocopy_win32(pcap_t *p, int size)
+{
+       if(PacketSetMinToCopy(p->adapter, size)==FALSE)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       int n = 0;
+       register u_char *bp, *ep;
+
+       cc = p->cc;
+       if (p->cc == 0) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that it
+                        * has, and return -2 to indicate that we were
+                        * told to break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return (-2);
+               }
+
+           /* capture the packets */
+               if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+                       return (-1);
+               }
+                       
+               cc = p->Packet->ulBytesReceived;
+
+               bp = p->Packet->Buffer;
+       } 
+       else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.
+        */
+#define bhp ((struct bpf_hdr *)bp)
+       ep = bp + cc;
+       while (1) {
+               register int caplen, hdrlen;
+
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else {
+                               p->bp = bp;
+                               p->cc = ep - bp;
+                               return (n);
+                       }
+               }
+               if (bp >= ep)
+                       break;
+
+               caplen = bhp->bh_caplen;
+               hdrlen = bhp->bh_hdrlen;
+
+               /*
+                * XXX A bpf_hdr matches a pcap_pkthdr.
+                */
+               (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+               bp += Packet_WORDALIGN(caplen + hdrlen);
+               if (++n >= cnt && cnt > 0) {
+                       p->bp = bp;
+                       p->cc = ep - bp;
+                       return (n);
+               }
+       }
+#undef bhp
+       p->cc = 0;
+       return (n);
+}
+
+#ifdef HAVE_DAG_API
+static int
+pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       u_char *dp = NULL;
+       int     packet_len = 0, caplen = 0;
+       struct pcap_pkthdr      pcap_header;
+       u_char *endofbuf;
+       int n = 0;
+       dag_record_t *header;
+       unsigned erf_record_len;
+       ULONGLONG ts;
+       int cc;
+       unsigned swt;
+       unsigned dfp = p->adapter->DagFastProcess;
+
+       cc = p->cc;
+       if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
+       {
+           /* Get new packets from the network */
+               if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+                       return (-1);
+               }
+
+               cc = p->Packet->ulBytesReceived;
+               if(cc == 0)
+                       /* The timeout has expired but we no packets arrived */
+                       return 0;
+               header = (dag_record_t*)p->adapter->DagBuffer;
+       } 
+       else
+               header = (dag_record_t*)p->bp;
+       
+       endofbuf = (char*)header + cc;
+       
+       /* 
+        * Cycle through the packets 
+        */
+       do
+       {
+               erf_record_len = SWAPS(header->rlen);
+               if((char*)header + erf_record_len > endofbuf)
+                       break;
+
+               /* Increase the number of captured packets */
+               p->md.stat.ps_recv++;
+               
+               /* Find the beginning of the packet */
+               dp = ((u_char *)header) + dag_record_size;
+
+               /* Determine actual packet len */
+               switch(header->type) 
+               {
+               case TYPE_ATM:
+                       packet_len = ATM_SNAPLEN;
+                       caplen = ATM_SNAPLEN;
+                       dp += 4;
+
+                       break;
+
+               case TYPE_ETH:
+                       swt = SWAPS(header->wlen);
+                       packet_len = swt - (p->md.dag_fcs_bits);
+                       caplen = erf_record_len - dag_record_size - 2;
+                       if (caplen > packet_len)
+                       {
+                               caplen = packet_len;
+                       }
+                       dp += 2;
+                       
+                       break;
+               
+               case TYPE_HDLC_POS:
+                       swt = SWAPS(header->wlen);
+                       packet_len = swt - (p->md.dag_fcs_bits);
+                       caplen = erf_record_len - dag_record_size;
+                       if (caplen > packet_len)
+                       {
+                               caplen = packet_len;
+                       }
+                       
+                       break;
+               }
+               
+               if(caplen > p->snapshot)
+                       caplen = p->snapshot;
+
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) 
+               {
+                       if (n == 0) 
+                       {
+                               p->break_loop = 0;
+                               return (-2);
+                       } 
+                       else 
+                       {
+                               p->bp = (char*)header;
+                               p->cc = endofbuf - (char*)header;
+                               return (n);
+                       }
+               }
+
+               if(!dfp)
+               {
+                       /* convert between timestamp formats */
+                       ts = header->ts;
+                       pcap_header.ts.tv_sec = (int)(ts >> 32);
+                       ts = (ts & 0xffffffffi64) * 1000000;
+                       ts += 0x80000000; /* rounding */
+                       pcap_header.ts.tv_usec = (int)(ts >> 32);
+                       if (pcap_header.ts.tv_usec >= 1000000) {
+                               pcap_header.ts.tv_usec -= 1000000;
+                               pcap_header.ts.tv_sec++;
+                       }
+               }
+               
+               /* No underlaying filtering system. We need to filter on our own */
+               if (p->fcode.bf_insns) 
+               {
+                       if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) 
+                       {
+                               /* Move to next packet */
+                               header = (dag_record_t*)((char*)header + erf_record_len);
+                               continue;
+                       }
+               }
+               
+               /* Fill the header for the user suppplied callback function */
+               pcap_header.caplen = caplen;
+               pcap_header.len = packet_len;
+               
+               /* Call the callback function */
+               (*callback)(user, &pcap_header, dp);
+               
+               /* Move to next packet */
+               header = (dag_record_t*)((char*)header + erf_record_len);
+
+               /* Stop if the number of packets requested by user has been reached*/
+               if (++n >= cnt && cnt > 0) 
+               {
+                       p->bp = (char*)header;
+                       p->cc = endofbuf - (char*)header;
+                       return (n);
+               }
+       }
+       while((u_char*)header < endofbuf);
+       
+  return 1;
+}
+#endif /* HAVE_DAG_API */
+
+/* Send a packet to the network */
+static int 
+pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
+       LPPACKET PacketToSend;
+
+       PacketToSend=PacketAllocatePacket();
+       
+       if (PacketToSend == NULL)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
+               return -1;
+       }
+       
+       PacketInitPacket(PacketToSend,(PVOID)buf,size);
+       if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+               PacketFreePacket(PacketToSend);
+               return -1;
+       }
+
+       PacketFreePacket(PacketToSend);
+
+       /*
+        * We assume it all got sent if "PacketSendPacket()" succeeded.
+        * "pcap_inject()" is expected to return the number of bytes
+        * sent.
+        */
+       return size;
+}
+
+static void
+pcap_cleanup_win32(pcap_t *p)
+{
+       if (p->adapter != NULL) {
+               PacketCloseAdapter(p->adapter);
+               p->adapter = NULL;
+       }
+       if (p->Packet) {
+               PacketFreePacket(p->Packet);
+               p->Packet = NULL;
+       }
+       pcap_cleanup_live_common(p);
+}
+
+static int
+pcap_activate_win32(pcap_t *p)
+{
+       NetType type;
+
+       if (p->opt.rfmon) {
+               /*
+                * No monitor mode on Windows.  It could be done on
+                * Vista with drivers that support the native 802.11
+                * mechanism and monitor mode.
+                */
+               return (PCAP_ERROR_RFMON_NOTSUP);
+       }
+
+       /* Init WinSock */
+       wsockinit();
+
+       p->adapter = PacketOpenAdapter(p->opt.source);
+       
+       if (p->adapter == NULL)
+       {
+               /* Adapter detected but we are not able to open it. Return failure. */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
+               return PCAP_ERROR;
+       }
+       
+       /*get network type*/
+       if(PacketGetNetType (p->adapter,&type) == FALSE)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
+               goto bad;
+       }
+       
+       /*Set the linktype*/
+       switch (type.LinkType) 
+       {
+       case NdisMediumWan:
+               p->linktype = DLT_EN10MB;
+               break;
+               
+       case NdisMedium802_3:
+               p->linktype = DLT_EN10MB;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               /*
+                * If that fails, just leave the list empty.
+                */
+               if (p->dlt_list != NULL) {
+                       p->dlt_list[0] = DLT_EN10MB;
+                       p->dlt_list[1] = DLT_DOCSIS;
+                       p->dlt_count = 2;
+               }
+               break;
+               
+       case NdisMediumFddi:
+               p->linktype = DLT_FDDI;
+               break;
+               
+       case NdisMedium802_5:                   
+               p->linktype = DLT_IEEE802;      
+               break;
+               
+       case NdisMediumArcnetRaw:
+               p->linktype = DLT_ARCNET;
+               break;
+               
+       case NdisMediumArcnet878_2:
+               p->linktype = DLT_ARCNET;
+               break;
+               
+       case NdisMediumAtm:
+               p->linktype = DLT_ATM_RFC1483;
+               break;
+               
+       case NdisMediumCHDLC:
+               p->linktype = DLT_CHDLC;
+               break;
+
+       case NdisMediumPPPSerial:
+               p->linktype = DLT_PPP_SERIAL;
+               break;
+
+       case NdisMediumNull:
+               p->linktype = DLT_NULL;
+               break;
+
+       case NdisMediumBare80211:
+               p->linktype = DLT_IEEE802_11;
+               break;
+
+       case NdisMediumRadio80211:
+               p->linktype = DLT_IEEE802_11_RADIO;
+               break;
+
+       case NdisMediumPpi:
+               p->linktype = DLT_PPI;
+               break;
+
+       default:
+               p->linktype = DLT_EN10MB;                       /*an unknown adapter is assumed to be ethernet*/
+               break;
+       }
+
+       /* Set promiscuous mode */
+       if (p->opt.promisc) 
+       {
+
+               if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
+               {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+                       goto bad;
+               }
+       }
+       else 
+       {
+               if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
+               {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+                       goto bad;
+               }
+       }
+
+       /* Set the buffer size */
+       p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
+
+       /* allocate Packet structure used during the capture */
+       if((p->Packet = PacketAllocatePacket())==NULL)
+       {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
+               goto bad;
+       }
+
+       if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
+       {
+       /* 
+        * Traditional Adapter 
+        */
+               /*
+                * If the buffer size wasn't explicitly set, default to
+                * WIN32_DEFAULT_USER_BUFFER_SIZE.
+                */
+               if (p->opt.buffer_size == 0)
+                       p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
+
+               if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
+               {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+                       goto bad;
+               }
+               
+               p->buffer = (u_char *)malloc(p->bufsize);
+               if (p->buffer == NULL) 
+               {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+                       goto bad;
+               }
+               
+               PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
+               
+               /* tell the driver to copy the buffer only if it contains at least 16K */
+               if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
+               {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
+                       goto bad;
+               }
+       }
+       else
+#ifdef HAVE_DAG_API
+       {
+       /* 
+        * Dag Card 
+        */
+               LONG    status;
+               HKEY    dagkey;
+               DWORD   lptype;
+               DWORD   lpcbdata;
+               int             postype = 0;
+               char    keyname[512];
+               
+               snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", 
+                       "SYSTEM\\CurrentControlSet\\Services\\DAG",
+                       strstr(_strlwr(p->opt.source), "dag"));
+               do
+               {
+                       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
+                       if(status != ERROR_SUCCESS)
+                               break;
+                       
+                       status = RegQueryValueEx(dagkey,
+                               "PosType",
+                               NULL,
+                               &lptype,
+                               (char*)&postype,
+                               &lpcbdata);
+                       
+                       if(status != ERROR_SUCCESS)
+                       {
+                               postype = 0;
+                       }
+                       
+                       RegCloseKey(dagkey);
+               }
+               while(FALSE);
+               
+               
+               p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
+               
+               /* Set the length of the FCS associated to any packet. This value 
+                * will be subtracted to the packet length */
+               p->md.dag_fcs_bits = p->adapter->DagFcsLen;
+       }
+#else
+       goto bad;
+#endif /* HAVE_DAG_API */
+       
+       PacketSetReadTimeout(p->adapter, p->md.timeout);
+       
+#ifdef HAVE_DAG_API
+       if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
+       {
+               /* install dag specific handlers for read and setfilter */
+               p->read_op = pcap_read_win32_dag;
+               p->setfilter_op = pcap_setfilter_win32_dag;
+       }
+       else
+       {
+#endif /* HAVE_DAG_API */
+               /* install traditional npf handlers for read and setfilter */
+               p->read_op = pcap_read_win32_npf;
+               p->setfilter_op = pcap_setfilter_win32_npf;
+#ifdef HAVE_DAG_API
+       }
+#endif /* HAVE_DAG_API */
+       p->setdirection_op = NULL;      /* Not implemented. */
+           /* XXX - can this be implemented on some versions of Windows? */
+       p->inject_op = pcap_inject_win32;
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_win32;
+       p->setnonblock_op = pcap_setnonblock_win32;
+       p->stats_op = pcap_stats_win32;
+       p->setbuff_op = pcap_setbuff_win32;
+       p->setmode_op = pcap_setmode_win32;
+       p->setmintocopy_op = pcap_setmintocopy_win32;
+       p->cleanup_op = pcap_cleanup_win32;
+
+       return (0);
+bad:
+       pcap_cleanup_win32(p);
+       return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+       pcap_t *p;
+
+       if (strlen(device) == 1)
+       {
+               /*
+                * It's probably a unicode string
+                * Convert to ascii and pass it to pcap_create_common
+                *
+                * This wonderful hack is needed because pcap_lookupdev still returns
+                * unicode strings, and it's used by windump when no device is specified
+                * in the command line
+                */
+               size_t length;
+               char* deviceAscii;
+
+               length = wcslen((wchar_t*)device);
+
+               deviceAscii = (char*)malloc(length + 1);
+
+               if (deviceAscii == NULL)
+               {
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
+                       return NULL;
+               }
+
+               snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
+               p = pcap_create_common(deviceAscii, ebuf);
+               free(deviceAscii);
+       }
+       else
+       {
+               p = pcap_create_common(device, ebuf);
+       }
+
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_win32;
+       return (p);
+}
+
+static int
+pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
+{
+       if(PacketSetBpf(p->adapter,fp)==FALSE){
+               /*
+                * Kernel filter not installed.
+                * XXX - fall back on userland filtering, as is done
+                * on other platforms?
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
+               return (-1);
+       }
+
+       /*
+        * Discard any previously-received packets, as they might have
+        * passed whatever filter was formerly in effect, but might
+        * not pass this filter (BIOCSETF discards packets buffered
+        * in the kernel, so you can lose packets in any case).
+        */
+       p->cc = 0;
+       return (0);
+}
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int 
+pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
+       
+       if(!fp) 
+       {
+               strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+               return -1;
+       }
+       
+       /* Install a user level filter */
+       if (install_bpf_program(p, fp) < 0) 
+       {
+               snprintf(p->errbuf, sizeof(p->errbuf),
+                       "setfilter, unable to install the filter: %s", pcap_strerror(errno));
+               return -1;
+       }
+       
+       p->md.use_bpf = 0;
+       
+       return (0);
+}
+
+static int
+pcap_getnonblock_win32(pcap_t *p, char *errbuf)
+{
+       /*
+        * XXX - if there were a PacketGetReadTimeout() call, we
+        * would use it, and return 1 if the timeout is -1
+        * and 0 otherwise.
+        */
+       return (p->nonblock);
+}
+
+static int
+pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
+{
+       int newtimeout;
+
+       if (nonblock) {
+               /*
+                * Set the read timeout to -1 for non-blocking mode.
+                */
+               newtimeout = -1;
+       } else {
+               /*
+                * Restore the timeout set when the device was opened.
+                * (Note that this may be -1, in which case we're not
+                * really leaving non-blocking mode.)
+                */
+               newtimeout = p->md.timeout;
+       }
+       if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "PacketSetReadTimeout: %s", pcap_win32strerror());
+               return (-1);
+       }
+       p->nonblock = (newtimeout == -1);
+       return (0);
+}
+
+/*platform-dependent routine to add devices other than NDIS interfaces*/
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+       return (0);
+}
diff --git a/pcap.3pcap.in b/pcap.3pcap.in
new file mode 100644 (file)
index 0000000..6f99cc5
--- /dev/null
@@ -0,0 +1,883 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3pcap.in,v 1.1 2008-10-21 07:33:01 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP 3PCAP "4 April 2008"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.SS Opening a capture handle for reading
+To open a handle for a live capture, given the name of the network or
+other interface on which the capture should be done, call
+.BR pcap_create (),
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate ().
+.PP
+To obtain a list of devices that can be opened for a live capture, call
+.BR pcap_findalldevs ();
+to free the list returned by
+.BR pcap_findalldevs (),
+call
+.BR pcap_freealldevs ().
+.BR pcap_lookupdev ()
+will return the first device on that list that is not a ``loopback``
+network interface.
+.PP
+To open a handle for a ``savefile'' from which to read packets, given the
+pathname of the ``savefile'', call
+.BR pcap_open_offline ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for reading, call
+.BR pcap_fopen_offline ().
+.PP
+In order to get a ``fake''
+.B pcap_t
+for use in routines that require a
+.B pcap_t
+as an argument, such as routines to open a ``savefile'' for writing and
+to compile a filter expression, call
+.BR pcap_open_dead ().
+.PP
+.BR pcap_create (),
+.BR pcap_open_offline (),
+.BR pcap_fopen_offline (),
+and
+.BR pcap_open_dead ()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+To close a handle, use
+.BR pcap_close ().
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet.  If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value.  If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen ().
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host.  This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc ().
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated.  It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter.  This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon (),
+and
+.BR pcap_can_set_rfmon ()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "read timeout"
+If, when capturing, packets are delivered as soon as they arrive, the
+application capturing the packets will be woken up for each packet as it
+arrives, and might have to make one or more calls to the operating
+system to fetch each packet.
+.IP
+If, instead, packets are not delivered as soon as they arrive, but are
+delivered after a short delay (called a "read timeout"), more than one
+packet can be accumulated before the packets are delivered, so that a
+single wakeup would be done for multiple packets, and each set of calls
+made to the operating system would supply multiple packets, rather than
+a single packet.  This reduces the per-packet CPU overhead if packets
+are arriving at a high rate, increasing the number of packets per second
+that can be captured.
+.IP
+The read timeout is required so that an application won't wait for the
+operating system's capture buffer to fill up before packets are
+delivered; if packets are arriving slowly, that wait could take an
+arbitrarily long period of time.
+.IP
+Not all platforms support a read timeout; on platforms that
+don't, the read timeout is ignored.  A zero value for the timeout,
+on platforms that support a read timeout,
+will cause a read to wait forever to allow enough packets to
+arrive, with no timeout.
+.IP
+.BR NOTE :
+the read timeout cannot be used to cause calls that read
+packets to return within a limited period of time, because, on some
+platforms, the read timeout isn't supported, and, on other platforms,
+the timer doesn't start until at least one packet arrives.  This means
+that the read timeout should
+.B NOT
+be used, for example, in an interactive application to allow the packet
+capture loop to ``poll'' for user input periodically, as there's no
+guarantee that a call reading packets will return after the timeout
+expires even if no packets have arrived.
+.IP
+The read timeout is set with
+.BR pcap_set_timeout ().
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive.  On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size ().
+.IP "timestamp type"
+On some platforms, the time stamp given to packets on live captures can
+come from different sources that can have different resolutions or that
+can have different relationships to the time values for the current time
+supplied by routines on the native operating system.  See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of time stamp types.
+.IP
+The time stamp type is set with
+.BR pcap_set_tstamp_type ().
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode.  Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device.  A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (1M)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you  must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes Mac OS X):
+You must have read access to
+.I /dev/bpf*
+on systems that don't have a cloning BPF device, or to
+.I /dev/bpf
+on systems that do.
+On BSDs with a devfs (this includes Mac OS X), this might involve more
+than just having somebody with super-user access setting the ownership
+or permissions on the BPF devices - it might involve configuring devfs
+to set the ownership or permissions every time the system is booted,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+The packets read from the handle may include a ``pseudo-header''
+containing various forms of packet meta-data, and probably includes a
+link-layer header whose contents can differ for different network
+interfaces.  To determine the format of the packets supplied by the
+handle, call
+.BR pcap_datalink ();
+.I http://www.tcpdump.org/linktypes.html
+lists the values it returns and describes the packet formats that
+correspond to those values.
+.PP
+To obtain the
+.B "FILE\ *"
+corresponding to a
+.B pcap_t
+opened for a ``savefile'', call
+.BR pcap_file ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_create (3PCAP)
+get a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_activate (3PCAP)
+activate a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_findalldevs (3PCAP)
+get a list of devices that can be opened for a live capture
+.TP
+.BR pcap_freealldevs (3PCAP)
+free list of devices
+.TP
+.BR pcap_lookupdev (3PCAP)
+get first non-loopback device on that list
+.TP
+.BR pcap_open_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname
+.TP
+.BR pcap_fopen_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.B "FILE\ *"
+.TP
+.BR pcap_open_dead (3PCAP)
+create a ``fake''
+.B pcap_t
+.TP
+.BR pcap_close (3PCAP)
+close a
+.B pcap_t
+.TP
+.BR pcap_set_snaplen (3PCAP)
+set the snapshot length for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_snapshot (3PCAP)
+get the snapshot length for a
+.B pcap_t
+.TP
+.BR pcap_set_promisc (3PCAP)
+set promiscuous mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_rfmon (3PCAP)
+set monitor mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_can_set_rfmon (3PCAP)
+determine whether monitor mode can be set for a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_timeout (3PCAP)
+set read timeout for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_buffer_size (3PCAP)
+set buffer size for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_tstamp_type (3PCAP)
+set time stamp type for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_list_tstamp_types (3PCAP)
+get list of available time stamp types for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_free_tstamp_types (3PCAP)
+free list of available time stamp types
+.TP
+.BR pcap_tstamp_type_val_to_name (3PCAP)
+get name for a time stamp type
+.TP
+.BR pcap_tstamp_type_val_to_description (3PCAP)
+get description for a time stamp type
+.TP
+.BR pcap_tstamp_name_to_val (3PCAP)
+get time stamp type corresponding to a name
+.TP
+.BR pcap_datalink (3PCAP)
+get link-layer header type for a
+.B pcap_t
+.TP
+.BR pcap_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_t
+opened for a ``savefile''
+.TP
+.BR pcap_is_swapped (3PCAP)
+determine whether a ``savefile'' being read came from a machine with the
+opposite byte order
+.TP
+.BR pcap_major_version (3PCAP)
+.PD 0
+.TP
+.BR pcap_minor_version (3PCAP)
+get the major and minor version of the file format version for a
+``savefile''
+.PD
+.RE
+.SS Selecting a link-layer header type for a live capture
+Some devices may provide more than one link-layer header type.  To
+obtain a list of all link-layer header types provided by a device, call
+.BR pcap_list_datalinks ()
+on an activated
+.B pcap_t
+for the device.
+To free a list of link-layer header types, call
+.BR pcap_free_datalinks ().
+To set the link-layer header type for a device, call
+.BR pcap_set_datalink ().
+This should be done after the device has been activated but before any
+packets are read and before any filters are compiled or installed.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_list_datalinks (3PCAP)
+get a list of link-layer header types for a device
+.TP
+.BR pcap_free_datalinks (3PCAP)
+free list of link-layer header types
+.TP
+.BR pcap_set_datalink (3PCAP)
+set link-layer header type for a device
+.TP
+.BR pcap_datalink_val_to_name (3PCAP)
+get name for a link-layer header type
+.TP
+.BR pcap_datalink_val_to_description (3PCAP)
+get description for a link-layer header type
+.TP
+.BR pcap_datalink_name_to_val (3PCAP)
+get link-layer header type corresponding to a name
+.RE
+.SS Reading packets
+Packets are read with
+.BR pcap_dispatch ()
+or
+.BR pcap_loop (),
+which process one or more packets, calling a callback routine for each
+packet, or with
+.BR pcap_next ()
+or
+.BR pcap_next_ex (),
+which return the next packet.
+The callback for
+.BR pcap_dispatch ()
+and
+.BR pcap_loop ()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+.BR pcap_next_ex ()
+supplies that pointer through a pointer argument.
+.BR pcap_next ()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in.
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet.  This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.BR pcap_set_snaplen ()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks).  When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.BR pcap_next ()
+returns that pointer;
+.BR pcap_next_ex ()
+supplies that pointer through a pointer argument.
+.PP
+To force the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+to terminate, call
+.BR pcap_breakloop ().
+.PP
+By default, when reading packets from an interface opened for a live
+capture,
+.BR pcap_dispatch (),
+.BR pcap_next (),
+and
+.BR pcap_next_ex ()
+will, if no packets are currently available to be read, block waiting
+for packets to become available.  On some, but
+.I not
+all, platforms, if a read timeout was specified, the wait will terminate
+after the read timeout expires; applications should be prepared for
+this, as it happens on some platforms, but should not rely on it, as it
+does not happen on other platforms.
+.PP
+A handle can be put into ``non-blocking mode'', so that those routines
+will, rather than blocking, return an indication that no packets are
+available to read.  Call
+.BR pcap_setnonblock ()
+to put a handle into non-blocking mode or to take it out of non-blocking
+mode; call
+.BR pcap_getnonblock ()
+to determine whether a handle is in non-blocking mode.  Note that
+non-blocking mode does not work correctly in Mac OS X 10.6.
+.PP
+Non-blocking mode is often combined with routines such as
+.BR select (2)
+or
+.BR poll (2)
+or other routines a platform offers to wait for the availability of data
+on any of a set of descriptors.  To obtain, for a handle, a descriptor
+that can be used in those routines, call
+.BR pcap_get_selectable_fd ().
+Not all handles have such a descriptor available;
+.BR pcap_get_selectable_fd ()
+will return \-1 if no such descriptor exists.  In addition, for various
+reasons, one or more of those routines will not work properly with the
+descriptor; the documentation for
+.BR pcap_get_selectable_fd ()
+gives details.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dispatch (3PCAP)
+read a bufferful of packets from a
+.B pcap_t
+open for a live capture or the full set of packets from a
+.B pcap_t
+open for a ``savefile''
+.TP
+.BR pcap_loop (3PCAP)
+read packets from a
+.B pcap_t
+until an interrupt or error occurs
+.TP
+.BR pcap_next (3PCAP)
+read the next packet from a
+.B pcap_t
+without an indication whether an error occurred
+.TP
+.BR pcap_next_ex (3PCAP)
+read the next packet from a
+.B pcap_t
+with an error indication on an error
+.TP
+.BR pcap_breakloop (3PCAP)
+prematurely terminate the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+.TP
+.BR pcap_setnonblock (3PCAP)
+set or clear non-blocking mode on a
+.B pcap_t
+.TP
+.BR pcap_getnonblock (3PCAP)
+get the state of non-blocking mode for a
+.B pcap_t
+.TP
+.BR pcap_get_selectable_fd (3PCAP)
+attempt to get a descriptor for a
+.B pcap_t
+that can be used in calls such as
+.BR select (2)
+and
+.BR poll (2)
+.RE
+.SS Filters
+In order to cause only certain packets to be returned when reading
+packets, a filter can be set on a handle.  For a live capture, the
+filtering will be performed in kernel mode, if possible, to avoid
+copying ``uninteresting'' packets from the kernel to user mode.
+.PP
+A filter can be specified as a text string; the syntax and semantics of
+the string are as described by
+.BR pcap-filter (@MAN_MISC_INFO@).
+A filter string is compiled into a program in a pseudo-machine-language
+by
+.BR pcap_compile ()
+and the resulting program can be made a filter for a handle with
+.BR pcap_setfilter ().
+The result of
+.BR pcap_compile ()
+can be freed with a call to
+.BR pcap_freecode ().
+.BR pcap_compile ()
+may require a network mask for certain expressions in the filter string;
+.BR pcap_lookupnet ()
+can be used to find the network address and network mask for a given
+capture device.
+.PP
+A compiled filter can also be applied directly to a packet that has been
+read using
+.BR pcap_offline_filter ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_compile (3PCAP)
+compile filter expression to a pseudo-machine-language code program
+.TP
+.BR pcap_freecode (3PCAP)
+free a filter program
+.TP
+.BR pcap_setfilter (3PCAP)
+set filter for a
+.B pcap_t
+.TP
+.BR pcap_lookupnet (3PCAP)
+get network address and network mask for a capture device
+.TP
+.BR pcap_offline_filter (3PCAP)
+apply a filter program to a packet
+.RE
+.SS Incoming and outgoing packets
+By default, libpcap will attempt to capture both packets sent by the
+machine and packets received by the machine.  To limit it to capturing
+only packets received by the machine or, if possible, only packets sent
+by the machine, call
+.BR pcap_setdirection ().
+.TP
+.BR Routines
+.RS
+.TP
+.BR pcap_setdirection (3PCAP)
+specify whether to capture incoming packets, outgoing packets, or both
+.RE
+.SS Capture statistics
+To get statistics about packets received and dropped in a live capture,
+call
+.BR pcap_stats ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_stats (3PCAP)
+get capture statistics
+.RE
+.SS Opening a handle for writing captured packets
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ().
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for writing, call
+.BR pcap_dump_fopen ().
+They each return pointers to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''.  If it
+succeeds, it will have created the file if it doesn't exist and
+truncated the file if it does exist.
+To close a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_close ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump_open (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a pathname
+.TP
+.BR pcap_dump_fopen (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a
+.B "FILE\ *"
+.TP
+.BR pcap_dump_close (3PCAP)
+close a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_dumper_t
+opened for a ``savefile''
+.RE
+.SS Writing packets
+To write a packet to a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump ().
+Packets written with
+.BR pcap_dump ()
+may be buffered, rather than being immediately written to the
+``savefile''.  Closing the
+.B pcap_dumper_t
+will cause all buffered-but-not-yet-written packets to be written to the
+``savefile''.
+To force all packets written to the
+.BR pcap_dumper_t ,
+and not yet written to the ``savefile'' because they're buffered by the
+.BR pcap_dumper_t ,
+to be written to the ``savefile'', without closing the
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_flush ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump (3PCAP)
+write packet to a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_flush (3PCAP)
+flush buffered packets written to a
+.B pcap_dumper_t
+to the ``savefile''
+.TP
+.BR pcap_dump_ftell (3PCAP)
+get current file position for a
+.B pcap_dumper_t
+.RE
+.SS Injecting packets
+If you have the required privileges, you can inject packets onto a
+network with a
+.B pcap_t
+for a live capture, using
+.BR pcap_inject ()
+or
+.BR pcap_sendpacket ().
+(The two routines exist for compatibility with both OpenBSD and WinPcap;
+they perform the same function, but have different return values.)
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_inject (3PCAP)
+.PD 0
+.TP
+.BR pcap_sendpacket (3PCAP)
+transmit a packet
+.PD
+.RE
+.SS Reporting errors
+Some routines return error or warning status codes; to convert them to a
+string, use
+.BR pcap_statustostr ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_statustostr (3PCAP)
+get a string for an error or warning status code
+.RE
+.SS Getting library version information
+To get a string giving version information about libpcap, call
+.BR pcap_library_version ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_library_version (3PCAP)
+get library version string
+.RE
+.SH BACKWARDS COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.BR pcap_create ()
+and
+.BR pcap_activate ()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.BR pcap_open_live ()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.BR pcap_create ()
+and
+.BR pcap_activate (),
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8),
+usermod(1M)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
diff --git a/pcap.c b/pcap.c
new file mode 100644 (file)
index 0000000..cfdd83f
--- /dev/null
+++ b/pcap.c
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.128 2008-12-23 20:13:29 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_DAG_API
+#include <dagnew.h>
+#include <dagapi.h>
+#endif
+
+int 
+pcap_not_initialized(pcap_t *pcap)
+{
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+/*
+ * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
+ * a PCAP_ERROR value on an error.
+ */
+int
+pcap_can_set_rfmon(pcap_t *p)
+{
+       return (p->can_set_rfmon_op(p));
+}
+
+/*
+ * For systems where rfmon mode is never supported.
+ */
+static int
+pcap_cant_set_rfmon(pcap_t *p _U_)
+{
+       return (0);
+}
+
+/*
+ * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
+ * types; the return value is the number of supported time stamp types.
+ * The list should be freed by a call to pcap_free_tstamp_types() when
+ * you're done with it.
+ *
+ * A return value of 0 means "you don't get a choice of time stamp type",
+ * in which case *tstamp_typesp is set to null.
+ *
+ * PCAP_ERROR is returned on error.
+ */
+int
+pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
+{
+       if (p->tstamp_type_count == 0) {
+               /*
+                * We don't support multiple time stamp types.
+                */
+               *tstamp_typesp = NULL;
+       } else {
+               *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
+                   p->tstamp_type_count);
+               if (*tstamp_typesp == NULL) {
+                       (void)snprintf(p->errbuf, sizeof(p->errbuf),
+                           "malloc: %s", pcap_strerror(errno));
+                       return (PCAP_ERROR);
+               }
+               (void)memcpy(*tstamp_typesp, p->tstamp_type_list,
+                   sizeof(**tstamp_typesp) * p->tstamp_type_count);
+       }
+       return (p->tstamp_type_count);
+}
+
+/*
+ * In Windows, you might have a library built with one version of the
+ * C runtime library and an application built with another version of
+ * the C runtime library, which means that the library might use one
+ * version of malloc() and free() and the application might use another
+ * version of malloc() and free().  If so, that means something
+ * allocated by the library cannot be freed by the application, so we
+ * need to have a pcap_free_tstamp_types() routine to free up the list
+ * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
+ * around free().
+ */
+void
+pcap_free_tstamp_types(int *tstamp_type_list)
+{
+       free(tstamp_type_list);
+}
+
+/*
+ * Default one-shot callback; overridden for capture types where the
+ * packet data cannot be guaranteed to be available after the callback
+ * returns, so that a copy must be made.
+ */
+static void
+pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
+{
+       struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
+
+       *sp->hdr = *h;
+       *sp->pkt = pkt;
+}
+
+const u_char *
+pcap_next(pcap_t *p, struct pcap_pkthdr *h)
+{
+       struct oneshot_userdata s;
+       const u_char *pkt;
+
+       s.hdr = h;
+       s.pkt = &pkt;
+       s.pd = p;
+       if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
+               return (0);
+       return (pkt);
+}
+
+int 
+pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
+    const u_char **pkt_data)
+{
+       struct oneshot_userdata s;
+
+       s.hdr = &p->pcap_header;
+       s.pkt = pkt_data;
+       s.pd = p;
+
+       /* Saves a pointer to the packet headers */
+       *pkt_header= &p->pcap_header;
+
+       if (p->sf.rfile != NULL) {
+               int status;
+
+               /* We are on an offline capture */
+               status = pcap_offline_read(p, 1, p->oneshot_callback,
+                   (u_char *)&s);
+
+               /*
+                * Return codes for pcap_offline_read() are:
+                *   -  0: EOF
+                *   - -1: error
+                *   - >1: OK
+                * The first one ('0') conflicts with the return code of
+                * 0 from pcap_read() meaning "no packets arrived before
+                * the timeout expired", so we map it to -2 so you can
+                * distinguish between an EOF from a savefile and a
+                * "no packets arrived before the timeout expired, try
+                * again" from a live capture.
+                */
+               if (status == 0)
+                       return (-2);
+               else
+                       return (status);
+       }
+
+       /*
+        * Return codes for pcap_read() are:
+        *   -  0: timeout
+        *   - -1: error
+        *   - -2: loop was broken out of with pcap_breakloop()
+        *   - >1: OK
+        * The first one ('0') conflicts with the return code of 0 from
+        * pcap_offline_read() meaning "end of file".
+       */
+       return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
+}
+
+static void
+initialize_ops(pcap_t *p)
+{
+       /*
+        * Set operation pointers for operations that only work on
+        * an activated pcap_t to point to a routine that returns
+        * a "this isn't activated" error.
+        */
+       p->read_op = (read_op_t)pcap_not_initialized;
+       p->inject_op = (inject_op_t)pcap_not_initialized;
+       p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
+       p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
+       p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
+       p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
+       p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
+       p->stats_op = (stats_op_t)pcap_not_initialized;
+#ifdef WIN32
+       p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
+       p->setmode_op = (setmode_op_t)pcap_not_initialized;
+       p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
+#endif
+
+       /*
+        * Default cleanup operation - implementations can override
+        * this, but should call pcap_cleanup_live_common() after
+        * doing their own additional cleanup.
+        */
+       p->cleanup_op = pcap_cleanup_live_common;
+
+       /*
+        * In most cases, the standard one-short callback can
+        * be used for pcap_next()/pcap_next_ex().
+        */
+       p->oneshot_callback = pcap_oneshot;
+}
+
+pcap_t *
+pcap_create_common(const char *source, char *ebuf)
+{
+       pcap_t *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                   pcap_strerror(errno));
+               return (NULL);
+       }
+       memset(p, 0, sizeof(*p));
+#ifndef WIN32
+       p->fd = -1;     /* not opened yet */
+       p->selectable_fd = -1;
+       p->send_fd = -1;
+#endif 
+
+       p->opt.source = strdup(source);
+       if (p->opt.source == NULL) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+                   pcap_strerror(errno));
+               free(p);
+               return (NULL);
+       }
+
+       /*
+        * Default to "can't set rfmon mode"; if it's supported by
+        * a platform, the create routine that called us can set
+        * the op to its routine to check whether a particular
+        * device supports it.
+        */
+       p->can_set_rfmon_op = pcap_cant_set_rfmon;
+
+       initialize_ops(p);
+
+       /* put in some defaults*/
+       pcap_set_timeout(p, 0);
+       pcap_set_snaplen(p, 65535);     /* max packet size */
+       p->opt.promisc = 0;
+       p->opt.buffer_size = 0;
+       p->opt.tstamp_type = -1;        /* default to not setting time stamp type */
+       return (p);
+}
+
+int
+pcap_check_activated(pcap_t *p)
+{
+       if (p->activated) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+                       " operation on activated capture");
+               return (-1);
+       }
+       return (0);
+}
+
+int
+pcap_set_snaplen(pcap_t *p, int snaplen)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->snapshot = snaplen;
+       return (0);
+}
+
+int
+pcap_set_promisc(pcap_t *p, int promisc)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->opt.promisc = promisc;
+       return (0);
+}
+
+int
+pcap_set_rfmon(pcap_t *p, int rfmon)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->opt.rfmon = rfmon;
+       return (0);
+}
+
+int
+pcap_set_timeout(pcap_t *p, int timeout_ms)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->md.timeout = timeout_ms;
+       return (0);
+}
+
+int
+pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
+{
+       int i;
+
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+
+       /*
+        * If p->tstamp_type_count is 0, we don't support setting
+        * the time stamp type at all.
+        */
+       if (p->tstamp_type_count == 0)
+               return (PCAP_ERROR_CANTSET_TSTAMP_TYPE);
+
+       /*
+        * Check whether we claim to support this type of time stamp.
+        */
+       for (i = 0; i < p->tstamp_type_count; i++) {
+               if (p->tstamp_type_list[i] == tstamp_type) {
+                       /*
+                        * Yes.
+                        */
+                       p->opt.tstamp_type = tstamp_type;
+                       return (0);
+               }
+       }
+
+       /*
+        * No.  We support setting the time stamp type, but not to this
+        * particular value.
+        */
+       return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
+}
+
+int
+pcap_set_buffer_size(pcap_t *p, int buffer_size)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->opt.buffer_size = buffer_size;
+       return (0);
+}
+
+int
+pcap_activate(pcap_t *p)
+{
+       int status;
+
+       /*
+        * Catch attempts to re-activate an already-activated
+        * pcap_t; this should, for example, catch code that
+        * calls pcap_open_live() followed by pcap_activate(),
+        * as some code that showed up in a Stack Exchange
+        * question did.
+        */
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       status = p->activate_op(p);
+       if (status >= 0)
+               p->activated = 1;
+       else {
+               if (p->errbuf[0] == '\0') {
+                       /*
+                        * No error message supplied by the activate routine;
+                        * for the benefit of programs that don't specially
+                        * handle errors other than PCAP_ERROR, return the
+                        * error message corresponding to the status.
+                        */
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+                           pcap_statustostr(status));
+               }
+
+               /*
+                * Undo any operation pointer setting, etc. done by
+                * the activate operation.
+                */
+               initialize_ops(p);
+       }
+       return (status);
+}
+
+pcap_t *
+pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
+{
+       pcap_t *p;
+       int status;
+
+       p = pcap_create(source, errbuf);
+       if (p == NULL)
+               return (NULL);
+       status = pcap_set_snaplen(p, snaplen);
+       if (status < 0)
+               goto fail;
+       status = pcap_set_promisc(p, promisc);
+       if (status < 0)
+               goto fail;
+       status = pcap_set_timeout(p, to_ms);
+       if (status < 0)
+               goto fail;
+       /*
+        * Mark this as opened with pcap_open_live(), so that, for
+        * example, we show the full list of DLT_ values, rather
+        * than just the ones that are compatible with capturing
+        * when not in monitor mode.  That allows existing applications
+        * to work the way they used to work, but allows new applications
+        * that know about the new open API to, for example, find out the
+        * DLT_ values that they can select without changing whether
+        * the adapter is in monitor mode or not.
+        */
+       p->oldstyle = 1;
+       status = pcap_activate(p);
+       if (status < 0)
+               goto fail;
+       return (p);
+fail:
+       if (status == PCAP_ERROR)
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+                   p->errbuf);
+       else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+           status == PCAP_ERROR_PERM_DENIED ||
+           status == PCAP_ERROR_PROMISC_PERM_DENIED)
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source,
+                   pcap_statustostr(status), p->errbuf);
+       else
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+                   pcap_statustostr(status));
+       pcap_close(p);
+       return (NULL);
+}
+
+int
+pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       return (p->read_op(p, cnt, callback, user));
+}
+
+/*
+ * XXX - is this necessary?
+ */
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+
+       return (p->read_op(p, cnt, callback, user));
+}
+
+int
+pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int n;
+
+       for (;;) {
+               if (p->sf.rfile != NULL) {
+                       /*
+                        * 0 means EOF, so don't loop if we get 0.
+                        */
+                       n = pcap_offline_read(p, cnt, callback, user);
+               } else {
+                       /*
+                        * XXX keep reading until we get something
+                        * (or an error occurs)
+                        */
+                       do {
+                               n = p->read_op(p, cnt, callback, user);
+                       } while (n == 0);
+               }
+               if (n <= 0)
+                       return (n);
+               if (cnt > 0) {
+                       cnt -= n;
+                       if (cnt <= 0)
+                               return (0);
+               }
+       }
+}
+
+/*
+ * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
+ */
+void
+pcap_breakloop(pcap_t *p)
+{
+       p->break_loop = 1;
+}
+
+int
+pcap_datalink(pcap_t *p)
+{
+       return (p->linktype);
+}
+
+int
+pcap_datalink_ext(pcap_t *p)
+{
+       return (p->linktype_ext);
+}
+
+int
+pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
+{
+       if (p->dlt_count == 0) {
+               /*
+                * We couldn't fetch the list of DLTs, which means
+                * this platform doesn't support changing the
+                * DLT for an interface.  Return a list of DLTs
+                * containing only the DLT this device supports.
+                */
+               *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
+               if (*dlt_buffer == NULL) {
+                       (void)snprintf(p->errbuf, sizeof(p->errbuf),
+                           "malloc: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+               **dlt_buffer = p->linktype;
+               return (1);
+       } else {
+               *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
+               if (*dlt_buffer == NULL) {
+                       (void)snprintf(p->errbuf, sizeof(p->errbuf),
+                           "malloc: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+               (void)memcpy(*dlt_buffer, p->dlt_list,
+                   sizeof(**dlt_buffer) * p->dlt_count);
+               return (p->dlt_count);
+       }
+}
+
+/*
+ * In Windows, you might have a library built with one version of the
+ * C runtime library and an application built with another version of
+ * the C runtime library, which means that the library might use one
+ * version of malloc() and free() and the application might use another
+ * version of malloc() and free().  If so, that means something
+ * allocated by the library cannot be freed by the application, so we
+ * need to have a pcap_free_datalinks() routine to free up the list
+ * allocated by pcap_list_datalinks(), even though it's just a wrapper
+ * around free().
+ */
+void
+pcap_free_datalinks(int *dlt_list)
+{
+       free(dlt_list);
+}
+
+int
+pcap_set_datalink(pcap_t *p, int dlt)
+{
+       int i;
+       const char *dlt_name;
+
+       if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
+               /*
+                * We couldn't fetch the list of DLTs, or we don't
+                * have a "set datalink" operation, which means
+                * this platform doesn't support changing the
+                * DLT for an interface.  Check whether the new
+                * DLT is the one this interface supports.
+                */
+               if (p->linktype != dlt)
+                       goto unsupported;
+
+               /*
+                * It is, so there's nothing we need to do here.
+                */
+               return (0);
+       }
+       for (i = 0; i < p->dlt_count; i++)
+               if (p->dlt_list[i] == dlt)
+                       break;
+       if (i >= p->dlt_count)
+               goto unsupported;
+       if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
+           dlt == DLT_DOCSIS) {
+               /*
+                * This is presumably an Ethernet device, as the first
+                * link-layer type it offers is DLT_EN10MB, and the only
+                * other type it offers is DLT_DOCSIS.  That means that
+                * we can't tell the driver to supply DOCSIS link-layer
+                * headers - we're just pretending that's what we're
+                * getting, as, presumably, we're capturing on a dedicated
+                * link to a Cisco Cable Modem Termination System, and
+                * it's putting raw DOCSIS frames on the wire inside low-level
+                * Ethernet framing.
+                */
+               p->linktype = dlt;
+               return (0);
+       }
+       if (p->set_datalink_op(p, dlt) == -1)
+               return (-1);
+       p->linktype = dlt;
+       return (0);
+
+unsupported:
+       dlt_name = pcap_datalink_val_to_name(dlt);
+       if (dlt_name != NULL) {
+               (void) snprintf(p->errbuf, sizeof(p->errbuf),
+                   "%s is not one of the DLTs supported by this device",
+                   dlt_name);
+       } else {
+               (void) snprintf(p->errbuf, sizeof(p->errbuf),
+                   "DLT %d is not one of the DLTs supported by this device",
+                   dlt);
+       }
+       return (-1);
+}
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+       (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
+       (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
+       (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
+       (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
+       (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
+       (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
+       (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
+       (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
+       (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
+       (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
+       (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
+       (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
+       (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
+       (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
+       (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
+       (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
+       (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
+       (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
+       (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
+       (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
+       (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
+       (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
+       (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
+       (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
+       (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
+       (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
+       (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
+       (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
+       (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
+       (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
+       (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
+       (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
+       (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
+       (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
+       (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
+       (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
+       (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
+       (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
+       (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
+       (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
+       (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
+       (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
+       (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
+       (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
+       (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
+       (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
+       (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
+       (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
+       (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
+       (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
+       (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
+       (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
+       (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
+       (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
+       (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
+       (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
+       (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
+       (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
+       (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
+       (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
+       (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
+       (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
+       (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
+       (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
+};
+
+int
+pcap_strcasecmp(const char *s1, const char *s2)
+{
+       register const u_char   *cm = charmap,
+                               *us1 = (const u_char *)s1,
+                               *us2 = (const u_char *)s2;
+
+       while (cm[*us1] == cm[*us2++])
+               if (*us1++ == '\0')
+                       return(0);
+       return (cm[*us1] - cm[*--us2]);
+}
+
+struct dlt_choice {
+       const char *name;
+       const char *description;
+       int     dlt;
+};
+
+#define DLT_CHOICE(code, description) { #code, description, code }
+#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
+
+static struct dlt_choice dlt_choices[] = {
+       DLT_CHOICE(DLT_NULL, "BSD loopback"),
+       DLT_CHOICE(DLT_EN10MB, "Ethernet"),
+       DLT_CHOICE(DLT_IEEE802, "Token ring"),
+       DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
+       DLT_CHOICE(DLT_SLIP, "SLIP"),
+       DLT_CHOICE(DLT_PPP, "PPP"),
+       DLT_CHOICE(DLT_FDDI, "FDDI"),
+       DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
+       DLT_CHOICE(DLT_RAW, "Raw IP"),
+       DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
+       DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
+       DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
+       DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
+       DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
+        DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
+       DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
+       DLT_CHOICE(DLT_IEEE802_11, "802.11"),
+       DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
+       DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
+       DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
+       DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
+       DLT_CHOICE(DLT_LTALK, "Localtalk"),
+       DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
+       DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
+       DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
+       DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
+       DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
+       DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
+       DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
+        DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+       DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+        DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
+        DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
+       DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+        DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
+        DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
+        DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
+       DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+       DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+       DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
+       DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
+       DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
+       DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
+       DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
+       DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
+        DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
+       DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
+       DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
+       DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
+       DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
+       DLT_CHOICE(DLT_GPF_T, "GPF-T"),
+       DLT_CHOICE(DLT_GPF_F, "GPF-F"),
+       DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
+       DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"),
+       DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
+       DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
+       DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
+       DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
+       DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
+       DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
+       DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
+       DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
+       DLT_CHOICE(DLT_A429, "Arinc 429"),
+       DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
+       DLT_CHOICE(DLT_USB, "USB"),
+       DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
+       DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
+       DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
+       DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
+       DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
+       DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
+       DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
+       DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
+       DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"),
+       DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
+       DLT_CHOICE(DLT_ERF, "Endace ERF header"),
+       DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
+       DLT_CHOICE(DLT_IPMB, "IPMB"),
+       DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
+       DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
+       DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
+       DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
+       DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
+       DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"),
+       DLT_CHOICE(DLT_DECT, "DECT"),
+       DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"),
+       DLT_CHOICE(DLT_WIHART, "Wireless HART"),
+       DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"),
+       DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
+       DLT_CHOICE(DLT_IPNET, "Solaris ipnet"),
+       DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
+       DLT_CHOICE(DLT_IPV4, "Raw IPv4"),
+       DLT_CHOICE(DLT_IPV6, "Raw IPv6"),
+       DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
+       DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"),
+       DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"),
+       DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
+       DLT_CHOICE(DLT_DVB_CI, "DVB-CI"),
+       DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
+       DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"),
+       DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
+       DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
+       DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
+       DLT_CHOICE_SENTINEL
+};
+
+int
+pcap_datalink_name_to_val(const char *name)
+{
+       int i;
+
+       for (i = 0; dlt_choices[i].name != NULL; i++) {
+               if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
+                   name) == 0)
+                       return (dlt_choices[i].dlt);
+       }
+       return (-1);
+}
+
+const char *
+pcap_datalink_val_to_name(int dlt)
+{
+       int i;
+
+       for (i = 0; dlt_choices[i].name != NULL; i++) {
+               if (dlt_choices[i].dlt == dlt)
+                       return (dlt_choices[i].name + sizeof("DLT_") - 1);
+       }
+       return (NULL);
+}
+
+const char *
+pcap_datalink_val_to_description(int dlt)
+{
+       int i;
+
+       for (i = 0; dlt_choices[i].name != NULL; i++) {
+               if (dlt_choices[i].dlt == dlt)
+                       return (dlt_choices[i].description);
+       }
+       return (NULL);
+}
+
+struct tstamp_type_choice {
+       const char *name;
+       const char *description;
+       int     type;
+};
+
+static struct tstamp_type_choice tstamp_type_choices[] = {
+       { "host", "Host", PCAP_TSTAMP_HOST },
+       { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
+       { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
+       { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
+       { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
+       { NULL, NULL, 0 }
+};
+
+int
+pcap_tstamp_type_name_to_val(const char *name)
+{
+       int i;
+
+       for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+               if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0)
+                       return (tstamp_type_choices[i].type);
+       }
+       return (PCAP_ERROR);
+}
+
+const char *
+pcap_tstamp_type_val_to_name(int tstamp_type)
+{
+       int i;
+
+       for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+               if (tstamp_type_choices[i].type == tstamp_type)
+                       return (tstamp_type_choices[i].name);
+       }
+       return (NULL);
+}
+
+const char *
+pcap_tstamp_type_val_to_description(int tstamp_type)
+{
+       int i;
+
+       for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+               if (tstamp_type_choices[i].type == tstamp_type)
+                       return (tstamp_type_choices[i].description);
+       }
+       return (NULL);
+}
+
+int
+pcap_snapshot(pcap_t *p)
+{
+       return (p->snapshot);
+}
+
+int
+pcap_is_swapped(pcap_t *p)
+{
+       return (p->sf.swapped);
+}
+
+int
+pcap_major_version(pcap_t *p)
+{
+       return (p->sf.version_major);
+}
+
+int
+pcap_minor_version(pcap_t *p)
+{
+       return (p->sf.version_minor);
+}
+
+FILE *
+pcap_file(pcap_t *p)
+{
+       return (p->sf.rfile);
+}
+
+int
+pcap_fileno(pcap_t *p)
+{
+#ifndef WIN32
+       return (p->fd);
+#else
+       if (p->adapter != NULL)
+               return ((int)(DWORD)p->adapter->hFile);
+       else
+               return (-1);
+#endif
+}
+
+#if !defined(WIN32) && !defined(MSDOS)
+int
+pcap_get_selectable_fd(pcap_t *p)
+{
+       return (p->selectable_fd);
+}
+#endif
+
+void
+pcap_perror(pcap_t *p, char *prefix)
+{
+       fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
+}
+
+char *
+pcap_geterr(pcap_t *p)
+{
+       return (p->errbuf);
+}
+
+int
+pcap_getnonblock(pcap_t *p, char *errbuf)
+{
+       return (p->getnonblock_op(p, errbuf));
+}
+
+/*
+ * Get the current non-blocking mode setting, under the assumption that
+ * it's just the standard POSIX non-blocking flag.
+ *
+ * We don't look at "p->nonblock", in case somebody tweaked the FD
+ * directly.
+ */
+#if !defined(WIN32) && !defined(MSDOS)
+int
+pcap_getnonblock_fd(pcap_t *p, char *errbuf)
+{
+       int fdflags;
+
+       fdflags = fcntl(p->fd, F_GETFL, 0);
+       if (fdflags == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       if (fdflags & O_NONBLOCK)
+               return (1);
+       else
+               return (0);
+}
+#endif
+
+int
+pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+       return (p->setnonblock_op(p, nonblock, errbuf));
+}
+
+#if !defined(WIN32) && !defined(MSDOS)
+/*
+ * Set non-blocking mode, under the assumption that it's just the
+ * standard POSIX non-blocking flag.  (This can be called by the
+ * per-platform non-blocking-mode routine if that routine also
+ * needs to do some additional work.)
+ */
+int
+pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
+{
+       int fdflags;
+
+       fdflags = fcntl(p->fd, F_GETFL, 0);
+       if (fdflags == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       if (nonblock)
+               fdflags |= O_NONBLOCK;
+       else
+               fdflags &= ~O_NONBLOCK;
+       if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+                   pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+#endif
+
+#ifdef WIN32
+/*
+ * Generate a string for the last Win32-specific error (i.e. an error generated when 
+ * calling a Win32 API).
+ * For errors occurred during standard C calls, we still use pcap_strerror()
+ */
+char *
+pcap_win32strerror(void)
+{
+       DWORD error;
+       static char errbuf[PCAP_ERRBUF_SIZE+1];
+       int errlen;
+       char *p;
+
+       error = GetLastError();
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+           PCAP_ERRBUF_SIZE, NULL);
+
+       /*
+        * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
+        * message.  Get rid of it.
+        */
+       errlen = strlen(errbuf);
+       if (errlen >= 2) {
+               errbuf[errlen - 1] = '\0';
+               errbuf[errlen - 2] = '\0';
+       }
+       p = strchr(errbuf, '\0');
+       snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
+       return (errbuf);
+}
+#endif
+
+/*
+ * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
+ */
+const char *
+pcap_statustostr(int errnum)
+{
+       static char ebuf[15+10+1];
+
+       switch (errnum) {
+
+       case PCAP_WARNING:
+               return("Generic warning");
+
+       case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
+               return ("That type of time stamp is not supported by that device");
+
+       case PCAP_WARNING_PROMISC_NOTSUP:
+               return ("That device doesn't support promiscuous mode");
+
+       case PCAP_ERROR:
+               return("Generic error");
+
+       case PCAP_ERROR_BREAK:
+               return("Loop terminated by pcap_breakloop");
+
+       case PCAP_ERROR_NOT_ACTIVATED:
+               return("The pcap_t has not been activated");
+
+       case PCAP_ERROR_ACTIVATED:
+               return ("The setting can't be changed after the pcap_t is activated");
+
+       case PCAP_ERROR_NO_SUCH_DEVICE:
+               return ("No such device exists");
+
+       case PCAP_ERROR_RFMON_NOTSUP:
+               return ("That device doesn't support monitor mode");
+
+       case PCAP_ERROR_NOT_RFMON:
+               return ("That operation is supported only in monitor mode");
+
+       case PCAP_ERROR_PERM_DENIED:
+               return ("You don't have permission to capture on that device");
+
+       case PCAP_ERROR_IFACE_NOT_UP:
+               return ("That device is not up");
+
+       case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
+               return ("That device doesn't support setting the time stamp type");
+
+       case PCAP_ERROR_PROMISC_PERM_DENIED:
+               return ("You don't have permission to capture in promiscuous mode on that device");
+       }
+       (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+       return(ebuf);
+}
+
+/*
+ * Not all systems have strerror().
+ */
+const char *
+pcap_strerror(int errnum)
+{
+#ifdef HAVE_STRERROR
+       return (strerror(errnum));
+#else
+       extern int sys_nerr;
+       extern const char *const sys_errlist[];
+       static char ebuf[15+10+1];
+
+       if ((unsigned int)errnum < sys_nerr)
+               return ((char *)sys_errlist[errnum]);
+       (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+       return(ebuf);
+#endif
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       return (p->setfilter_op(p, fp));
+}
+
+/*
+ * Set direction flag, which controls whether we accept only incoming
+ * packets, only outgoing packets, or both.
+ * Note that, depending on the platform, some or all direction arguments
+ * might not be supported.
+ */
+int
+pcap_setdirection(pcap_t *p, pcap_direction_t d)
+{
+       if (p->setdirection_op == NULL) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "Setting direction is not implemented on this platform");
+               return (-1);
+       } else
+               return (p->setdirection_op(p, d));
+}
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       return (p->stats_op(p, ps));
+}
+
+static int
+pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Statistics aren't available from a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+#ifdef WIN32
+int
+pcap_setbuff(pcap_t *p, int dim)
+{
+       return (p->setbuff_op(p, dim));
+}
+
+static int
+pcap_setbuff_dead(pcap_t *p, int dim)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+int
+pcap_setmode(pcap_t *p, int mode)
+{
+       return (p->setmode_op(p, mode));
+}
+
+static int
+pcap_setmode_dead(pcap_t *p, int mode)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "impossible to set mode on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+int
+pcap_setmintocopy(pcap_t *p, int size)
+{
+       return (p->setmintocopy_op(p, size));
+}
+
+static int
+pcap_setmintocopy_dead(pcap_t *p, int size)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
+}
+#endif
+
+/*
+ * On some platforms, we need to clean up promiscuous or monitor mode
+ * when we close a device - and we want that to happen even if the
+ * application just exits without explicitl closing devices.
+ * On those platforms, we need to register a "close all the pcaps"
+ * routine to be called when we exit, and need to maintain a list of
+ * pcaps that need to be closed to clean up modes.
+ *
+ * XXX - not thread-safe.
+ */
+
+/*
+ * List of pcaps on which we've done something that needs to be
+ * cleaned up.
+ * If there are any such pcaps, we arrange to call "pcap_close_all()"
+ * when we exit, and have it close all of them.
+ */
+static struct pcap *pcaps_to_close;
+
+/*
+ * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
+ * be called on exit.
+ */
+static int did_atexit;
+
+static void
+pcap_close_all(void)
+{
+       struct pcap *handle;
+
+       while ((handle = pcaps_to_close) != NULL)
+               pcap_close(handle);
+}
+
+int
+pcap_do_addexit(pcap_t *p)
+{
+       /*
+        * If we haven't already done so, arrange to have
+        * "pcap_close_all()" called when we exit.
+        */
+       if (!did_atexit) {
+               if (atexit(pcap_close_all) == -1) {
+                       /*
+                        * "atexit()" failed; let our caller know.
+                        */
+                       strncpy(p->errbuf, "atexit failed",
+                           PCAP_ERRBUF_SIZE);
+                       return (0);
+               }
+               did_atexit = 1;
+       }
+       return (1);
+}
+
+void
+pcap_add_to_pcaps_to_close(pcap_t *p)
+{
+       p->md.next = pcaps_to_close;
+       pcaps_to_close = p;
+}
+
+void
+pcap_remove_from_pcaps_to_close(pcap_t *p)
+{
+       pcap_t *pc, *prevpc;
+
+       for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
+           prevpc = pc, pc = pc->md.next) {
+               if (pc == p) {
+                       /*
+                        * Found it.  Remove it from the list.
+                        */
+                       if (prevpc == NULL) {
+                               /*
+                                * It was at the head of the list.
+                                */
+                               pcaps_to_close = pc->md.next;
+                       } else {
+                               /*
+                                * It was in the middle of the list.
+                                */
+                               prevpc->md.next = pc->md.next;
+                       }
+                       break;
+               }
+       }
+}
+
+void
+pcap_cleanup_live_common(pcap_t *p)
+{
+       if (p->buffer != NULL) {
+               free(p->buffer);
+               p->buffer = NULL;
+       }
+       if (p->dlt_list != NULL) {
+               free(p->dlt_list);
+               p->dlt_list = NULL;
+               p->dlt_count = 0;
+       }
+       if (p->tstamp_type_list != NULL) {
+               free(p->tstamp_type_list);
+               p->tstamp_type_list = NULL;
+               p->tstamp_type_count = 0;
+       }
+       pcap_freecode(&p->fcode);
+#if !defined(WIN32) && !defined(MSDOS)
+       if (p->fd >= 0) {
+               close(p->fd);
+               p->fd = -1;
+       }
+       p->selectable_fd = -1;
+       p->send_fd = -1;
+#endif
+}
+
+static void
+pcap_cleanup_dead(pcap_t *p _U_)
+{
+       /* Nothing to do. */
+}
+
+pcap_t *
+pcap_open_dead(int linktype, int snaplen)
+{
+       pcap_t *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL)
+               return NULL;
+       memset (p, 0, sizeof(*p));
+       p->snapshot = snaplen;
+       p->linktype = linktype;
+       p->stats_op = pcap_stats_dead;
+#ifdef WIN32
+       p->setbuff_op = pcap_setbuff_dead;
+       p->setmode_op = pcap_setmode_dead;
+       p->setmintocopy_op = pcap_setmintocopy_dead;
+#endif
+       p->cleanup_op = pcap_cleanup_dead;
+       p->activated = 1;
+       return (p);
+}
+
+/*
+ * API compatible with WinPcap's "send a packet" routine - returns -1
+ * on error, 0 otherwise.
+ *
+ * XXX - what if we get a short write?
+ */
+int
+pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
+{
+       if (p->inject_op(p, buf, size) == -1)
+               return (-1);
+       return (0);
+}
+
+/*
+ * API compatible with OpenBSD's "send a packet" routine - returns -1 on
+ * error, number of bytes written otherwise.
+ */
+int
+pcap_inject(pcap_t *p, const void *buf, size_t size)
+{
+       return (p->inject_op(p, buf, size));
+}
+
+void
+pcap_close(pcap_t *p)
+{
+       if (p->opt.source != NULL)
+               free(p->opt.source);
+       p->cleanup_op(p);
+       free(p);
+}
+
+/*
+ * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
+ * data for the packet, check whether the packet passes the filter.
+ * Returns the return value of the filter program, which will be zero if
+ * the packet doesn't pass and non-zero if the packet does pass.
+ */
+int
+pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h,
+    const u_char *pkt)
+{
+       struct bpf_insn *fcode = fp->bf_insns;
+
+       if (fcode != NULL) 
+               return (bpf_filter(fcode, pkt, h->len, h->caplen));
+       else
+               return (0);
+}
+
+/*
+ * We make the version string static, and return a pointer to it, rather
+ * than exporting the version string directly.  On at least some UNIXes,
+ * if you import data from a shared library into an program, the data is
+ * bound into the program binary, so if the string in the version of the
+ * library with which the program was linked isn't the same as the
+ * string in the version of the library with which the program is being
+ * run, various undesirable things may happen (warnings, the string
+ * being the one from the version of the library with which the program
+ * was linked, or even weirder things, such as the string being the one
+ * from the library but being truncated).
+ */
+#ifdef HAVE_VERSION_H
+#include "version.h"
+#else
+static const char pcap_version_string[] = "libpcap version 1.x.y";
+#endif
+
+#ifdef WIN32
+/*
+ * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
+ * version numbers when building WinPcap.  (It'd be nice to do so for
+ * the packet.dll version number as well.)
+ */
+static const char wpcap_version_string[] = "4.0";
+static const char pcap_version_string_fmt[] =
+    "WinPcap version %s, based on %s";
+static const char pcap_version_string_packet_dll_fmt[] =
+    "WinPcap version %s (packet.dll version %s), based on %s";
+static char *full_pcap_version_string;
+
+const char *
+pcap_lib_version(void)
+{
+       char *packet_version_string;
+       size_t full_pcap_version_string_len;
+
+       if (full_pcap_version_string == NULL) {
+               /*
+                * Generate the version string.
+                */
+               packet_version_string = PacketGetVersion();
+               if (strcmp(wpcap_version_string, packet_version_string) == 0) {
+                       /*
+                        * WinPcap version string and packet.dll version
+                        * string are the same; just report the WinPcap
+                        * version.
+                        */
+                       full_pcap_version_string_len =
+                           (sizeof pcap_version_string_fmt - 4) +
+                           strlen(wpcap_version_string) +
+                           strlen(pcap_version_string);
+                       full_pcap_version_string =
+                           malloc(full_pcap_version_string_len);
+                       sprintf(full_pcap_version_string,
+                           pcap_version_string_fmt, wpcap_version_string,
+                           pcap_version_string);
+               } else {
+                       /*
+                        * WinPcap version string and packet.dll version
+                        * string are different; that shouldn't be the
+                        * case (the two libraries should come from the
+                        * same version of WinPcap), so we report both
+                        * versions.
+                        */
+                       full_pcap_version_string_len =
+                           (sizeof pcap_version_string_packet_dll_fmt - 6) +
+                           strlen(wpcap_version_string) +
+                           strlen(packet_version_string) +
+                           strlen(pcap_version_string);
+                       full_pcap_version_string = malloc(full_pcap_version_string_len);
+
+                       sprintf(full_pcap_version_string,
+                           pcap_version_string_packet_dll_fmt,
+                           wpcap_version_string, packet_version_string,
+                           pcap_version_string);
+               }
+       }
+       return (full_pcap_version_string);
+}
+
+#elif defined(MSDOS)
+
+static char *full_pcap_version_string;
+
+const char *
+pcap_lib_version (void)
+{
+       char *packet_version_string;
+       size_t full_pcap_version_string_len;
+       static char dospfx[] = "DOS-";
+
+       if (full_pcap_version_string == NULL) {
+               /*
+                * Generate the version string.
+                */
+               full_pcap_version_string_len =
+                   sizeof dospfx + strlen(pcap_version_string);
+               full_pcap_version_string =
+                   malloc(full_pcap_version_string_len);
+               strcpy(full_pcap_version_string, dospfx);
+               strcat(full_pcap_version_string, pcap_version_string);
+       }
+       return (full_pcap_version_string);
+}
+
+#else /* UN*X */
+
+const char *
+pcap_lib_version(void)
+{
+       return (pcap_version_string);
+}
+#endif
diff --git a/pcap.h b/pcap.h
new file mode 100644 (file)
index 0000000..490a4bf
--- /dev/null
+++ b/pcap.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006-10-04 18:09:22 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Many applications
+ * expect to be able to include <pcap.h>, and at least some of them
+ * go through contortions in their configure scripts to try to detect
+ * OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
+ * leaving behind a <pcap.h> file.
+ */
+#include <pcap/pcap.h>
diff --git a/pcap/bluetooth.h b/pcap/bluetooth.h
new file mode 100644 (file)
index 0000000..813bea3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * bluetooth data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007-09-22 02:10:17 guy Exp $
+ */
+#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
+#define _PCAP_BLUETOOTH_STRUCTS_H__
+
+/*
+ * Header prepended libpcap to each bluetooth h:4 frame.
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_h4_header {
+       u_int32_t direction; /* if first bit is set direction is incoming */
+} pcap_bluetooth_h4_header;
+
+
+#endif
diff --git a/pcap/bpf.h b/pcap/bpf.h
new file mode 100644 (file)
index 0000000..8bcde7f
--- /dev/null
@@ -0,0 +1,1289 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)bpf.h       7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.32 2008-12-23 20:13:29 guy Exp $ (LBL)
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * At least two programs found by Google Code Search explicitly includes
+ * <pcap/bpf.h> (even though <pcap.h>/<pcap/pcap.h> includes it for you),
+ * so moving that stuff to <pcap/pcap.h> would break the build for some
+ * programs.
+ */
+
+/*
+ * If we've already included <net/bpf.h>, don't re-define this stuff.
+ * We assume BSD-style multiple-include protection in <net/bpf.h>,
+ * which is true of all but the oldest versions of FreeBSD and NetBSD,
+ * or Tru64 UNIX-style multiple-include protection (or, at least,
+ * Tru64 UNIX 5.x-style; I don't have earlier versions available to check),
+ * or AIX-style multiple-include protection (or, at least, AIX 5.x-style;
+ * I don't have earlier versions available to check).
+ *
+ * We do not check for BPF_MAJOR_VERSION, as that's defined by
+ * <linux/filter.h>, which is directly or indirectly included in some
+ * programs that also include pcap.h, and <linux/filter.h> doesn't
+ * define stuff we need.
+ *
+ * This also provides our own multiple-include protection.
+ */
+#if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
+#define lib_pcap_bpf_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long          bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros.  BPF_WORDALIGN rounds up to the next 
+ * even multiple of BPF_ALIGNMENT.
+ *
+ * Tcpdump's print-pflog.c uses this, so we define it here.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+       u_int bf_len;
+       struct bpf_insn *bf_insns;
+};
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value.  Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ *     http://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL       0       /* BSD loopback encapsulation */
+#define DLT_EN10MB     1       /* Ethernet (10Mb) */
+#define DLT_EN3MB      2       /* Experimental Ethernet (3Mb) */
+#define DLT_AX25       3       /* Amateur Radio AX.25 */
+#define DLT_PRONET     4       /* Proteon ProNET Token Ring */
+#define DLT_CHAOS      5       /* Chaos */
+#define DLT_IEEE802    6       /* 802.5 Token Ring */
+#define DLT_ARCNET     7       /* ARCNET, with BSD-style header */
+#define DLT_SLIP       8       /* Serial Line IP */
+#define DLT_PPP                9       /* Point-to-point Protocol */
+#define DLT_FDDI       10      /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483        11      /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW                14      /* raw IP */
+#else
+#define DLT_RAW                12      /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't.  So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13      /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS  14      /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15      /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS  16      /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
+ *
+ * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
+ * as 117 so that pflog captures would use a link-layer header type
+ * value that didn't collide with any other values.  On all
+ * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
+ * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
+ *
+ * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
+ *
+ * Don't use 17 for anything else.
+ */
+
+/*
+ * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
+ * Mac OS X; don't use it for anything else.  (FreeBSD uses 121,
+ * which collides with DLT_HHDLC, even though it doesn't use 18
+ * for anything and doesn't appear to have ever used it for anything.)
+ *
+ * We define it as 18 on those platforms; it is, unfortunately, used
+ * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
+ * in general.  As the packet format for it, like that for
+ * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
+ * we don't support printing it in tcpdump except on OSes that
+ * have the relevant header files, so it's not that useful on
+ * other platforms.
+ */
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#define DLT_PFSYNC     18
+#endif
+
+#define DLT_ATM_CLIP   19      /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800.  I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE  32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50      /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER  51      /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies.  The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL  99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN       104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC     104     /* Cisco HDLC */
+#define DLT_CHDLC      DLT_C_HDLC
+
+#define DLT_IEEE802_11 105     /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't.  (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.)  We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY     107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP       12
+#else
+#define DLT_LOOP       108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC                13
+#else
+#define DLT_ENC                109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL  113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK      114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET     115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER   116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG      117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS  118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER       119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER     120
+
+/*
+ * Sigh.
+ *
+ * This was reserved for Siemens HiPath HDLC on 2002-01-25, as
+ * requested by Tomas Kukosa.
+ *
+ * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
+ * assigned 121 as DLT_PFSYNC.  Its libpcap does DLT_ <-> LINKTYPE_
+ * mapping, so it probably supports capturing on the pfsync device
+ * but not saving the captured data to a pcap file.
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * use 18 in pcap files as well.
+ *
+ * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their
+ * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry
+ * for DLT_PFSYNC, so it might not be able to write out dump files
+ * with 18 as the link-layer header type.  (Earlier versions might
+ * not have done mapping, in which case they'd work the same way
+ * OpenBSD does.)
+ *
+ * Mac OS X defines it as 18, but doesn't appear to use it as of
+ * Mac OS X 10.7.3.  Its libpcap does DLT_ <-> LINKTYPE_ mapping.
+ *
+ * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on
+ * all other platforms.  We'll define DLT_HHDLC as 121 on everything
+ * except for FreeBSD; anybody who wants to compile, on FreeBSD, code
+ * that uses DLT_HHDLC is out of luck.
+ *
+ * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map
+ * it, so that savefiles won't use 121 for PFSYNC - they'll all
+ * use 18.  Code that uses pcap_datalink() to determine the link-layer
+ * header type of a savefile won't, when built and run on FreeBSD,
+ * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC
+ * capture files; code that doesn't, such as the code in Wireshark,
+ * will be able to distinguish between them.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC             121
+#else
+#define DLT_HHDLC              121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC         122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM             123     /* Solaris+SunATM */
+
+/* 
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO                 124     /* RapidIO */
+#define DLT_PCI_EXP             125     /* PCI Express */
+#define DLT_AURORA              126     /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO   127     /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP                128     /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX       129     /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP       130
+#define DLT_JUNIPER_MLFR        131
+#define DLT_JUNIPER_ES          132
+#define DLT_JUNIPER_GGSN        133
+#define DLT_JUNIPER_MFR         134
+#define DLT_JUNIPER_ATM2        135
+#define DLT_JUNIPER_SERVICES    136
+#define DLT_JUNIPER_ATM1        137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>.  The header that's presented is an Ethernet-like
+ * header:
+ *
+ *     #define FIREWIRE_EUI64_LEN      8
+ *     struct firewire_header {
+ *             u_char  firewire_dhost[FIREWIRE_EUI64_LEN];
+ *             u_char  firewire_shost[FIREWIRE_EUI64_LEN];
+ *             u_short firewire_type;
+ *     };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394     138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR     139     /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2               140     /* MTP2, without pseudo-header */
+#define DLT_MTP3               141     /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP               142     /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS             143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA         144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP             145
+#define DLT_IBM_SN             146
+
+/*
+ * Reserved for private use.  If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0              147
+#define DLT_USER1              148
+#define DLT_USER2              149
+#define DLT_USER3              150
+#define DLT_USER4              151
+#define DLT_USER5              152
+#define DLT_USER6              153
+#define DLT_USER7              154
+#define DLT_USER8              155
+#define DLT_USER9              156
+#define DLT_USER10             157
+#define DLT_USER11             158
+#define DLT_USER12             159
+#define DLT_USER13             160
+#define DLT_USER14             161
+#define DLT_USER15             162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ *     http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163   /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR     164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP       165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD           166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION    DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE       167
+#define DLT_JUNIPER_PPPOE_ATM   168
+
+#define DLT_GPRS_LLC           169     /* GPRS LLC */
+#define DLT_GPF_T              170     /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F              171     /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1          172
+#define DLT_GCOM_SERIAL                173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER    174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems.  They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH            175     /* Ethernet */
+#define DLT_ERF_POS            176     /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/).  Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD         177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER       178
+#define DLT_JUNIPER_PPP         179
+#define DLT_JUNIPER_FRELAY      180
+#define DLT_JUNIPER_CHDLC       181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR                 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP          183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429                184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM            185
+
+/*
+ * USB packets, beginning with a USB setup header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB                        186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4   187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX          189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B              190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI                        192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO   193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM         194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ */
+#define DLT_IEEE802_15_4       195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA               196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records.  Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF                        197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board.  Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1              198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc..  Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB               199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST          200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ *     http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS          202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD               203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR       204     /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR    205     /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR    206     /* Frame Relay */
+#define DLT_LAPB_WITH_DIR      207     /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX         209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY            210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST               211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN                        212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL         213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA         214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY    215
+
+/* 
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg. 
+ */
+#define DLT_LINUX_EVDEV                216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define DLT_GSMTAP_UM          217
+#define DLT_GSMTAP_ABIS                218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS               219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED  220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define DLT_DECT               221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ *   I have already written dissectors for but need an OK from
+ *   legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS                 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define DLT_WIHART             223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2               224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS     225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ *     u_int8_t   dli_version;
+ *     u_int8_t   dli_family;
+ *     u_int16_t  dli_htype;
+ *     u_int32_t  dli_pktlen;
+ *     u_int32_t  dli_ifindex;
+ *     u_int32_t  dli_grifindex;
+ *     u_int32_t  dli_zsrc;
+ *     u_int32_t  dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET              226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN.  See Documentation/networking/can.txt in the Linux
+ * source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define DLT_CAN_SOCKETCAN      227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6.  Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define DLT_IPV4               228
+#define DLT_IPV6               229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ *     http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ *     http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ *     http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define DLT_DBUS               231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_VS                 232
+#define DLT_JUNIPER_SRX_E2E            233
+#define DLT_JUNIPER_FIBRECHANNEL       234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver).  See
+ *
+ *     http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define DLT_DVB_CI             235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010).  Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel@cinterion.com>.
+ */
+#define DLT_MUX27010           236
+
+/*
+ * STANAG 5066 D_PDUs.  Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU  237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC  238
+
+/*
+ * NetFilter LOG messages 
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define DLT_NFLOG              239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER                240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT    241
+
+/*
+ * IP-over-Infiniband, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define DLT_IPOIB              242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define DLT_MPEG_2_TS          243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define DLT_NG40               244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define DLT_NFC_LLCP           245
+
+/*
+ * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
+ *
+ * DLT_PFSYNC has different values on different platforms, and all of
+ * them collide with something used elsewhere.  On platforms that
+ * don't already define it, define it as 245.
+ */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
+#define DLT_PFSYNC             246
+#endif
+
+#define DLT_MATCHING_MAX       246     /* highest value in the "matching" range */
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class.  A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x)           ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type.  The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with.  Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define        DLT_CLASS_NETBSD_RAWAF  0x02240000
+#define        DLT_NETBSD_RAWAF(af)    (DLT_CLASS_NETBSD_RAWAF | (af))
+#define        DLT_NETBSD_RAWAF_AF(x)  ((x) & 0x0000ffff)
+#define        DLT_IS_NETBSD_RAWAF(x)  (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define                BPF_LD          0x00
+#define                BPF_LDX         0x01
+#define                BPF_ST          0x02
+#define                BPF_STX         0x03
+#define                BPF_ALU         0x04
+#define                BPF_JMP         0x05
+#define                BPF_RET         0x06
+#define                BPF_MISC        0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define                BPF_W           0x00
+#define                BPF_H           0x08
+#define                BPF_B           0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define                BPF_IMM         0x00
+#define                BPF_ABS         0x20
+#define                BPF_IND         0x40
+#define                BPF_MEM         0x60
+#define                BPF_LEN         0x80
+#define                BPF_MSH         0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code)   ((code) & 0xf0)
+#define                BPF_ADD         0x00
+#define                BPF_SUB         0x10
+#define                BPF_MUL         0x20
+#define                BPF_DIV         0x30
+#define                BPF_OR          0x40
+#define                BPF_AND         0x50
+#define                BPF_LSH         0x60
+#define                BPF_RSH         0x70
+#define                BPF_NEG         0x80
+#define                BPF_JA          0x00
+#define                BPF_JEQ         0x10
+#define                BPF_JGT         0x20
+#define                BPF_JGE         0x30
+#define                BPF_JSET        0x40
+#define BPF_SRC(code)  ((code) & 0x08)
+#define                BPF_K           0x00
+#define                BPF_X           0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define                BPF_A           0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define                BPF_TAX         0x00
+#define                BPF_TXA         0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+       u_short code;
+       u_char  jt;
+       u_char  jf;
+       bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(const struct bpf_insn *, int);
+extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) */
diff --git a/pcap/ipnet.h b/pcap/ipnet.h
new file mode 100644 (file)
index 0000000..5330847
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define        IPH_AF_INET     2               /* Matches Solaris's AF_INET */
+#define        IPH_AF_INET6    26              /* Matches Solaris's AF_INET6 */
+
+#define        IPNET_OUTBOUND          1
+#define        IPNET_INBOUND           2
diff --git a/pcap/namedb.h b/pcap/namedb.h
new file mode 100644 (file)
index 0000000..e314557
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006-10-04 18:09:22 guy Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they'll
+ */
+struct pcap_etherent {
+       u_char addr[6];
+       char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+struct pcap_etherent *pcap_next_etherent(FILE *);
+u_char *pcap_ether_hostton(const char*);
+u_char *pcap_ether_aton(const char *);
+
+bpf_u_int32 **pcap_nametoaddr(const char *);
+#ifdef INET6
+struct addrinfo *pcap_nametoaddrinfo(const char *);
+#endif
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int    pcap_nametoport(const char *, int *, int *);
+int    pcap_nametoportrange(const char *, int *, int *, int *);
+int    pcap_nametoproto(const char *);
+int    pcap_nametoeproto(const char *);
+int    pcap_nametollc(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF            -1
+
+/* XXX move these to pcap-int.h? */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+u_short        __pcap_nametodnaddr(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/pcap/pcap.h b/pcap/pcap.h
new file mode 100644 (file)
index 0000000..a02b359
--- /dev/null
@@ -0,0 +1,462 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.15 2008-10-06 15:27:32 gianluca Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_pcap_h
+#define lib_pcap_pcap_h
+
+#if defined(WIN32)
+  #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+  #include <sys/types.h>
+  #include <sys/socket.h>  /* u_int, u_char etc. */
+#else /* UN*X */
+  #include <sys/types.h>
+  #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap/bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Version number of the current version of the pcap file format.
+ *
+ * NOTE: this is *NOT* the version number of the libpcap library.
+ * To fetch the version information for the version of libpcap
+ * you're using, use pcap_lib_version().
+ */
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ *     introduce a new structure for the new format, if the layout
+ *     of the structure changed;
+ *
+ *     send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ *     a new magic number for your new capture file format, and, when
+ *     you get the new magic number, put it in "savefile.c";
+ *
+ *     use that magic number for save files with the changed file
+ *     header;
+ *
+ *     make the code in "savefile.c" capable of reading files with
+ *     the old file header as well as files with the new file header
+ *     (using the magic number to determine the header format).
+ *
+ * Then supply the changes as a patch at
+ *
+ *     http://sourceforge.net/projects/libpcap/
+ *
+ * so that future versions of libpcap and programs that use it (such as
+ * tcpdump) will be able to read your new capture file format.
+ */
+struct pcap_file_header {
+       bpf_u_int32 magic;
+       u_short version_major;
+       u_short version_minor;
+       bpf_int32 thiszone;     /* gmt to local correction */
+       bpf_u_int32 sigfigs;    /* accuracy of timestamps */
+       bpf_u_int32 snaplen;    /* max length saved portion of each pkt */
+       bpf_u_int32 linktype;   /* data link type (LINKTYPE_*) */
+};
+
+/*
+ * Macros for the value returned by pcap_datalink_ext().
+ * 
+ * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
+ * gives the FCS length of packets in the capture.
+ */
+#define LT_FCS_LENGTH_PRESENT(x)       ((x) & 0x04000000)
+#define LT_FCS_LENGTH(x)               (((x) & 0xF0000000) >> 28)
+#define LT_FCS_DATALINK_EXT(x)         ((((x) & 0xF) << 28) | 0x04000000)
+
+typedef enum {
+       PCAP_D_INOUT = 0,
+       PCAP_D_IN,
+       PCAP_D_OUT
+} pcap_direction_t;
+
+/*
+ * Generic per-packet information, as supplied by libpcap.
+ *
+ * The time stamp can and should be a "struct timeval", regardless of
+ * whether your system supports 32-bit tv_sec in "struct timeval",
+ * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
+ * and 64-bit applications.  The on-disk format of savefiles uses 32-bit
+ * tv_sec (and tv_usec); this structure is irrelevant to that.  32-bit
+ * and 64-bit versions of libpcap, even if they're on the same platform,
+ * should supply the appropriate version of "struct timeval", even if
+ * that's not what the underlying packet capture mechanism supplies.
+ */
+struct pcap_pkthdr {
+       struct timeval ts;      /* time stamp */
+       bpf_u_int32 caplen;     /* length of portion present */
+       bpf_u_int32 len;        /* length this packet (off wire) */
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+       u_int ps_recv;          /* number of packets received */
+       u_int ps_drop;          /* number of packets dropped */
+       u_int ps_ifdrop;        /* drops by interface -- only supported on some platforms */
+#ifdef WIN32
+       u_int bs_capt;          /* number of packets that reach the application */
+#endif /* WIN32 */
+};
+
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+       u_long  rx_packets;        /* total packets received       */
+       u_long  tx_packets;        /* total packets transmitted    */
+       u_long  rx_bytes;          /* total bytes received         */
+       u_long  tx_bytes;          /* total bytes transmitted      */
+       u_long  rx_errors;         /* bad packets received         */
+       u_long  tx_errors;         /* packet transmit problems     */
+       u_long  rx_dropped;        /* no space in Rx buffers       */
+       u_long  tx_dropped;        /* no space available for Tx    */
+       u_long  multicast;         /* multicast packets received   */
+       u_long  collisions;
+
+       /* detailed rx_errors: */
+       u_long  rx_length_errors;
+       u_long  rx_over_errors;    /* receiver ring buff overflow  */
+       u_long  rx_crc_errors;     /* recv'd pkt with crc error    */
+       u_long  rx_frame_errors;   /* recv'd frame alignment error */
+       u_long  rx_fifo_errors;    /* recv'r fifo overrun          */
+       u_long  rx_missed_errors;  /* recv'r missed packet         */
+
+       /* detailed tx_errors */
+       u_long  tx_aborted_errors;
+       u_long  tx_carrier_errors;
+       u_long  tx_fifo_errors;
+       u_long  tx_heartbeat_errors;
+       u_long  tx_window_errors;
+     };
+#endif
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+       struct pcap_if *next;
+       char *name;             /* name to hand to "pcap_open_live()" */
+       char *description;      /* textual description of interface, or NULL */
+       struct pcap_addr *addresses;
+       bpf_u_int32 flags;      /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK       0x00000001      /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+       struct pcap_addr *next;
+       struct sockaddr *addr;          /* address */
+       struct sockaddr *netmask;       /* netmask for that address */
+       struct sockaddr *broadaddr;     /* broadcast address for that address */
+       struct sockaddr *dstaddr;       /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+                            const u_char *);
+
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR                     -1      /* generic error code */
+#define PCAP_ERROR_BREAK               -2      /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED       -3      /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED           -4      /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE      -5      /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP                -6      /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON           -7      /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED         -8      /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP                -9      /* interface isn't up */
+#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10     /* this device doesn't support setting the time stamp type */
+#define PCAP_ERROR_PROMISC_PERM_DENIED -11     /* you don't have permission to capture in promiscuous mode */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING                   1       /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP    2       /* this device doesn't support promiscuous mode */
+#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP        3       /* the requested time stamp type is not supported */
+
+/*
+ * Value to pass to pcap_compile() as the netmask if you don't know what
+ * the netmask is.
+ */
+#define PCAP_NETMASK_UNKNOWN   0xffffffff
+
+char   *pcap_lookupdev(char *);
+int    pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+pcap_t *pcap_create(const char *, char *);
+int    pcap_set_snaplen(pcap_t *, int);
+int    pcap_set_promisc(pcap_t *, int);
+int    pcap_can_set_rfmon(pcap_t *);
+int    pcap_set_rfmon(pcap_t *, int);
+int    pcap_set_timeout(pcap_t *, int);
+int    pcap_set_tstamp_type(pcap_t *, int);
+int    pcap_set_buffer_size(pcap_t *, int);
+int    pcap_activate(pcap_t *);
+
+int    pcap_list_tstamp_types(pcap_t *, int **);
+void   pcap_free_tstamp_types(int *);
+int    pcap_tstamp_type_name_to_val(const char *);
+const char *pcap_tstamp_type_val_to_name(int);
+const char *pcap_tstamp_type_val_to_description(int);
+
+/*
+ * Time stamp types.
+ * Not all systems and interfaces will necessarily support all of these.
+ *
+ * A system that supports PCAP_TSTAMP_HOST is offering time stamps
+ * provided by the host machine, rather than by the capture device,
+ * but not committing to any characteristics of the time stamp;
+ * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes.
+ *
+ * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine,
+ * that's low-precision but relatively cheap to fetch; it's normally done
+ * using the system clock, so it's normally synchronized with times you'd
+ * fetch from system calls.
+ *
+ * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine,
+ * that's high-precision; it might be more expensive to fetch.  It might
+ * or might not be synchronized with the system clock, and might have
+ * problems with time stamps for packets received on different CPUs,
+ * depending on the platform.
+ *
+ * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the
+ * capture device; it's synchronized with the system clock.
+ *
+ * PCAP_TSTAMP_ADAPTER_UNSYNCED is a high-precision time stamp supplied by
+ * the capture device; it's not synchronized with the system clock.
+ *
+ * Note that time stamps synchronized with the system clock can go
+ * backwards, as the system clock can go backwards.  If a clock is
+ * not in sync with the system clock, that could be because the
+ * system clock isn't keeping accurate time, because the other
+ * clock isn't keeping accurate time, or both.
+ *
+ * Note that host-provided time stamps generally correspond to the
+ * time when the time-stamping code sees the packet; this could
+ * be some unknown amount of time after the first or last bit of
+ * the packet is received by the network adapter, due to batching
+ * of interrupts for packet arrival, queueing delays, etc..
+ */
+#define PCAP_TSTAMP_HOST               0       /* host-provided, unknown characteristics */
+#define PCAP_TSTAMP_HOST_LOWPREC       1       /* host-provided, low precision */
+#define PCAP_TSTAMP_HOST_HIPREC                2       /* host-provided, high precision */
+#define PCAP_TSTAMP_ADAPTER            3       /* device-provided, synced with the system clock */
+#define PCAP_TSTAMP_ADAPTER_UNSYNCED   4       /* device-provided, not synced with the system clock */
+
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
+pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_offline(const char *, char *);
+#if defined(WIN32)
+pcap_t  *pcap_hopen_offline(intptr_t, char *);
+#if !defined(LIBPCAP_EXPORTS)
+#define pcap_fopen_offline(f,b) \
+       pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
+#else /*LIBPCAP_EXPORTS*/
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+#else /*WIN32*/
+pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*WIN32*/
+
+void   pcap_close(pcap_t *);
+int    pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int    pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+       pcap_next(pcap_t *, struct pcap_pkthdr *);
+int    pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+void   pcap_breakloop(pcap_t *);
+int    pcap_stats(pcap_t *, struct pcap_stat *);
+int    pcap_setfilter(pcap_t *, struct bpf_program *);
+int    pcap_setdirection(pcap_t *, pcap_direction_t);
+int    pcap_getnonblock(pcap_t *, char *);
+int    pcap_setnonblock(pcap_t *, int, char *);
+int    pcap_inject(pcap_t *, const void *, size_t);
+int    pcap_sendpacket(pcap_t *, const u_char *, int);
+const char *pcap_statustostr(int);
+const char *pcap_strerror(int);
+char   *pcap_geterr(pcap_t *);
+void   pcap_perror(pcap_t *, char *);
+int    pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+           bpf_u_int32);
+int    pcap_compile_nopcap(int, int, struct bpf_program *,
+           const char *, int, bpf_u_int32);
+void   pcap_freecode(struct bpf_program *);
+int    pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
+           const u_char *);
+int    pcap_datalink(pcap_t *);
+int    pcap_datalink_ext(pcap_t *);
+int    pcap_list_datalinks(pcap_t *, int **);
+int    pcap_set_datalink(pcap_t *, int);
+void   pcap_free_datalinks(int *);
+int    pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+int    pcap_snapshot(pcap_t *);
+int    pcap_is_swapped(pcap_t *);
+int    pcap_major_version(pcap_t *);
+int    pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE   *pcap_file(pcap_t *);
+int    pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+FILE   *pcap_dump_file(pcap_dumper_t *);
+long   pcap_dump_ftell(pcap_dumper_t *);
+int    pcap_dump_flush(pcap_dumper_t *);
+void   pcap_dump_close(pcap_dumper_t *);
+void   pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+int    pcap_findalldevs(pcap_if_t **, char *);
+void   pcap_freealldevs(pcap_if_t *);
+
+const char *pcap_lib_version(void);
+
+/*
+ * On at least some versions of NetBSD, we don't want to declare
+ * bpf_filter() here, as it's also be declared in <net/bpf.h>, with a
+ * different signature, but, on other BSD-flavored UN*Xes, it's not
+ * declared in <net/bpf.h>, so we *do* want to declare it here, so it's
+ * declared when we build pcap-bpf.c.
+ */
+#ifndef __NetBSD__
+u_int  bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#endif
+int    bpf_validate(const struct bpf_insn *f, int len);
+char   *bpf_image(const struct bpf_insn *, int);
+void   bpf_dump(const struct bpf_program *, int);
+
+#if defined(WIN32)
+
+/*
+ * Win32 definitions
+ */
+
+int pcap_setbuff(pcap_t *p, int dim);
+int pcap_setmode(pcap_t *p, int mode);
+int pcap_setmintocopy(pcap_t *p, int size);
+
+#ifdef WPCAP
+/* Include file with the wpcap-specific extensions */
+#include <Win32-Extensions.h>
+#endif /* WPCAP */
+
+#define MODE_CAPT 0
+#define MODE_STAT 1
+#define MODE_MON 2
+
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int  pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
+/*
+ * UN*X definitions
+ */
+
+int    pcap_get_selectable_fd(pcap_t *);
+
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* lib_pcap_pcap_h */
diff --git a/pcap/sll.h b/pcap/sll.h
new file mode 100644 (file)
index 0000000..7ad811d
--- /dev/null
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.3 2008-05-30 01:35:33 guy Exp $ (LBL)
+ */
+
+/*
+ * For captures on Linux cooked sockets, we construct a fake header
+ * that includes:
+ *
+ *     a 2-byte "packet type" which is one of:
+ *
+ *             LINUX_SLL_HOST          packet was sent to us
+ *             LINUX_SLL_BROADCAST     packet was broadcast
+ *             LINUX_SLL_MULTICAST     packet was multicast
+ *             LINUX_SLL_OTHERHOST     packet was sent to somebody else
+ *             LINUX_SLL_OUTGOING      packet was sent *by* us;
+ *
+ *     a 2-byte Ethernet protocol field;
+ *
+ *     a 2-byte link-layer type;
+ *
+ *     a 2-byte link-layer address length;
+ *
+ *     an 8-byte source link-layer address, whose actual length is
+ *     specified by the previous value.
+ *
+ * All fields except for the link-layer address are in network byte order.
+ *
+ * DO NOT change the layout of this structure, or change any of the
+ * LINUX_SLL_ values below.  If you must change the link-layer header
+ * for a "cooked" Linux capture, introduce a new DLT_ type (ask
+ * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
+ * new header in captures of that type, so that programs that can
+ * handle DLT_LINUX_SLL captures will continue to handle them correctly
+ * without any change, and so that capture files with different headers
+ * can be told apart and programs that read them can dissect the
+ * packets in them.
+ */
+
+#ifndef lib_pcap_sll_h
+#define lib_pcap_sll_h
+
+/*
+ * A DLT_LINUX_SLL fake link-layer header.
+ */
+#define SLL_HDR_LEN    16              /* total header length */
+#define SLL_ADDRLEN    8               /* length of address field */
+
+struct sll_header {
+       u_int16_t sll_pkttype;          /* packet type */
+       u_int16_t sll_hatype;           /* link-layer address type */
+       u_int16_t sll_halen;            /* link-layer address length */
+       u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
+       u_int16_t sll_protocol;         /* protocol */
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
+ * PACKET_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux, and so that they
+ * don't change even if the PACKET_ values change.
+ */
+#define LINUX_SLL_HOST         0
+#define LINUX_SLL_BROADCAST    1
+#define LINUX_SLL_MULTICAST    2
+#define LINUX_SLL_OTHERHOST    3
+#define LINUX_SLL_OUTGOING     4
+
+/*
+ * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
+ * ETH_P_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux.  We assume, for now,
+ * that the ETH_P_ values won't change in Linux; if they do, then:
+ *
+ *     if we don't translate them in "pcap-linux.c", capture files
+ *     won't necessarily be readable if captured on a system that
+ *     defines ETH_P_ values that don't match these values;
+ *
+ *     if we do translate them in "pcap-linux.c", that makes life
+ *     unpleasant for the BPF code generator, as the values you test
+ *     for in the kernel aren't the values that you test for when
+ *     reading a capture file, so the fixup code run on BPF programs
+ *     handed to the kernel ends up having to do more work.
+ *
+ * Add other values here as necessary, for handling packet types that
+ * might show up on non-Ethernet, non-802.x networks.  (Not all the ones
+ * in the Linux "if_ether.h" will, I suspect, actually show up in
+ * captures.)
+ */
+#define LINUX_SLL_P_802_3      0x0001  /* Novell 802.3 frames without 802.2 LLC header */
+#define LINUX_SLL_P_802_2      0x0004  /* 802.2 frames (not D/I/X Ethernet) */
+
+#endif
diff --git a/pcap/usb.h b/pcap/usb.h
new file mode 100644 (file)
index 0000000..aa35122
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.9 2008-12-23 20:13:29 guy Exp $
+ */
+#ifndef _PCAP_USB_STRUCTS_H__
+#define _PCAP_USB_STRUCTS_H__
+
+/* 
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN   0x80
+#define URB_ISOCHRONOUS   0x0
+#define URB_INTERRUPT     0x1
+#define URB_CONTROL       0x2
+#define URB_BULK          0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT        'S'
+#define URB_COMPLETE      'C'
+#define URB_ERROR         'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each Control S-type packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+       u_int8_t bmRequestType;
+       u_int8_t bRequest;
+       u_int16_t wValue;
+       u_int16_t wIndex;
+       u_int16_t wLength;
+} pcap_usb_setup;
+
+/*
+ * Information from the URB for Isochronous transfers.
+ */
+typedef struct _iso_rec {
+       int32_t error_count;
+       int32_t numdesc;
+} iso_rec;
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ */
+typedef struct _usb_header {
+       u_int64_t id;
+       u_int8_t event_type;
+       u_int8_t transfer_type;
+       u_int8_t endpoint_number;
+       u_int8_t device_address;
+       u_int16_t bus_id;
+       char setup_flag;/*if !=0 the urb setup header is not present*/
+       char data_flag; /*if !=0 no urb data is present*/
+       int64_t ts_sec;
+       int32_t ts_usec;
+       int32_t status;
+       u_int32_t urb_len;
+       u_int32_t data_len; /* amount of urb data really present in this event*/
+       pcap_usb_setup setup;
+} pcap_usb_header;
+
+/*
+ * Header prepended by linux kernel to each event for the 2.6.31
+ * and later kernels; for the 2.6.21 through 2.6.30 kernels, the
+ * "iso_rec" information, and the fields starting with "interval"
+ * are zeroed-out padding fields.
+ *
+ * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
+ */
+typedef struct _usb_header_mmapped {
+       u_int64_t id;
+       u_int8_t event_type;
+       u_int8_t transfer_type;
+       u_int8_t endpoint_number;
+       u_int8_t device_address;
+       u_int16_t bus_id;
+       char setup_flag;/*if !=0 the urb setup header is not present*/
+       char data_flag; /*if !=0 no urb data is present*/
+       int64_t ts_sec;
+       int32_t ts_usec;
+       int32_t status;
+       u_int32_t urb_len;
+       u_int32_t data_len; /* amount of urb data really present in this event*/
+       union {
+               pcap_usb_setup setup;
+               iso_rec iso;
+       } s;
+       int32_t interval;       /* for Interrupt and Isochronous events */
+       int32_t start_frame;    /* for Isochronous events */
+       u_int32_t xfer_flags;   /* copy of URB's transfer flags */
+       u_int32_t ndesc;        /* number of isochronous descriptors */
+} pcap_usb_header_mmapped;
+
+/*
+ * Isochronous descriptors; for isochronous transfers there might be
+ * one or more of these at the beginning of the packet data.  The
+ * number of descriptors is given by the "ndesc" field in the header;
+ * as indicated, in older kernels that don't put the descriptors at
+ * the beginning of the packet, that field is zeroed out, so that field
+ * can be trusted even in captures from older kernels.
+ */
+typedef struct _usb_isodesc {
+       int32_t         status;
+       u_int32_t       offset;
+       u_int32_t       len;
+       u_int8_t        pad[4];
+} usb_isodesc;
+
+#endif
diff --git a/pcap/vlan.h b/pcap/vlan.h
new file mode 100644 (file)
index 0000000..41aa8c7
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1 2008-08-06 07:45:00 guy Exp $
+ */
+
+#ifndef lib_pcap_vlan_h
+#define lib_pcap_vlan_h
+
+struct vlan_tag {
+       u_int16_t       vlan_tpid;              /* ETH_P_8021Q */
+       u_int16_t       vlan_tci;               /* VLAN TCI */
+};
+
+#define VLAN_TAG_LEN   4
+
+#endif
diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap
new file mode 100644 (file)
index 0000000..f963d35
--- /dev/null
@@ -0,0 +1,97 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.5 2008-07-01 08:02:33 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_ACTIVATE 3PCAP "5 April 2008"
+.SH NAME
+pcap_activate \- activate a capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_activate(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_activate()
+is used to activate a packet capture handle to look
+at packets on the network, with the options that were set on the handle
+being in effect.
+.SH RETURN VALUE
+.B pcap_activate()
+returns 0 on success without warnings,
+.B PCAP_WARNING_PROMISC_NOTSUP
+on success on a device that doesn't support promiscuous mode if
+promiscuous mode was requested,
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+on success if the time stamp type specified in a previous
+.B pcap_set_tstamp_type()
+call isn't supported by the capture source (the time stamp type is
+left as the default),
+.B PCAP_WARNING
+on success with any other warning,
+.B PCAP_ERROR_ACTIVATED
+if the handle has already been activated,
+.B PCAP_ERROR_NO_SUCH_DEVICE
+if the capture source specified when the handle was created doesn't
+exist,
+.B PCAP_ERROR_PERM_DENIED
+if the process doesn't have permission to open the capture source,
+.B PCAP_ERROR_PROMISC_PERM_DENIED
+if the process has permission to open the capture source but doesn't
+have permission to put it into promiscuous mode,
+.B PCAP_ERROR_RFMON_NOTSUP
+if monitor mode was specified but the capture source doesn't support
+monitor mode,
+.B PCAP_ERROR_IFACE_NOT_UP
+if the capture source is not up, and
+.B PCAP_ERROR
+if another error occurred.
+If
+.B PCAP_WARNING
+or
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display a message describing the warning or
+error.
+If
+.BR PCAP_WARNING_PROMISC_NOTSUP ,
+.BR PCAP_ERROR_NO_SUCH_DEVICE ,
+or
+.B PCAP_ERROR_PERM_DENIED
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display an message giving additional details
+about the problem that might be useful for debugging the problem if it's
+unexpected.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_breakloop.3pcap b/pcap_breakloop.3pcap
new file mode 100644 (file)
index 0000000..2372348
--- /dev/null
@@ -0,0 +1,105 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_breakloop.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_BREAKLOOP 3PCAP "5 April 2008"
+.SH NAME
+pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_breakloop(pcap_t *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_breakloop()
+sets a flag that will force
+.B pcap_dispatch()
+or
+.B pcap_loop()
+to return rather than looping; they will return the number of packets
+that have been processed so far, or \-2 if no packets have been
+processed so far.
+.PP
+This routine is safe to use inside a signal handler on UNIX or a console
+control handler on Windows, as it merely sets a flag that is checked
+within the loop.
+.PP
+The flag is checked in loops reading packets from the OS - a signal by
+itself will not necessarily terminate those loops - as well as in loops
+processing a set of packets returned by the OS.
+.ft B
+Note that if you are catching signals on UNIX systems that support
+restarting system calls after a signal, and calling pcap_breakloop()
+in the signal handler, you must specify, when catching those signals,
+that system calls should NOT be restarted by that signal.  Otherwise,
+if the signal interrupted a call reading packets in a live capture,
+when your signal handler returns after calling pcap_breakloop(), the
+call will be restarted, and the loop will not terminate until more
+packets arrive and the call completes.
+.PP
+Note also that, in a multi-threaded application, if one thread is
+blocked in
+.BR pcap_dispatch() ,
+.BR pcap_loop() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() ,
+a call to
+.B pcap_breakloop()
+in a different thread will not unblock that thread; you will need to use
+whatever mechanism the OS provides for breaking a thread out of blocking
+calls in order to unblock the thread, such as thread cancellation in
+systems that support POSIX threads.
+.ft R
+.PP
+Note that
+.B pcap_next()
+and
+.B pcap_next_ex()
+will, on some platforms, loop reading packets from the OS; that loop
+will not necessarily be terminated by a signal, so
+.B pcap_breakloop()
+should be used to terminate packet processing even if
+.B pcap_next()
+or
+.B pcap_next_ex()
+is being used.
+.PP
+.B pcap_breakloop()
+does not guarantee that no further packets will be processed by
+.B pcap_dispatch()
+or
+.B pcap_loop()
+after it is called; at most one more packet might be processed.
+.PP
+If \-2 is returned from
+.B pcap_dispatch()
+or
+.BR pcap_loop() ,
+the flag is cleared, so a subsequent call will resume reading packets. 
+If a positive number is returned, the flag is not cleared, so a
+subsequent call will return \-2 and clear the flag.
+.SH SEE ALSO
+pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP)
diff --git a/pcap_can_set_rfmon.3pcap b/pcap_can_set_rfmon.3pcap
new file mode 100644 (file)
index 0000000..00b92a4
--- /dev/null
@@ -0,0 +1,64 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_can_set_rfmon.3pcap,v 1.1 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CAN_SET_RFMON 3PCAP "18 May 2010"
+.SH NAME
+pcap_can_set_rfmon \- check whether monitor mode can be set for a
+not-yet-activated capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_can_set_rfmon(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_can_set_rfmon()
+checks whether monitor mode could be set on a capture handle when
+the handle is activated.
+.SH RETURN VALUE
+.B pcap_can_set_rfmon()
+returns 0 if monitor mode could not be set,
+1 if monitor mode could be set,
+.B PCAP_ERROR_NO_SUCH_DEVICE
+if the capture source specified when the handle was created doesn't
+exist,
+.B PCAP_ERROR_PERM_DENIED
+if the process doesn't have permission to check whether monitor mode
+could be supported,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, or
+.B PCAP_ERROR
+if an error occurred.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_set_rfmon(3PCAP)
diff --git a/pcap_close.3pcap b/pcap_close.3pcap
new file mode 100644 (file)
index 0000000..810664d
--- /dev/null
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_close.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CLOSE 3PCAP "5 April 2008"
+.SH NAME
+pcap_close \- close a capture device or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_close(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_close()
+closes the files associated with
+.I p
+and deallocates resources.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_compile.3pcap.in b/pcap_compile.3pcap.in
new file mode 100644 (file)
index 0000000..7dbdad5
--- /dev/null
@@ -0,0 +1,72 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_compile.3pcap.in,v 1.1 2008-10-21 07:33:02 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_COMPILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program.  See
+.BR pcap-filter (@MAN_MISC_INFO@)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program.  If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied; tests
+for IPv4 broadcast addresses will fail to compile, but all other tests in
+the filter program will be OK.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
+pcap_geterr(3PCAP), pcap-filter(@MAN_MISC_INFO@)
diff --git a/pcap_create.3pcap b/pcap_create.3pcap
new file mode 100644 (file)
index 0000000..153f9fd
--- /dev/null
@@ -0,0 +1,74 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_create.3pcap,v 1.1 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CREATE 3PCAP "5 April 2008"
+.SH NAME
+pcap_create \- create a live capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_create(const char *source, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_create()
+is used to create a packet capture handle to look
+at packets on the network.
+.I source
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I source
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+The returned handle must be activated with
+.B pcap_activate()
+before packets can be captured
+with it; options for the capture, such as promiscuous mode, can be set
+on the handle before activating it.
+.SH RETURN VALUE
+.B pcap_create()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_datalink.3pcap.in b/pcap_datalink.3pcap.in
new file mode 100644 (file)
index 0000000..3d4ace1
--- /dev/null
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink.3pcap.in,v 1.1 2008-10-21 07:33:02 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "22 August 2010"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link-layer header type for the live capture or ``savefile''
+specified by
+.IR p .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/pcap_datalink_name_to_val.3pcap b/pcap_datalink_name_to_val.3pcap
new file mode 100644 (file)
index 0000000..9c8e18a
--- /dev/null
@@ -0,0 +1,48 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_name_to_val.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "22 August 2010"
+.SH NAME
+pcap_datalink_name_to_val \- get the link-layer header type value
+corresponding to a header type name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink_name_to_val(const char *name);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_name_to_val()
+translates a link-layer header type name, which is a
+.B DLT_
+name with the
+.B DLT_
+removed, to the corresponding link-layer header type value.  The
+translation is case-insensitive.
+.SH RETURN VALUE
+.B pcap_datalink_name_to_val()
+returns 0 on success and \-1 on failure.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_datalink_val_to_name.3pcap b/pcap_datalink_val_to_name.3pcap
new file mode 100644 (file)
index 0000000..26397fa
--- /dev/null
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_val_to_name.3pcap,v 1.3 2008-12-24 21:45:25 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "22 August 2010"
+.SH NAME
+pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
+name or description for a link-layer header type value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_datalink_val_to_name(int dlt);
+const char *pcap_datalink_val_to_description(int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_val_to_name()
+translates a link-layer header type value to the corresponding
+link-layer header type name.  NULL is returned on failure.
+.PP
+.B pcap_datalink_val_to_description()
+translates a link-layer header type value to a short description of that
+link-layer header type.  NULL is returned on failure.
diff --git a/pcap_dump.3pcap b/pcap_dump.3pcap
new file mode 100644 (file)
index 0000000..1ccd82a
--- /dev/null
@@ -0,0 +1,53 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump \- write a packet to a capture file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump(u_char *user, struct pcap_pkthdr *h,
+.ti +8
+u_char *sp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump()
+outputs a packet to the ``savefile'' opened with
+.BR pcap_dump_open() .
+Note that its calling arguments are suitable for use with
+.B pcap_dispatch()
+or
+.BR pcap_loop() .
+If called directly, the 
+.I user
+parameter is of type 
+.B pcap_dumper_t
+as returned by
+.BR pcap_dump_open() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dispatch(3PCAP),
+pcap_loop(3PCAP)
diff --git a/pcap_dump_close.3pcap b/pcap_dump_close.3pcap
new file mode 100644 (file)
index 0000000..4ed820b
--- /dev/null
@@ -0,0 +1,39 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_close.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_CLOSE 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_close \- close a savefile being written to
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump_close(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_close()
+closes the ``savefile.''
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/pcap_dump_file.3pcap b/pcap_dump_file.3pcap
new file mode 100644 (file)
index 0000000..9e51a2a
--- /dev/null
@@ -0,0 +1,40 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_file.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_file \- get the standard I/O stream for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_dump_file(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_file()
+returns the standard I/O stream of the ``savefile'' opened by
+.BR pcap_dump_open() .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_dump_flush.3pcap b/pcap_dump_flush.3pcap
new file mode 100644 (file)
index 0000000..b553883
--- /dev/null
@@ -0,0 +1,45 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_flush.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FLUSH 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_flush \- flush to a savefile packets dumped
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_dump_flush(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_flush()
+flushes the output buffer to the ``savefile,'' so that any packets
+written with
+.B pcap_dump()
+but not yet written to the ``savefile'' will be written.
+.SH RETURN VALUE
+.B pcap_dump_flush()
+returns 0 on success and \-1 on failure.
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/pcap_dump_ftell.3pcap b/pcap_dump_ftell.3pcap
new file mode 100644 (file)
index 0000000..1d0f96f
--- /dev/null
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_ftell.3pcap,v 1.3 2008-04-06 02:53:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FTELL 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_ftell \- get the current file offset for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+long pcap_dump_ftell(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_ftell()
+returns the current file position for the ``savefile'', representing the
+number of bytes written by
+.B pcap_dump_open()
+and
+.BR pcap_dump() .
+\-1 is returned on error.
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/pcap_dump_open.3pcap.in b/pcap_dump_open.3pcap.in
new file mode 100644 (file)
index 0000000..2a5dc9d
--- /dev/null
@@ -0,0 +1,87 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_open.3pcap.in,v 1.1 2008-10-23 05:56:59 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_OPEN 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" in a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create()
+and activated by an earlier call to
+.BR pcap_activate() ,
+or returned by an earlier call to
+.BR pcap_open_offline() ,
+.BR pcap_open_live() ,
+or
+.BR pcap_open_dead() .
+The link-layer type and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump()
+and
+.B pcap_dump_close()
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(\fIp\fB)
+can be used to get the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP),
+pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
+pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/pcap_file.3pcap b/pcap_file.3pcap
new file mode 100644 (file)
index 0000000..1471ab6
--- /dev/null
@@ -0,0 +1,59 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_file.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_file \- get the standard I/O stream for a savefile being read
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_file(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_file()
+returns the standard I/O stream of the ``savefile,'' if a ``savefile''
+was opened with
+.BR pcap_open_offline() ,
+or NULL, if a network device was opened with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() .
+.PP
+Note that the Packet Capture library is usually built with large file
+support, so the standard I/O stream of the ``savefile'' might refer to
+a file larger than 2 gigabytes; applications that use
+.B pcap_file()
+should, if possible, use calls that support large files on the return
+value of
+.B pcap_file()
+or the value returned by
+.B fileno()
+when passed the return value of
+.BR pcap_file() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_open_offline(3PCAP)
diff --git a/pcap_fileno.3pcap b/pcap_fileno.3pcap
new file mode 100644 (file)
index 0000000..723733e
--- /dev/null
@@ -0,0 +1,68 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_fileno.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILENO 3PCAP "5 April 2008"
+.SH NAME
+pcap_fileno \- get the file descriptor for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_fileno(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+If
+.I p
+refers to a network device that was opened for a live capture using
+a combination of
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or using
+.BR pcap_open_live() ,
+.B pcap_fileno()
+returns the file descriptor from which captured packets are read.
+.LP
+If
+.I p
+refers to a ``savefile'' that was opened using functions such as
+.BR pcap_open_offline()
+or
+.BR pcap_fopen_offline() ,
+a ``dead''
+.B pcap_t
+opened using
+.BR pcap_open_dead() ,
+or a
+.B pcap_t
+that was created with
+.B pcap_create()
+but that has not yet been activated with
+.BR pcap_activate() ,
+it returns \-1.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_live(3PCAP), pcap_open_offline(3PCAP),
+pcap_fopen_offline(3PCAP), pcap_open_dead(3PCAP)
diff --git a/pcap_findalldevs.3pcap b/pcap_findalldevs.3pcap
new file mode 100644 (file)
index 0000000..2e56d09
--- /dev/null
@@ -0,0 +1,186 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_findalldevs.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FINDALLDEVS 3PCAP "22 August 2010"
+.SH NAME
+pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
+free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
+void pcap_freealldevs(pcap_if_t *alldevs);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_findalldevs()
+constructs a list of network devices that can be opened with
+.B pcap_create()
+and
+.B pcap_activate()
+or with
+.BR pcap_open_live() .
+(Note that there may be network devices that cannot be opened by the
+process calling
+.BR pcap_findalldevs() ,
+because, for example, that process does not have sufficient privileges
+to open them for capturing; if so, those devices will not appear on the
+list.)
+If
+.B pcap_findalldevs()
+succeeds, the pointer pointed to by
+.I alldevsp
+is set to point to the first element of the list, or to
+.B NULL
+if no devices were found (this is considered success).
+Each element of the list is of type
+.BR pcap_if_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B name
+a pointer to a string giving a name for the device to pass to
+.B pcap_open_live()
+.TP
+.B description
+if not
+.BR NULL ,
+a pointer to a string giving a human-readable description of the device
+.TP
+.B addresses
+a pointer to the first element of a list of network addresses for the
+device,
+or
+.B NULL
+if the device has no addresses
+.TP
+.B flags
+device flags:
+.RS
+.TP
+.B PCAP_IF_LOOPBACK
+set if the device is a loopback interface
+.RE
+.RE
+.PP
+Each element of the list of addresses is of type
+.BR pcap_addr_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B addr
+a pointer to a
+.B "struct sockaddr"
+containing an address
+.TP
+.B netmask
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the netmask corresponding to the address pointed to by
+.B addr
+.TP
+.B broadaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the broadcast address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the device doesn't support broadcasts
+.TP
+.B dstaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the destination address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the device isn't a point-to-point interface
+.RE
+.PP
+Note that the addresses in the list of addresses might be IPv4
+addresses, IPv6 addresses, or some other type of addresses, so you must
+check the
+.B sa_family
+member of the
+.B "struct sockaddr"
+before interpreting the contents of the address; do not assume that the
+addresses are all IPv4 addresses, or even all IPv4 or IPv6 addresses.
+IPv4 addresses have the value
+.BR AF_INET ,
+IPv6 addresses have the value
+.B AF_INET6
+(which older operating systems that don't support IPv6 might not
+define), and other addresses have other values.  Whether other addresses
+are returned, and what types they might have is platform-dependent.
+For IPv4 addresses, the
+.B "struct sockaddr"
+pointer can be interpreted as if it pointed to a
+.BR "struct sockaddr_in" ;
+for IPv6 addresses, it can be interpreted as if it pointed to a
+.BR "struct sockaddr_in6".
+.PP
+The list of devices must be freed with
+.BR pcap_freealldevs() ,
+whch frees the list pointed to by
+.IR alldevs .
+.SH RETURN VALUE
+.B pcap_findalldevs()
+returns 0 on success and \-1 on failure; as indicated, finding no
+devices is considered success, rather than failure, so 0 will be
+returned in that case.
+If \-1 is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_live(3PCAP)
diff --git a/pcap_freecode.3pcap b/pcap_freecode.3pcap
new file mode 100644 (file)
index 0000000..31b4f89
--- /dev/null
@@ -0,0 +1,45 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_freecode.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FREECODE 3PCAP "5 April 2008"
+.SH NAME
+pcap_freecode \- free a BPF program
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_freecode(struct bpf_program *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_freecode()
+is used to free up allocated memory pointed to by a
+.I bpf_program
+struct generated by
+.B pcap_compile()
+when that BPF program is no longer needed, for example after it
+has been made the filter program for a pcap structure by a call to
+.BR pcap_setfilter() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP), pcap_setfilter(3PCAP)
diff --git a/pcap_get_selectable_fd.3pcap b/pcap_get_selectable_fd.3pcap
new file mode 100644 (file)
index 0000000..ae33dbb
--- /dev/null
@@ -0,0 +1,129 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_get_selectable_fd.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "5 April 2008"
+.SH NAME
+pcap_get_selectable_fd \- get a file descriptor on which a select() can
+be done for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_selectable_fd(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_selectable_fd()
+returns, on UNIX, a file descriptor number for a file descriptor on
+which one can
+do a
+.B select()
+or
+.B poll()
+to wait for it to be possible to read packets without blocking, if such
+a descriptor exists, or \-1, if no such descriptor exists.  Some network
+devices opened with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() ,
+do not support
+.B select()
+or
+.B poll()
+(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace
+DAG devices), so \-1 is returned for those devices.
+.PP
+Note that in:
+.IP
+FreeBSD prior to FreeBSD 4.6;
+.IP
+NetBSD prior to NetBSD 3.0;
+.IP
+OpenBSD prior to OpenBSD 2.4;
+.IP
+Mac OS X prior to Mac OS X 10.7;
+.PP
+.B select()
+and
+.B poll()
+do not work correctly on BPF devices;
+.B pcap_get_selectable_fd()
+will return a file descriptor on most of those versions (the exceptions
+being FreeBSD 4.3 and 4.4), but a simple
+.B select()
+or
+.B poll()
+will not indicate that the descriptor is readable until a full buffer's
+worth of packets is received, even if the read timeout expires before
+then.  To work around this, an application that uses
+.B select()
+or
+.B poll()
+to wait for packets to arrive must put the
+.B pcap_t
+in non-blocking mode, and must arrange that the
+.B select()
+or
+.B poll()
+have a timeout less than or equal to the read timeout,
+and must try to read packets after that timeout expires, regardless of
+whether
+.B select()
+or
+.B poll()
+indicated that the file descriptor for the
+.B pcap_t
+is ready to be read or not.  (That workaround will not work in FreeBSD
+4.3 and later; however, in FreeBSD 4.6 and later,
+.B select()
+and
+.B poll()
+work correctly on BPF devices, so the workaround isn't necessary,
+although it does no harm.)
+.PP
+Note also that
+.B poll()
+doesn't work on character special files, including BPF devices, in Mac
+OS X 10.4 and 10.5, so, while
+.B select()
+can be used on the descriptor returned by
+.BR pcap_get_selectable_fd() ,
+.B poll()
+cannot be used on it those versions of Mac OS X.  Kqueues also don't
+work on that descriptor.
+.BR poll() ,
+but not kqueues, work on that descriptor in Mac OS X releases prior to
+10.4;
+.B poll()
+and kqueues work on that descriptor in Mac OS X 10.6 and later.
+.PP
+.B pcap_get_selectable_fd()
+is not available on Windows.
+.SH RETURN VALUE
+A selectable file descriptor is returned if one exists; otherwise, \-1
+is returned.
+.SH SEE ALSO
+pcap(3PCAP), select(2), poll(2)
diff --git a/pcap_geterr.3pcap b/pcap_geterr.3pcap
new file mode 100644 (file)
index 0000000..1a4ea34
--- /dev/null
@@ -0,0 +1,53 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_geterr.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GETERR 3PCAP "5 April 2008"
+.SH NAME
+pcap_geterr, pcap_perror \- get or print libpcap error message text
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+char *pcap_geterr(pcap_t *p);
+void pcap_perror(pcap_t *p, char *prefix);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_geterr()
+returns the error text pertaining to the last pcap library error.
+.BR NOTE :
+the pointer it returns will no longer point to a valid error message
+string after the
+.B pcap_t
+passed to it is closed; you must use or copy the string before closing
+the
+.BR pcap_t .
+.PP
+.B pcap_perror()
+prints the text of the last pcap library error on
+.BR stderr ,
+prefixed by
+.IR prefix .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_inject.3pcap b/pcap_inject.3pcap
new file mode 100644 (file)
index 0000000..79a3eea
--- /dev/null
@@ -0,0 +1,90 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_inject.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_INJECT 3PCAP "5 April 2008"
+.SH NAME
+pcap_inject, pcap_sendpacket \- transmit a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_inject(pcap_t *p, const void *buf, size_t size);
+int pcap_sendpacket(pcap_t *p, const u_char *buf, int size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_inject()
+sends a raw packet through the network interface;
+.I buf
+points to the data of the packet, including the link-layer header, and
+.I size
+is the number of bytes in the packet.
+.PP
+Note that, even if you successfully open the network interface, you
+might not have permission to send packets on it, or it might not support
+sending packets; as
+.I pcap_open_live()
+doesn't have a flag to indicate whether to open for capturing, sending,
+or capturing and sending, you cannot request an open that supports
+sending and be notified at open time whether sending will be possible.
+Note also that some devices might not support sending packets.
+.PP
+Note that, on some platforms, the link-layer header of the packet that's
+sent might not be the same as the link-layer header of the packet
+supplied to
+.BR pcap_inject() ,
+as the source link-layer address, if the header contains such an
+address, might be changed to be the address assigned to the interface on
+which the packet it sent, if the platform doesn't support sending
+completely raw and unchanged packets.  Even worse, some drivers on some
+platforms might change the link-layer type field to whatever value
+libpcap used when attaching to the device, even on platforms that
+.I do
+nominally support sending completely raw and unchanged packets.
+.PP
+.B pcap_sendpacket()
+is like
+.BR pcap_inject() ,
+but it returns 0 on success, rather than returning the number of bytes
+written.
+.RB ( pcap_inject()
+comes from OpenBSD;
+.B pcap_sendpacket()
+comes from WinPcap.  Both are provided for compatibility.)
+.SH RETURN VALUE
+.B pcap_inject()
+returns the number of bytes written on success and \-1 on failure.
+.PP
+.B pcap_sendpacket()
+returns 0 on success and \-1 on failure.
+.PP
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/pcap_is_swapped.3pcap b/pcap_is_swapped.3pcap
new file mode 100644 (file)
index 0000000..4d26b3b
--- /dev/null
@@ -0,0 +1,42 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_is_swapped.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_IS_SWAPPED 3PCAP "5 April 2008"
+.SH NAME
+pcap_is_swapped \- find out whether a savefile has the native byte order
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_is_swapped(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_is_swapped()
+returns true if
+.I p
+refers to a ``savefile'' that uses a different byte order
+than the current system.  For a live capture, it always returns false.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_lib_version.3pcap b/pcap_lib_version.3pcap
new file mode 100644 (file)
index 0000000..7b39be1
--- /dev/null
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lib_version.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIB_VERSION 3PCAP "5 April 2008"
+.SH NAME
+pcap_lib_version \- get the version information for libpcap
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_lib_version(void);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lib_version()
+returns a pointer to a string giving information about the version of
+the libpcap library being used; note that it contains more information
+than just a version number.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_list_datalinks.3pcap.in b/pcap_list_datalinks.3pcap.in
new file mode 100644 (file)
index 0000000..6327576
--- /dev/null
@@ -0,0 +1,64 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_list_datalinks.3pcap.in,v 1.1 2008-10-21 07:33:02 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_DATALINKS 3PCAP "22 August 2010"
+.SH NAME
+pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
+types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+void pcap_free_datalinks(int *dlt_list);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported link-layer header types of the
+interface associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf 
+to point to that array.
+.LP
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks() ,
+which frees the list of link-layer header types pointed to by
+.IR dlt_list .
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of link-layer header types in the array on success
+and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP),
+pcap_datalink_val_to_name(3PCAP),
+pcap-linktype(@MAN_MISC_INFO@)
diff --git a/pcap_list_tstamp_types.3pcap.in b/pcap_list_tstamp_types.3pcap.in
new file mode 100644 (file)
index 0000000..66d3d66
--- /dev/null
@@ -0,0 +1,70 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "21 August 2010"
+.SH NAME
+pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
+stamp types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp);
+void pcap_free_tstamp_types(int *tstamp_types);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_tstamp_types()
+is used to get a list of the supported time stamp types of the interface
+associated with the pcap descriptor.
+.B pcap_list_tstamp_types()
+allocates an array to hold the list and sets
+.I *tstamp_typesp
+to point to the array.
+See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of all the time stamp types.
+.PP
+The caller is responsible for freeing the array with
+.BR pcap_free_tstamp_types() ,
+which frees the list pointed to by
+.IR tstamp_types .
+.SH RETURN VALUE
+.B pcap_list_tstamp_types()
+returns the number of time stamp types in the array on success and
+.B PCAP_ERROR
+on failure.
+A return value of zero means that you cannot specify a time stamp type;
+you are limited to the capture device's default time stamp type.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
+pcap-tstamp(@MAN_MISC_INFO@)
diff --git a/pcap_lookupdev.3pcap b/pcap_lookupdev.3pcap
new file mode 100644 (file)
index 0000000..8b23cb8
--- /dev/null
@@ -0,0 +1,62 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupdev.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPDEV 3PCAP "5 April 2008"
+.SH NAME
+pcap_lookupdev \- find the default device on which to capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+char *pcap_lookupdev(char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lookupdev()
+returns a pointer to a string giving the name of a network device
+suitable for use with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() ,
+and with
+.BR pcap_lookupnet() .
+If there is an error,
+.B NULL
+is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_live(3PCAP), pcap_lookupnet(3PCAP)
diff --git a/pcap_lookupnet.3pcap b/pcap_lookupnet.3pcap
new file mode 100644 (file)
index 0000000..75c82cf
--- /dev/null
@@ -0,0 +1,65 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupnet.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPNET 3PCAP "5 April 2008"
+.SH NAME
+pcap_lookupnet \- find the IPv4 network number and netmask for a device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_lookupnet(const char *device, bpf_u_int32 *netp,
+.ti +8
+bpf_u_int32 *maskp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lookupnet()
+is used to determine the IPv4 network number and mask
+associated with the network device
+.IR device .
+Both
+.I netp
+and
+.I maskp
+are
+.I bpf_u_int32
+pointers.
+.SH RETURN VALUE
+.B pcap_lookupnet()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_loop.3pcap b/pcap_loop.3pcap
new file mode 100644 (file)
index 0000000..da30693
--- /dev/null
@@ -0,0 +1,157 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_loop.3pcap,v 1.4 2008-12-25 02:01:32 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOP 3PCAP "24 December 2008"
+.SH NAME
+pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,
+.ti +8
+                            const u_char *bytes);
+.ft
+.LP
+.ft B
+int pcap_loop(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+int pcap_dispatch(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_loop()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop()
+is called, or an error occurs.
+It does
+.B not
+return when live read timeouts occur.
+A value of \-1 or 0 for
+.I cnt
+is equivalent to infinity, so that packets are processed until another
+ending condition occurs.
+.PP
+.B pcap_dispatch()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the current bufferful of packets is
+reached when doing a live capture, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop()
+is called, or an error occurs.
+Thus, when doing a live capture,
+.I cnt
+is the maximum number of packets to process before returning, but is not
+a minimum number; when reading a live capture, only one
+bufferful of packets is read at a time, so fewer than
+.I cnt
+packets may be processed. A value of \-1 or 0 for
+.I cnt
+causes all the packets received in one buffer to be processed when
+reading a live capture, and causes all the packets in the file to be
+processed when reading a ``savefile''.
+.PP
+.ft B
+(In older versions of libpcap, the behavior when
+\fIcnt\fP
+was 0 was undefined; different platforms and devices behaved
+differently, so code that must work with older versions of libpcap
+should use \-1, nor 0, as the value of
+\fIcnt\fP.)
+.ft R
+.PP
+.I callback
+specifies a
+.I pcap_handler
+routine to be called with three arguments:
+a
+.I u_char
+pointer which is passed in the
+.I user
+argument to
+.B pcap_loop()
+or
+.BR pcap_dispatch() ,
+a
+.I const struct pcap_pkthdr
+pointer pointing to the packet time stamp and lengths, and a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet.  The
+.I struct pcap_pkthdr
+and the packet data are not to be freed by the callback routine, and are
+not guaranteed to be valid after the callback routine returns; if the
+code needs them to be valid after the callback, it must make a copy of
+them.
+.SH RETURN VALUE
+.B pcap_loop()
+returns 0 if
+.I cnt
+is exhausted, \-1 if an error occurs, or \-2 if the loop terminated due
+to a call to
+.B pcap_breakloop()
+before any packets were processed.
+It does
+.B not
+return when live read timeouts occur; instead, it attempts to read more
+packets.
+.PP
+.B pcap_dispatch()
+returns the number of packets processed on success; this can be 0 if no
+packets were read from a live capture (if, for example, they were
+discarded because they didn't pass the packet filter, or if, on
+platforms that support a read timeout that starts before any packets
+arrive, the timeout expires before any packets arrive, or if the file
+descriptor for the capture device is in non-blocking mode and no packets
+were available to be read) or if no more packets are available in a
+``savefile.''  It returns \-1 if an error occurs or \-2 if the loop
+terminated due to a call to
+.B pcap_breakloop()
+before any packets were processed.
+.ft B
+If your application uses pcap_breakloop(),
+make sure that you explicitly check for \-1 and \-2, rather than just
+checking for a return value < 0.
+.ft R
+.PP
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP)
diff --git a/pcap_major_version.3pcap b/pcap_major_version.3pcap
new file mode 100644 (file)
index 0000000..31903dc
--- /dev/null
@@ -0,0 +1,56 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_major_version.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_MAJOR_VERSION 3PCAP "5 April 2008"
+.SH NAME
+pcap_major_version, pcap_minor_version \- get the version number of a savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_major_version(pcap_t *p);
+int pcap_minor_version(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+If
+.I p
+refers to a ``savefile'',
+.B pcap_major_version()
+returns the major number of the file format of the ``savefile'' and
+.B pcap_minor_version()
+returns the minor number of the file format of the ``savefile''.  The
+version number is stored in the ``savefile''; note that the meaning of
+its values depends on the type of ``savefile'' (for example, pcap or
+pcap-NG).
+.PP
+If
+.I p
+refers to a live capture, the values returned by
+.B pcap_major_version()
+and
+.B pcap_minor_version()
+are not meaningful.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_next_ex.3pcap b/pcap_next_ex.3pcap
new file mode 100644 (file)
index 0000000..7373836
--- /dev/null
@@ -0,0 +1,107 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_next_ex.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_NEXT_EX 3PCAP "5 April 2008"
+.SH NAME
+pcap_next_ex, pcap_next \- read the next packet from a pcap_t
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
+.ti +8
+const u_char **pkt_data);
+const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_next_ex()
+reads the next packet and returns a success/failure indication.
+If the packet was read without problems, the pointer pointed to by the
+.I pkt_header
+argument is set to point to the
+.I pcap_pkthdr
+struct for the packet, and the
+pointer pointed to by the
+.I pkt_data
+argument is set to point to the data in the packet.  The
+.I struct pcap_pkthdr
+and the packet data are not to be freed by the caller, and are not
+guaranteed to be valid after the next call to
+.BR pcap_next_ex() ,
+.BR pcap_next() ,
+.BR pcap_loop() ,
+or
+.BR pcap_dispatch() ;
+if the code needs them to remain valid, it must make a copy of them.
+.PP
+.B pcap_next()
+reads the next packet (by calling
+.B pcap_dispatch()
+with a
+.I cnt
+of 1) and returns a
+.I u_char
+pointer to the data in that packet.  The
+packet data is not to be freed by the caller, and is not
+guaranteed to be valid after the next call to
+.BR pcap_next_ex() ,
+.BR pcap_next() ,
+.BR pcap_loop() ,
+or
+.BR pcap_dispatch() ;
+if the code needs it to remain valid, it must make a copy of it.
+The
+.I pcap_pkthdr
+structure pointed to by
+.I h
+is filled in with the appropriate values for the packet.
+.SH RETURN VALUE
+.B pcap_next_ex()
+returns 1 if the packet was read without problems, 0
+if packets are being read from a live capture, and the timeout expired,
+\-1 if an error occurred while reading the packet, and \-2 if
+packets are being read from a ``savefile'', and there are no more
+packets to read from the savefile.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.PP
+.B pcap_next()
+returns a pointer to the packet data on success, and returns
+.B NULL
+if an error occurred, or if no packets were read from a live
+capture (if, for example, they were discarded because they didn't pass
+the packet filter, or if, on platforms that support a read timeout that
+starts before any packets arrive, the timeout expires before any packets
+arrive, or if the file descriptor for the capture device is in
+non-blocking mode and no packets were available to be read), or if no
+more packets are available in a ``savefile.''  Unfortunately, there is
+no way to determine whether an error occurred or not.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP)
diff --git a/pcap_offline_filter.3pcap b/pcap_offline_filter.3pcap
new file mode 100644 (file)
index 0000000..596c5e4
--- /dev/null
@@ -0,0 +1,57 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_offline_filter.3pcap,v 1.1 2008-05-13 15:19:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OFFLINE_FILTER 3PCAP "13 May 2008"
+.SH NAME
+pcap_offline_filter \- check whether a filter matches a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_offline_filter(struct bpf_program *fp,
+.ti +8
+const struct pcap_pkthdr *h, const u_char *pkt)
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_offline_filter()
+checks whether a filter matches a packet.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile() .
+.I h
+points to the
+.I pcap_pkthdr
+structure for the packet, and
+.I pkt
+points to the data in the packet.
+.SH RETURN VALUE
+.B pcap_offline_filter()
+returns the return value of the filter program.  This will be zero if
+the packet doesn't match the filter and non-zero if the packet matches
+the filter.
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP)
diff --git a/pcap_open_dead.3pcap.in b/pcap_open_dead.3pcap.in
new file mode 100644 (file)
index 0000000..00df786
--- /dev/null
@@ -0,0 +1,52 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_dead.3pcap.in,v 1.1 2008-10-21 07:33:02 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_DEAD 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_dead \- open a fake pcap_t for compiling filters or opening a
+capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+is used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap.  It is
+typically used when just using libpcap for compiling BPF code.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/pcap_open_live.3pcap b/pcap_open_live.3pcap
new file mode 100644 (file)
index 0000000..0889a2a
--- /dev/null
@@ -0,0 +1,89 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_live.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_LIVE 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_live \- open a device for capturing
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_live(const char *device, int snaplen,
+.ti +8
+int promisc, int to_ms, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_live()
+is used to obtain a packet capture handle to look
+at packets on the network.
+.I device
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I device
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+.I snaplen
+specifies the snapshot length to be set on the handle.
+.PP
+.I promisc
+specifies if the interface is to be put into promiscuous mode.
+.PP
+.I to_ms
+specifies the read timeout in milliseconds.
+.SH RETURN VALUE
+.B pcap_open_live()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+may also be set to warning text when
+.B pcap_open_live()
+succeeds; to detect this case the caller should store a zero-length string in
+.I errbuf
+before calling
+.B pcap_open_live()
+and display the warning to the user if
+.I errbuf
+is no longer a zero-length string.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_open_offline.3pcap.in b/pcap_open_offline.3pcap.in
new file mode 100644 (file)
index 0000000..3f9f5a2
--- /dev/null
@@ -0,0 +1,82 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_offline.3pcap.in,v 1.1 2008-10-23 05:56:59 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_OFFLINE 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+is called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file can have the pcap file
+format as described in
+.BR pcap-savefile (@MAN_FILE_FORMATS@),
+which is the file format used by, among other programs,
+.BR tcpdump (1)
+and
+.BR tcpslice (1),
+or can have the pcap-ng file format, although not all pcap-ng files can
+be read.
+The name "-" in a synonym for
+.BR stdin .
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+to read dumped data from an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.B pcap_open_offline()
+and
+.B pcap_fopen_offline()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/pcap_set_buffer_size.3pcap b/pcap_set_buffer_size.3pcap
new file mode 100644 (file)
index 0000000..060e923
--- /dev/null
@@ -0,0 +1,47 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_buffer_size.3pcap,v 1.1 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_BUFFER_SIZE 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_buffer_size \- set the buffer size for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_buffer_size(pcap_t *p, int buffer_size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_buffer_size()
+sets the buffer size that will be used on a capture handle when
+the handle is activated to
+.IR buffer_size ,
+which is in units of bytes.
+.SH RETURN VALUE
+.B pcap_set_buffer_size()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_set_datalink.3pcap b/pcap_set_datalink.3pcap
new file mode 100644 (file)
index 0000000..9af32d0
--- /dev/null
@@ -0,0 +1,53 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_datalink.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_DATALINK 3PCAP "22 August 2010"
+.SH NAME
+pcap_set_datalink \- set the link-layer header type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_datalink(pcap_t *p, int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_datalink()
+is used to set the current link-layer header type of the pcap descriptor
+to the type specified by
+.IR dlt .
+.SH RETURN VALUE
+.B pcap_set_datalink()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP),
+pcap_datalink_name_to_val(3PCAP)
diff --git a/pcap_set_promisc.3pcap b/pcap_set_promisc.3pcap
new file mode 100644 (file)
index 0000000..382260c
--- /dev/null
@@ -0,0 +1,48 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_promisc.3pcap,v 1.1 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_PROMISC 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_promisc \- set promiscuous mode for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_promisc(pcap_t *p, int promisc);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_promisc()
+sets whether promiscuous mode should be set on a capture handle when
+the handle is activated.
+If
+.I promisc
+is non-zero, promiscuous mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_promisc()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_set_rfmon.3pcap b/pcap_set_rfmon.3pcap
new file mode 100644 (file)
index 0000000..ee73556
--- /dev/null
@@ -0,0 +1,49 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_rfmon.3pcap,v 1.1 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_RFMON 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_rfmon \- set monitor mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_rfmon(pcap_t *p, int rfmon);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_rfmon()
+sets whether monitor mode should be set on a capture handle when
+the handle is activated.
+If
+.I rfmon
+is non-zero, monitor mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_rfmon()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_can_set_rfmon(3PCAP)
diff --git a/pcap_set_snaplen.3pcap b/pcap_set_snaplen.3pcap
new file mode 100644 (file)
index 0000000..74195d9
--- /dev/null
@@ -0,0 +1,46 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_snaplen.3pcap,v 1.1 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_SNAPLEN 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_snaplen \- set the snapshot length for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_snaplen(pcap_t *p, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_snaplen()
+sets the snapshot length to be used on a capture handle when the handle
+is activated to
+.IR snaplen .
+.SH RETURN VALUE
+.B pcap_set_snaplen()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_set_timeout.3pcap b/pcap_set_timeout.3pcap
new file mode 100644 (file)
index 0000000..c361b7d
--- /dev/null
@@ -0,0 +1,47 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_timeout.3pcap,v 1.1 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TIMEOUT 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_timeout \- set the read timeout for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_timeout(pcap_t *p, int to_ms);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_timeout()
+sets the read timeout that will be used on a capture handle when
+the handle is activated to
+.IR to_ms ,
+which is in units of milliseconds.
+.SH RETURN VALUE
+.B pcap_set_timeout()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/pcap_set_tstamp_type.3pcap.in b/pcap_set_tstamp_type.3pcap.in
new file mode 100644 (file)
index 0000000..261c315
--- /dev/null
@@ -0,0 +1,65 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "21 August 2010"
+.SH NAME
+pcap_set_tstamp_type \- set the time stamp type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_type(pcap_t *p, int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_type()
+sets the the type of time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_type .
+It must be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+.B pcap_list_tstamp_types()
+will give a list of the time stamp types supported by a given capture
+device.
+See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of all the time stamp types.
+.SH RETURN VALUE
+.B pcap_set_tstamp_type()
+returns 0 on success if the specified time stamp type is expected to be
+supported by the capture device,
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+on success if the specified time stamp type is not supported by the
+capture device,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, and
+.B PCAP_ERROR_CANTSET_TSTAMP_TYPE
+if the capture device doesn't support setting the time stamp type.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_list_tstamp_types(3PCAP),
+pcap_tstamp_type_name_to_val(3PCAP),
+pcap-tstamp(@MAN_MISC_INFO@)
diff --git a/pcap_setdirection.3pcap b/pcap_setdirection.3pcap
new file mode 100644 (file)
index 0000000..bd0fb25
--- /dev/null
@@ -0,0 +1,71 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setdirection.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETDIRECTION 3PCAP "5 April 2008"
+.SH NAME
+pcap_setdirection \- set the direction for which packets will be captured
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setdirection(pcap_t *p, pcap_direction_t d);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setdirection()
+is used to specify a direction that packets will be captured.
+.I d
+is one of the constants
+.BR PCAP_D_IN ,
+.B PCAP_D_OUT
+or 
+.BR PCAP_D_INOUT .
+.B PCAP_D_IN
+will only capture packets received by the device,
+.B PCAP_D_OUT
+will only capture packets sent by the device and
+.B PCAP_D_INOUT
+will capture packets received by or sent by the device.
+.B PCAP_D_INOUT
+is the default setting if this function is not called.
+.PP
+.B pcap_setdirection()
+isn't necessarily fully supported on all platforms; some platforms might
+return an error for all values, and some other platforms might not
+support
+.BR PCAP_D_OUT .
+.PP
+This operation is not supported if a ``savefile'' is being read.
+.SH RETURN VALUE
+.B pcap_setdirection()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/pcap_setfilter.3pcap b/pcap_setfilter.3pcap
new file mode 100644 (file)
index 0000000..89d5da7
--- /dev/null
@@ -0,0 +1,54 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setfilter.3pcap,v 1.4 2008-05-13 15:19:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETFILTER 3PCAP "5 April 2008"
+.SH NAME
+pcap_setfilter \- set the filter
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setfilter()
+is used to specify a filter program.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile() .
+.SH RETURN VALUE
+.B pcap_setfilter()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP), pcap_geterr(3PCAP)
diff --git a/pcap_setnonblock.3pcap b/pcap_setnonblock.3pcap
new file mode 100644 (file)
index 0000000..b00fce1
--- /dev/null
@@ -0,0 +1,75 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setnonblock.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETNONBLOCK 3PCAP "5 April 2008"
+.SH NAME
+pcap_setnonblock, pcap_getnonblock \- set or get the state of
+non-blocking mode on a capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+int pcap_getnonblock(pcap_t *p, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setnonblock()
+puts a capture handle into ``non-blocking'' mode, or takes it out
+of ``non-blocking'' mode, depending on whether the
+.I nonblock
+argument is non-zero or zero.  It has no effect on ``savefiles''.
+If there is an error, \-1 is returned and
+.I errbuf
+is filled in with an appropriate error message; otherwise, 0 is
+returned.
+In
+``non-blocking'' mode, an attempt to read from the capture descriptor
+with
+.B pcap_dispatch()
+will, if no packets are currently available to be read, return 0
+immediately rather than blocking waiting for packets to arrive.
+.B pcap_loop()
+and
+.B pcap_next()
+will not work in ``non-blocking'' mode.
+.SH RETURN VALUE
+.B pcap_getnonblock()
+returns the current ``non-blocking'' state of the capture descriptor; it
+always returns 0 on ``savefiles''.
+If there is an error, \-1 is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.PP
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
diff --git a/pcap_snapshot.3pcap b/pcap_snapshot.3pcap
new file mode 100644 (file)
index 0000000..3025312
--- /dev/null
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_snapshot.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SNAPSHOT 3PCAP "5 April 2008"
+.SH NAME
+pcap_snapshot \- get the snapshot length
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_snapshot(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_snapshot()
+returns the snapshot length specified when
+.B pcap_set_snapshot()
+or
+.B pcap_open_live()
+was called, for a live capture, or the snapshot length from the capture
+file, for a ``savefile''.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_stats.3pcap b/pcap_stats.3pcap
new file mode 100644 (file)
index 0000000..a953e21
--- /dev/null
@@ -0,0 +1,99 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_stats.3pcap,v 1.3 2008-04-06 02:53:22 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STATS 3PCAP "7 September 2009"
+.SH NAME
+pcap_stats \- get capture statistics
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_stats(pcap_t *p, struct pcap_stat *ps);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_stats()
+fills in the
+.B struct pcap_stat
+pointed to by its second argument.  The values represent
+packet statistics from the start of the run to the time of the call.
+.PP
+.B pcap_stats()
+is supported only on live captures, not on ``savefiles''; no statistics
+are stored in ``savefiles'', so no statistics are available when reading
+from a ``savefile''.
+.PP
+A
+.B struct pcap_stat
+has the following members:
+.RS
+.TP
+.B ps_recv
+number of packets received;
+.TP
+.B ps_drop
+number of packets dropped because there was no room in the operating
+system's buffer when they arrived, because packets weren't being read
+fast enough;
+.TP
+.B ps_ifdrop
+number of packets dropped by the network interface or its driver.
+.RE
+.PP
+The statistics do not behave the same way on all platforms.
+.B ps_recv
+might count packets whether they passed any filter set with
+.BR pcap_setfilter (3PCAP)
+or not, or it might count only packets that pass the filter.
+It also might, or might not, count packets dropped because there was no
+room in the operating system's buffer when they arrived.
+.B ps_drop
+is not available on all platforms; it is zero on platforms where it's
+not available.  If packet filtering is done in libpcap, rather than in
+the operating system, it would count packets that don't pass the filter.
+Both
+.B ps_recv
+and
+.B ps_drop
+might, or might not, count packets not yet read from the operating
+system and thus not yet seen by the application.
+.B ps_ifdrop
+might, or might not, be implemented; if it's zero, that might mean that
+no packets were dropped by the interface, or it might mean that the
+statistic is unavailable, so it should not be treated as an indication
+that the interface did not drop any packets.
+.SH RETURN VALUE
+.B pcap_stats()
+returns 0 on success and returns \-1 if there is an error or if
+.I p
+doesn't support packet statistics.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/pcap_statustostr.3pcap b/pcap_statustostr.3pcap
new file mode 100644 (file)
index 0000000..da18f69
--- /dev/null
@@ -0,0 +1,43 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_statustostr.3pcap,v 1.1 2008-04-09 21:39:21 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STATUSTOSTR 3PCAP "9 April 2008"
+.SH NAME
+pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_statustostr(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_statustostr()
+converts a
+.B PCAP_ERROR_
+or
+.B PCAP_WARNING_
+value returned by a libpcap routine to an error string.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/pcap_strerror.3pcap b/pcap_strerror.3pcap
new file mode 100644 (file)
index 0000000..8e6319b
--- /dev/null
@@ -0,0 +1,42 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_strerror.3pcap,v 1.2 2008-04-05 20:26:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STRERROR 3PCAP "4 April 2008"
+.SH NAME
+pcap_strerror \- convert an errno value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_strerror(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_strerror()
+is provided in case
+.BR strerror (3)
+isn't available.  It returns an error message string corresponding to
+.IR error .
+.SH SEE ALSO
+strerror(3)
diff --git a/pcap_tstamp_type_name_to_val.3pcap b/pcap_tstamp_type_name_to_val.3pcap
new file mode 100644 (file)
index 0000000..8fcc4d7
--- /dev/null
@@ -0,0 +1,45 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "21 August 2010"
+.SH NAME
+pcap_tstamp_type_name_to_val \- get the time stamp type value
+corresponding to a time stamp type name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_tstamp_type_name_to_val(const char *name);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_tstamp_type_name_to_val()
+translates a time stamp type name to the corresponding time stamp type
+value.  The translation is case-insensitive.
+.SH RETURN VALUE
+.B pcap_tstamp_type_name_to_val()
+returns 0 on success and
+.B PCAP_ERROR
+on failure.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP)
diff --git a/pcap_tstamp_type_val_to_name.3pcap b/pcap_tstamp_type_val_to_name.3pcap
new file mode 100644 (file)
index 0000000..5d8d754
--- /dev/null
@@ -0,0 +1,45 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "21 August 2010"
+.SH NAME
+pcap_tstamp_type_val_to_name, pcap_tstamp_type_val_to_description \- get
+a name or description for a time stamp type value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_tstamp_type_val_to_name(int tstamp_type);
+const char *pcap_tstamp_type_val_to_description(int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_tstamp_type_val_to_name()
+translates a time stamp type value to the corresponding time stamp type
+name.  NULL is returned on failure.
+.PP
+.B pcap_tstamp_type_val_to_description()
+translates a time stamp type value to a short description of that time
+stamp type.  NULL is returned on failure.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_name_to_val(3PCAP)
diff --git a/ppp.h b/ppp.h
new file mode 100644 (file)
index 0000000..4e1d08d
--- /dev/null
+++ b/ppp.h
@@ -0,0 +1,58 @@
+/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.12 2005-02-08 19:52:19 guy Exp $ (LBL) */
+/*
+ * Point to Point Protocol (PPP) RFC1331
+ *
+ * Copyright 1989 by Carnegie Mellon.
+ *
+ * Permission to use, copy, modify, and distribute this program for any
+ * purpose and without fee is hereby granted, provided that this copyright
+ * and permission notice appear on all copies and supporting documentation,
+ * the name of Carnegie Mellon not be used in advertising or publicity
+ * pertaining to distribution of the program without specific prior
+ * permission, and notice be given in supporting documentation that copying
+ * and distribution is by permission of Carnegie Mellon and Stanford
+ * University.  Carnegie Mellon makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ */
+#define PPP_ADDRESS    0xff    /* The address byte value */
+#define PPP_CONTROL    0x03    /* The control byte value */
+
+#define PPP_PPPD_IN    0x00    /* non-standard for DLT_PPP_PPPD */
+#define PPP_PPPD_OUT   0x01    /* non-standard for DLT_PPP_PPPD */
+
+/* Protocol numbers */
+#define PPP_IP         0x0021  /* Raw IP */
+#define PPP_OSI                0x0023  /* OSI Network Layer */
+#define PPP_NS         0x0025  /* Xerox NS IDP */
+#define PPP_DECNET     0x0027  /* DECnet Phase IV */
+#define PPP_APPLE      0x0029  /* Appletalk */
+#define PPP_IPX                0x002b  /* Novell IPX */
+#define PPP_VJC                0x002d  /* Van Jacobson Compressed TCP/IP */
+#define PPP_VJNC       0x002f  /* Van Jacobson Uncompressed TCP/IP */
+#define PPP_BRPDU      0x0031  /* Bridging PDU */
+#define PPP_STII       0x0033  /* Stream Protocol (ST-II) */
+#define PPP_VINES      0x0035  /* Banyan Vines */
+#define PPP_IPV6       0x0057  /* Internet Protocol version 6 */
+
+#define PPP_HELLO      0x0201  /* 802.1d Hello Packets */
+#define PPP_LUXCOM     0x0231  /* Luxcom */
+#define PPP_SNS                0x0233  /* Sigma Network Systems */
+#define PPP_MPLS_UCAST  0x0281  /* rfc 3032 */
+#define PPP_MPLS_MCAST  0x0283  /* rfc 3022 */
+
+#define PPP_IPCP       0x8021  /* IP Control Protocol */
+#define PPP_OSICP      0x8023  /* OSI Network Layer Control Protocol */
+#define PPP_NSCP       0x8025  /* Xerox NS IDP Control Protocol */
+#define PPP_DECNETCP   0x8027  /* DECnet Control Protocol */
+#define PPP_APPLECP    0x8029  /* Appletalk Control Protocol */
+#define PPP_IPXCP      0x802b  /* Novell IPX Control Protocol */
+#define PPP_STIICP     0x8033  /* Strean Protocol Control Protocol */
+#define PPP_VINESCP    0x8035  /* Banyan Vines Control Protocol */
+#define PPP_IPV6CP     0x8057  /* IPv6 Control Protocol */
+#define PPP_MPLSCP      0x8281  /* rfc 3022 */
+
+#define PPP_LCP                0xc021  /* Link Control Protocol */
+#define PPP_PAP                0xc023  /* Password Authentication Protocol */
+#define PPP_LQM                0xc025  /* Link Quality Monitoring */
+#define PPP_CHAP       0xc223  /* Challenge Handshake Authentication Protocol */
diff --git a/runlex.sh b/runlex.sh
new file mode 100755 (executable)
index 0000000..74f2161
--- /dev/null
+++ b/runlex.sh
@@ -0,0 +1,235 @@
+#! /bin/sh
+
+#
+# runlex.sh
+# Script to run Lex/Flex.
+# First argument is the (quoted) name of the command; if it's null, that
+# means that neither Flex nor Lex was found, so we report an error and
+# quit.
+#
+# @(#) $Header: /tcpdump/master/libpcap/runlex.sh,v 1.4 2007-12-31 03:38:39 guy Exp $
+#
+
+#
+# Get the name of the command to run, and then shift to get the arguments.
+#
+if [ $# -eq 0 ]
+then
+       echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
+       exit 1
+fi
+LEX="$1"
+shift
+
+#
+# Check whether we have Lex or Flex.
+#
+if [ -z "${LEX}" ]
+then
+       echo "Neither lex nor flex was found" 1>&2
+       exit 1
+fi
+
+#
+# Process the flags.  We don't use getopt because we don't want to
+# embed complete knowledge of what options are supported by Lex/Flex.
+#
+flags=""
+outfile=lex.yy.c
+while [ $# -ne 0 ]
+do
+       case "$1" in
+
+       -o*)
+               #
+               # Set the output file name.
+               #
+               outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
+               ;;
+
+       -*)
+               #
+               # Add this to the list of flags.
+               #
+               flags="$flags $1"
+               ;;
+
+       --|*)
+               #
+               # End of flags.
+               #
+               break
+               ;;
+       esac
+       shift
+done
+
+#
+# Is it Lex, or is it Flex?
+#
+if [ "${LEX}" = flex ]
+then
+       #
+       # It's Flex.
+       #
+       have_flex=yes
+
+       #
+       # Does it support the --noFUNCTION options?  If so, we pass
+       # --nounput, as at least some versions that support those
+       # options don't support disabling yyunput by defining
+       # YY_NO_UNPUT.
+       #
+       if flex --help | egrep noFUNCTION >/dev/null
+       then
+               flags="$flags --nounput"
+
+               #
+               # Does it support -R, for generating reentrant scanners?
+               # If so, we're not currently using that feature, but
+               # it'll generate some unused functions anyway - and there
+               # won't be any header file declaring them, so there'll be
+               # defined-but-not-declared warnings.  Therefore, we use
+               # --noFUNCTION options to suppress generating those
+               # functions.
+               #
+               if flex --help | egrep reentrant >/dev/null
+               then
+                       flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
+               fi
+       fi
+else
+       #
+       # It's Lex.
+       #
+       have_flex=no
+fi
+
+#
+# OK, run it.
+# If it's lex, it doesn't support -o, so we just write to
+# lex.yy.c and, if it succeeds, rename it to the right name,
+# otherwise we remove lex.yy.c.
+# If it's flex, it supports -o, so we use that - flex with -P doesn't
+# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
+#
+if [ $have_flex = yes ]
+then
+       ${LEX} $flags -o"$outfile" "$@"
+
+       #
+       # Did it succeed?
+       #
+       status=$?
+       if [ $status -ne 0 ]
+       then
+               #
+               # No.  Exit with the failing exit status.
+               #
+               exit $status
+       fi
+
+       #
+       # Flex has the annoying habit of stripping all but the last
+       # component of the "-o" flag argument and using that as the
+       # place to put the output.  This gets in the way of building
+       # in a directory different from the source directory.  Try
+       # to work around this.
+       #
+       # Is the outfile where we think it is?
+       #
+       outfile_base=`basename "$outfile"`
+       if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
+       then
+               #
+               # No, it's not, but it is in the current directory.  Put it
+               # where it's supposed to be.
+               #
+               mv "$outfile_base" "$outfile"
+
+               #
+               # Did that succeed?
+               #
+               status=$?
+               if [ $status -ne 0 ]
+               then
+                       #
+                       # No.  Exit with the failing exit status.
+                       #
+                       exit $status
+               fi
+       fi
+else
+       ${LEX} $flags "$@"
+
+       #
+       # Did it succeed?
+       #
+       status=$?
+       if [ $status -ne 0 ]
+       then
+               #
+               # No.  Get rid of any lex.yy.c file we generated, and
+               # exit with the failing exit status.
+               #
+               rm -f lex.yy.c
+               exit $status
+       fi
+
+       #
+       # OK, rename lex.yy.c to the right output file.
+       #
+       mv lex.yy.c "$outfile" 
+
+       #
+       # Did that succeed?
+       #
+       status=$?
+       if [ $status -ne 0 ]
+       then
+               #
+               # No.  Get rid of any lex.yy.c file we generated, and
+               # exit with the failing exit status.
+               #
+               rm -f lex.yy.c
+               exit $status
+       fi
+fi
+
+#
+# OK, now let's generate a header file declaring the relevant functions
+# defined by the .c file; if the .c file is .../foo.c, the header file
+# will be .../foo.h.
+#
+# This works around some other Flex suckage, wherein it doesn't declare
+# the lex routine before defining it, causing compiler warnings.
+# XXX - newer versions of Flex support --header-file=, to generate the
+# appropriate header file.  With those versions, we should use that option.
+#
+
+#
+# Get the name of the prefix; scan the source files for a %option prefix
+# line.  We use the last one.
+#
+prefix=`sed -n 's/%option[     ][      ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
+if [ ! -z "$prefix" ]
+then
+       prefixline="#define yylex ${prefix}lex"
+fi
+
+#
+# Construct the name of the header file.
+#
+header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
+
+#
+# Spew out the declaration.
+#
+cat <<EOF >$header_file
+/* This is generated by runlex.sh.  Do not edit it. */
+$prefixline
+#ifndef YY_DECL
+#define YY_DECL int yylex(void)
+#endif  
+YY_DECL;
+EOF
diff --git a/savefile.c b/savefile.c
new file mode 100644 (file)
index 0000000..8115749
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * savefile.c - supports offline use of tcpdump
+ *     Extraction/creation by Jeffrey Mogul, DECWRL
+ *     Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.183 2008-12-23 20:13:29 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+#include "pcap/usb.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcap.h"
+#include "sf-pcap-ng.h"
+
+/*
+ * Setting O_BINARY on DOS/Windows is a bit tricky
+ */
+#if defined(WIN32)
+  #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
+#elif defined(MSDOS)
+  #if defined(__HIGHC__)
+  #define SET_BINMODE(f)  setmode(f, O_BINARY)
+  #else
+  #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
+  #endif
+#endif
+
+static int
+sf_getnonblock(pcap_t *p, char *errbuf)
+{
+       /*
+        * This is a savefile, not a live capture file, so never say
+        * it's in non-blocking mode.
+        */
+       return (0);
+}
+
+static int
+sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+       /*
+        * This is a savefile, not a live capture file, so reject
+        * requests to put it in non-blocking mode.  (If it's a
+        * pipe, it could be put in non-blocking mode, but that
+        * would significantly complicate the code to read packets,
+        * as it would have to handle reading partial packets and
+        * keeping the state of the read.)
+        */
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Savefiles cannot be put into non-blocking mode");
+       return (-1);
+}
+
+static int
+sf_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Statistics aren't available from savefiles");
+       return (-1);
+}
+
+#ifdef WIN32
+static int
+sf_setbuff(pcap_t *p, int dim)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The kernel buffer size cannot be set while reading from a file");
+       return (-1);
+}
+
+static int
+sf_setmode(pcap_t *p, int mode)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "impossible to set mode while reading from a file");
+       return (-1);
+}
+
+static int
+sf_setmintocopy(pcap_t *p, int size)
+{
+       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The mintocopy parameter cannot be set while reading from a file");
+       return (-1);
+}
+#endif
+
+static int
+sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+       strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+           PCAP_ERRBUF_SIZE);
+       return (-1);
+}
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+static int
+sf_setdirection(pcap_t *p, pcap_direction_t d)
+{
+       snprintf(p->errbuf, sizeof(p->errbuf),
+           "Setting direction is not supported on savefiles");
+       return (-1);
+}
+
+static void
+sf_cleanup(pcap_t *p)
+{
+       if (p->sf.rfile != stdin)
+               (void)fclose(p->sf.rfile);
+       if (p->buffer != NULL)
+               free(p->buffer);
+       pcap_freecode(&p->fcode);
+}
+
+pcap_t *
+pcap_open_offline(const char *fname, char *errbuf)
+{
+       FILE *fp;
+       pcap_t *p;
+
+       if (fname[0] == '-' && fname[1] == '\0')
+       {
+               fp = stdin;
+#if defined(WIN32) || defined(MSDOS)
+               /*
+                * We're reading from the standard input, so put it in binary
+                * mode, as savefiles are binary files.
+                */
+               SET_BINMODE(fp);
+#endif
+       }
+       else {
+#if !defined(WIN32) && !defined(MSDOS)
+               fp = fopen(fname, "r");
+#else
+               fp = fopen(fname, "rb");
+#endif
+               if (fp == NULL) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+                           pcap_strerror(errno));
+                       return (NULL);
+               }
+       }
+       p = pcap_fopen_offline(fp, errbuf);
+       if (p == NULL) {
+               if (fp != stdin)
+                       fclose(fp);
+       }
+       return (p);
+}
+
+#ifdef WIN32
+pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
+{
+       int fd;
+       FILE *file;
+
+       fd = _open_osfhandle(osfd, _O_RDONLY);
+       if ( fd < 0 ) 
+       {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+               return NULL;
+       }
+
+       file = _fdopen(fd, "rb");
+       if ( file == NULL ) 
+       {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+               return NULL;
+       }
+
+       return pcap_fopen_offline(file, errbuf);
+}
+#endif
+
+static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
+       pcap_check_header,
+       pcap_ng_check_header
+};
+
+#define        N_FILE_TYPES    (sizeof check_headers / sizeof check_headers[0])
+
+#ifdef WIN32
+static
+#endif
+pcap_t *
+pcap_fopen_offline(FILE *fp, char *errbuf)
+{
+       register pcap_t *p;
+       bpf_u_int32 magic;
+       size_t amt_read;
+       u_int i;
+
+       p = pcap_create_common("(savefile)", errbuf);
+       if (p == NULL)
+               return (NULL);
+
+       /*
+        * Read the first 4 bytes of the file; the network analyzer dump
+        * file formats we support (pcap and pcap-ng), and several other
+        * formats we might support in the future (such as snoop, DOS and
+        * Windows Sniffer, and Microsoft Network Monitor) all have magic
+        * numbers that are unique in their first 4 bytes.
+        */
+       amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
+       if (amt_read != sizeof(magic)) {
+               if (ferror(fp)) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+               } else {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated dump file; tried to read %lu file header bytes, only got %lu",
+                           (unsigned long)sizeof(magic),
+                           (unsigned long)amt_read);
+               }
+               goto bad;
+       }
+
+       /*
+        * Try all file types.
+        */
+       for (i = 0; i < N_FILE_TYPES; i++) {
+               switch ((*check_headers[i])(p, magic, fp, errbuf)) {
+
+               case -1:
+                       /*
+                        * Error trying to read the header.
+                        */
+                       goto bad;
+
+               case 1:
+                       /*
+                        * Yup, that's it.
+                        */
+                       goto found;
+               }
+       }
+
+       /*
+        * Well, who knows what this mess is....
+        */
+       snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
+       goto bad;
+
+found:
+       p->sf.rfile = fp;
+
+#ifdef PCAP_FDDIPAD
+       /* Padding only needed for live capture fcode */
+       p->fddipad = 0;
+#endif
+
+#if !defined(WIN32) && !defined(MSDOS)
+       /*
+        * You can do "select()" and "poll()" on plain files on most
+        * platforms, and should be able to do so on pipes.
+        *
+        * You can't do "select()" on anything other than sockets in
+        * Windows, so, on Win32 systems, we don't have "selectable_fd".
+        */
+       p->selectable_fd = fileno(fp);
+#endif
+
+       p->read_op = pcap_offline_read;
+       p->inject_op = sf_inject;
+       p->setfilter_op = install_bpf_program;
+       p->setdirection_op = sf_setdirection;
+       p->set_datalink_op = NULL;      /* we don't support munging link-layer headers */
+       p->getnonblock_op = sf_getnonblock;
+       p->setnonblock_op = sf_setnonblock;
+       p->stats_op = sf_stats;
+#ifdef WIN32
+       p->setbuff_op = sf_setbuff;
+       p->setmode_op = sf_setmode;
+       p->setmintocopy_op = sf_setmintocopy;
+#endif
+       p->cleanup_op = sf_cleanup;
+       p->activated = 1;
+
+       return (p);
+ bad:
+       free(p);
+       return (NULL);
+}
+
+/*
+ * Read packets from a capture file, and call the callback for each
+ * packet.
+ * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
+ */
+int
+pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       struct bpf_insn *fcode;
+       int status = 0;
+       int n = 0;
+       u_char *data;
+
+       while (status == 0) {
+               struct pcap_pkthdr h;
+
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return -2 to indicate
+                * that we were told to break out of the loop, otherwise
+                * leave the flag set, so that the *next* call will break
+                * out of the loop without having read any packets, and
+                * return the number of packets we've processed so far.
+                */
+               if (p->break_loop) {
+                       if (n == 0) {
+                               p->break_loop = 0;
+                               return (-2);
+                       } else
+                               return (n);
+               }
+
+               status = p->sf.next_packet_op(p, &h, &data);
+               if (status) {
+                       if (status == 1)
+                               return (0);
+                       return (status);
+               }
+
+               if ((fcode = p->fcode.bf_insns) == NULL ||
+                   bpf_filter(fcode, data, h.len, h.caplen)) {
+                       (*callback)(user, &h, data);
+                       if (++n >= cnt && cnt > 0)
+                               break;
+               }
+       }
+       /*XXX this breaks semantics tcpslice expects */
+       return (n);
+}
diff --git a/scanner.l b/scanner.l
new file mode 100644 (file)
index 0000000..064e9c8
--- /dev/null
+++ b/scanner.l
@@ -0,0 +1,466 @@
+%{
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.112 2008-02-06 10:21:30 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#ifdef INET6
+#ifdef WIN32
+#include <pcap-stdinc.h>
+
+#ifdef __MINGW32__
+#include "ip6_misc.h"
+#endif
+#else /* WIN32 */
+#include <sys/socket.h>        /* for "struct sockaddr" in "struct addrinfo" */
+#include <netdb.h>     /* for "struct addrinfo" */
+#endif /* WIN32 */
+
+/* Workaround for AIX 4.3 */
+#if !defined(AI_NUMERICHOST)
+#define AI_NUMERICHOST 0x04
+#endif
+#endif /*INET6*/
+#include <pcap/namedb.h>
+#include "tokdefs.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static int stoi(char *);
+static inline int xdtoi(int);
+
+#ifdef FLEX_SCANNER
+#define YY_NO_INPUT
+#define YY_NO_UNPUT
+static YY_BUFFER_STATE in_buffer;
+#else
+static const char *in_buffer;
+
+#undef getc
+#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
+#endif
+
+#define yylval pcap_lval
+extern YYSTYPE yylval;
+
+%}
+
+N              ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B              ([0-9A-Fa-f][0-9A-Fa-f]?)
+B2             ([0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])
+W              ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?)
+
+%a 18400
+%o 21500
+%e 7600
+%k 4550
+%p 27600
+%n 2000
+
+V680           {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W}
+
+V670           ::{W}:{W}:{W}:{W}:{W}:{W}:{W}
+V671           {W}::{W}:{W}:{W}:{W}:{W}:{W}
+V672           {W}:{W}::{W}:{W}:{W}:{W}:{W}
+V673           {W}:{W}:{W}::{W}:{W}:{W}:{W}
+V674           {W}:{W}:{W}:{W}::{W}:{W}:{W}
+V675           {W}:{W}:{W}:{W}:{W}::{W}:{W}
+V676           {W}:{W}:{W}:{W}:{W}:{W}::{W}
+V677           {W}:{W}:{W}:{W}:{W}:{W}:{W}::
+
+V660           ::{W}:{W}:{W}:{W}:{W}:{W}
+V661           {W}::{W}:{W}:{W}:{W}:{W}
+V662           {W}:{W}::{W}:{W}:{W}:{W}
+V663           {W}:{W}:{W}::{W}:{W}:{W}
+V664           {W}:{W}:{W}:{W}::{W}:{W}
+V665           {W}:{W}:{W}:{W}:{W}::{W}
+V666           {W}:{W}:{W}:{W}:{W}:{W}::
+
+V650           ::{W}:{W}:{W}:{W}:{W}
+V651           {W}::{W}:{W}:{W}:{W}
+V652           {W}:{W}::{W}:{W}:{W}
+V653           {W}:{W}:{W}::{W}:{W}
+V654           {W}:{W}:{W}:{W}::{W}
+V655           {W}:{W}:{W}:{W}:{W}::
+
+V640           ::{W}:{W}:{W}:{W}
+V641           {W}::{W}:{W}:{W}
+V642           {W}:{W}::{W}:{W}
+V643           {W}:{W}:{W}::{W}
+V644           {W}:{W}:{W}:{W}::
+
+V630           ::{W}:{W}:{W}
+V631           {W}::{W}:{W}
+V632           {W}:{W}::{W}
+V633           {W}:{W}:{W}::
+
+V620           ::{W}:{W}
+V621           {W}::{W}
+V622           {W}:{W}::
+
+V610           ::{W}
+V611           {W}::
+
+V600           ::
+
+V6604          {W}:{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+
+V6504          ::{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6514          {W}::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6524          {W}:{W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6534          {W}:{W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6544          {W}:{W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6554          {W}:{W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6404          ::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6414          {W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6424          {W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6434          {W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6444          {W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6304          ::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6314          {W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6324          {W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6334          {W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6204          ::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6214          {W}::{W}:{N}\.{N}\.{N}\.{N}
+V6224          {W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6104          ::{W}:{N}\.{N}\.{N}\.{N}
+V6114          {W}::{N}\.{N}\.{N}\.{N}
+
+V6004          ::{N}\.{N}\.{N}\.{N}
+
+
+V6             ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004})
+
+MAC            ({B}:{B}:{B}:{B}:{B}:{B}|{B}\-{B}\-{B}\-{B}\-{B}\-{B}|{B}\.{B}\.{B}\.{B}\.{B}\.{B}|{B2}\.{B2}\.{B2}|{B2}{3})
+
+
+
+%%
+dst            return DST;
+src            return SRC;
+
+link|ether|ppp|slip  return LINK;
+fddi|tr|wlan   return LINK;
+arp            return ARP;
+rarp           return RARP;
+ip             return IP;
+sctp           return SCTP;
+tcp            return TCP;
+udp            return UDP;
+icmp           return ICMP;
+igmp           return IGMP;
+igrp           return IGRP;
+pim            return PIM;
+vrrp           return VRRP;
+carp           return CARP;
+radio          return RADIO;
+
+ip6            {
+#ifdef INET6
+               return IPV6;
+#else
+               bpf_error("%s not supported", yytext);
+#endif
+               }
+icmp6          {
+#ifdef INET6
+               return ICMPV6;
+#else
+               bpf_error("%s not supported", yytext);
+#endif
+               }
+ah             return AH;
+esp            return ESP;
+
+atalk          return ATALK;
+aarp           return AARP;
+decnet         return DECNET;
+lat            return LAT;
+sca            return SCA;
+moprc          return MOPRC;
+mopdl          return MOPDL;
+
+iso            return ISO;
+esis           return ESIS;
+es-is          return ESIS;
+isis           return ISIS;
+is-is          return ISIS;
+l1              return L1;
+l2              return L2;
+iih             return IIH;
+lsp             return LSP;
+snp             return SNP;
+csnp            return CSNP;
+psnp            return PSNP;
+
+clnp           return CLNP;
+
+stp            return STP;
+
+ipx            return IPX;
+
+netbeui                return NETBEUI;
+
+host           return HOST;
+net            return NET;
+mask           return NETMASK;
+port           return PORT;
+portrange      return PORTRANGE;
+proto          return PROTO;
+protochain     {
+#ifdef NO_PROTOCHAIN
+                 bpf_error("%s not supported", yytext);
+#else
+                 return PROTOCHAIN;
+#endif
+               }
+
+gateway                return GATEWAY;
+
+type           return TYPE;
+subtype                return SUBTYPE;
+direction|dir  return DIR;
+address1|addr1 return ADDR1;
+address2|addr2 return ADDR2;
+address3|addr3 return ADDR3;
+address4|addr4 return ADDR4;
+ra             return RA;
+ta             return TA;
+
+less           return LESS;
+greater                return GREATER;
+byte           return CBYTE;
+broadcast      return TK_BROADCAST;
+multicast      return TK_MULTICAST;
+
+and|"&&"       return AND;
+or|"||"                return OR;
+not            return '!';
+
+len|length     return LEN;
+inbound                return INBOUND;
+outbound       return OUTBOUND;
+
+vlan           return VLAN;
+mpls           return MPLS;
+pppoed         return PPPOED;
+pppoes         return PPPOES;
+
+lane           return LANE;
+llc            return LLC;
+metac          return METAC;
+bcc            return BCC;
+oam            return OAM;
+oamf4          return OAMF4;
+oamf4ec                return OAMF4EC;
+oamf4sc                return OAMF4SC;
+sc             return SC;
+ilmic          return ILMIC;
+vpi            return VPI;
+vci            return VCI;
+connectmsg     return CONNECTMSG;
+metaconnect    return METACONNECT;
+
+on|ifname      return PF_IFNAME;
+rset|ruleset   return PF_RSET;
+rnr|rulenum    return PF_RNR;
+srnr|subrulenum        return PF_SRNR;
+reason         return PF_REASON;
+action         return PF_ACTION;
+
+fisu           return FISU;
+lssu           return LSSU;
+lsu            return LSSU;
+msu            return MSU;
+sio            return SIO;
+opc            return OPC;
+dpc            return DPC;
+sls            return SLS;
+
+[ \r\n\t]              ;
+[+\-*/:\[\]!<>()&|=]   return yytext[0];
+">="                   return GEQ;
+"<="                   return LEQ;
+"!="                   return NEQ;
+"=="                   return '=';
+"<<"                   return LSH;
+">>"                   return RSH;
+${B}                   { yylval.e = pcap_ether_aton(((char *)yytext)+1);
+                         return AID; }
+{MAC}                  { yylval.e = pcap_ether_aton((char *)yytext);
+                         return EID; }
+{N}                    { yylval.i = stoi((char *)yytext); return NUM; }
+({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})        {
+                       yylval.s = sdup((char *)yytext); return HID; }
+{V6}                   {
+#ifdef INET6
+                         struct addrinfo hints, *res;
+                         memset(&hints, 0, sizeof(hints));
+                         hints.ai_family = AF_INET6;
+                         hints.ai_flags = AI_NUMERICHOST;
+                         if (getaddrinfo(yytext, NULL, &hints, &res))
+                               bpf_error("bogus IPv6 address %s", yytext);
+                         else {
+                               freeaddrinfo(res);
+                               yylval.s = sdup((char *)yytext); return HID6;
+                         }
+#else
+                         bpf_error("IPv6 address %s not supported", yytext);
+#endif /*INET6*/
+                       }
+{B}:+({B}:+)+          { bpf_error("bogus ethernet address %s", yytext); }
+icmptype               { yylval.i = 0; return NUM; }
+icmpcode               { yylval.i = 1; return NUM; }
+icmp-echoreply         { yylval.i = 0; return NUM; }
+icmp-unreach           { yylval.i = 3; return NUM; }
+icmp-sourcequench      { yylval.i = 4; return NUM; }
+icmp-redirect          { yylval.i = 5; return NUM; }
+icmp-echo              { yylval.i = 8; return NUM; }
+icmp-routeradvert      { yylval.i = 9; return NUM; }
+icmp-routersolicit     { yylval.i = 10; return NUM; }
+icmp-timxceed          { yylval.i = 11; return NUM; }
+icmp-paramprob         { yylval.i = 12; return NUM; }
+icmp-tstamp            { yylval.i = 13; return NUM; }
+icmp-tstampreply       { yylval.i = 14; return NUM; }
+icmp-ireq              { yylval.i = 15; return NUM; }
+icmp-ireqreply         { yylval.i = 16; return NUM; }
+icmp-maskreq           { yylval.i = 17; return NUM; }
+icmp-maskreply         { yylval.i = 18; return NUM; }
+tcpflags               { yylval.i = 13; return NUM; }
+tcp-fin                        { yylval.i = 0x01; return NUM; }
+tcp-syn                        { yylval.i = 0x02; return NUM; }
+tcp-rst                        { yylval.i = 0x04; return NUM; }
+tcp-push               { yylval.i = 0x08; return NUM; }
+tcp-ack                        { yylval.i = 0x10; return NUM; }
+tcp-urg                        { yylval.i = 0x20; return NUM; }
+[A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
+                        yylval.s = sdup((char *)yytext); return ID; }
+"\\"[^ !()\n\t]+       { yylval.s = sdup((char *)yytext + 1); return ID; }
+[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
+                       bpf_error("illegal token: %s", yytext); }
+.                      { bpf_error("illegal char '%c'", *yytext); }
+%%
+void
+lex_init(buf)
+       const char *buf;
+{
+#ifdef FLEX_SCANNER
+       in_buffer = yy_scan_string(buf);
+#else
+       in_buffer = buf;
+#endif
+}
+
+/*
+ * Do any cleanup necessary after parsing.
+ */
+void
+lex_cleanup()
+{
+#ifdef FLEX_SCANNER
+       if (in_buffer != NULL)
+               yy_delete_buffer(in_buffer);
+       in_buffer = NULL;
+#endif
+}
+
+/*
+ * Also define a yywrap.  Note that if we're using flex, it will
+ * define a macro to map this identifier to pcap_wrap.
+ */
+int
+yywrap()
+{
+       return 1;
+}
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+/*
+ * Convert string to integer.  Just like atoi(), but checks for
+ * preceding 0x or 0 and uses hex or octal instead of decimal.
+ */
+static int
+stoi(s)
+       char *s;
+{
+       int base = 10;
+       int n = 0;
+
+       if (*s == '0') {
+               if (s[1] == 'x' || s[1] == 'X') {
+                       s += 2;
+                       base = 16;
+               }
+               else {
+                       base = 8;
+                       s += 1;
+               }
+       }
+       while (*s)
+               n = n * base + xdtoi(*s++);
+
+       return n;
+}
diff --git a/sf-pcap-ng.c b/sf-pcap-ng.c
new file mode 100644 (file)
index 0000000..7eb6db7
--- /dev/null
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap-ng.c - pcap-ng-file-format-specific code from savefile.c
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header$ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "pcap-common.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcap-ng.h"
+
+/*
+ * Block types.
+ */
+
+/*
+ * Common part at the beginning of all blocks.
+ */
+struct block_header {
+       bpf_u_int32     block_type;
+       bpf_u_int32     total_length;
+};
+
+/*
+ * Common trailer at the end of all blocks.
+ */
+struct block_trailer {
+       bpf_u_int32     total_length;
+};
+
+/*
+ * Common options.
+ */
+#define OPT_ENDOFOPT   0       /* end of options */
+#define OPT_COMMENT    1       /* comment string */
+
+/*
+ * Option header.
+ */
+struct option_header {
+       u_short         option_code;
+       u_short         option_length;
+};
+
+/*
+ * Structures for the part of each block type following the common
+ * part.
+ */
+
+/*
+ * Section Header Block.
+ */
+#define BT_SHB                 0x0A0D0D0A
+
+struct section_header_block {
+       bpf_u_int32     byte_order_magic;
+       u_short         major_version;
+       u_short         minor_version;
+       u_int64_t       section_length;
+       /* followed by options and trailer */
+};
+
+/*
+ * Byte-order magic value.
+ */
+#define BYTE_ORDER_MAGIC       0x1A2B3C4D
+
+/*
+ * Current version number.  If major_version isn't PCAP_NG_VERSION_MAJOR,
+ * that means that this code can't read the file.
+ */
+#define PCAP_NG_VERSION_MAJOR  1
+
+/*
+ * Interface Description Block.
+ */
+#define BT_IDB                 0x00000001
+
+struct interface_description_block {
+       u_short         linktype;
+       u_short         reserved;
+       bpf_u_int32     snaplen;
+       /* followed by options and trailer */
+};
+
+/*
+ * Options in the IDB.
+ */
+#define IF_NAME                2       /* interface name string */
+#define IF_DESCRIPTION 3       /* interface description string */
+#define IF_IPV4ADDR    4       /* interface's IPv4 address and netmask */
+#define IF_IPV6ADDR    5       /* interface's IPv6 address and prefix length */
+#define IF_MACADDR     6       /* interface's MAC address */
+#define IF_EUIADDR     7       /* interface's EUI address */
+#define IF_SPEED       8       /* interface's speed, in bits/s */
+#define IF_TSRESOL     9       /* interface's time stamp resolution */
+#define IF_TZONE       10      /* interface's time zone */
+#define IF_FILTER      11      /* filter used when capturing on interface */
+#define IF_OS          12      /* string OS on which capture on this interface was done */
+#define IF_FCSLEN      13      /* FCS length for this interface */
+#define IF_TSOFFSET    14      /* time stamp offset for this interface */
+
+/*
+ * Enhanced Packet Block.
+ */
+#define BT_EPB                 0x00000006
+
+struct enhanced_packet_block {
+       bpf_u_int32     interface_id;
+       bpf_u_int32     timestamp_high;
+       bpf_u_int32     timestamp_low;
+       bpf_u_int32     caplen;
+       bpf_u_int32     len;
+       /* followed by packet data, options, and trailer */
+};
+
+/*
+ * Simple Packet Block.
+ */
+#define BT_SPB                 0x00000003
+
+struct simple_packet_block {
+       bpf_u_int32     len;
+       /* followed by packet data and trailer */
+};
+
+/*
+ * Packet Block.
+ */
+#define BT_PB                  0x00000002
+
+struct packet_block {
+       u_short         interface_id;
+       u_short         drops_count;
+       bpf_u_int32     timestamp_high;
+       bpf_u_int32     timestamp_low;
+       bpf_u_int32     caplen;
+       bpf_u_int32     len;
+       /* followed by packet data, options, and trailer */
+};
+
+/*
+ * Block cursor - used when processing the contents of a block.
+ * Contains a pointer into the data being processed and a count
+ * of bytes remaining in the block.
+ */
+struct block_cursor {
+       u_char          *data;
+       size_t          data_remaining;
+       bpf_u_int32     block_type;
+};
+
+static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
+    u_char **data);
+
+static int
+read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
+    char *errbuf)
+{
+       size_t amt_read;
+
+       amt_read = fread(buf, 1, bytes_to_read, fp);
+       if (amt_read != bytes_to_read) {
+               if (ferror(fp)) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+               } else {
+                       if (amt_read == 0 && !fail_on_eof)
+                               return (0);     /* EOF */
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated dump file; tried to read %lu bytes, only got %lu",
+                           (unsigned long)bytes_to_read,
+                           (unsigned long)amt_read);
+               }
+               return (-1);
+       }
+       return (1);
+}
+
+static int
+read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
+{
+       int status;
+       struct block_header bhdr;
+
+       status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
+       if (status <= 0)
+               return (status);        /* error or EOF */
+
+       if (p->sf.swapped) {
+               bhdr.block_type = SWAPLONG(bhdr.block_type);
+               bhdr.total_length = SWAPLONG(bhdr.total_length);
+       }
+
+       /*
+        * Is this block "too big"?
+        *
+        * We choose 16MB as "too big", for now, so that we handle
+        * "reasonably" large buffers but don't chew up all the
+        * memory if we read a malformed file.
+        */
+       if (bhdr.total_length > 16*1024*1024) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "pcap-ng block size %u > maximum %u",
+                   bhdr.total_length, 16*1024*1024);
+                   return (-1);
+       }
+
+       /*
+        * Is this block "too small" - i.e., is it shorter than a block
+        * header plus a block trailer?
+        */
+       if (bhdr.total_length < sizeof(struct block_header) +
+           sizeof(struct block_trailer)) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block in pcap-ng dump file has a length of %u < %lu",
+                   bhdr.total_length,
+                   (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
+               return (-1);
+       }
+
+       /*
+        * Is the buffer big enough?
+        */
+       if (p->bufsize < bhdr.total_length) {
+               /*
+                * No - make it big enough.
+                */
+               p->buffer = realloc(p->buffer, bhdr.total_length);
+               if (p->buffer == NULL) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+                       return (-1);
+               }
+       }
+
+       /*
+        * Copy the stuff we've read to the buffer, and read the rest
+        * of the block.
+        */
+       memcpy(p->buffer, &bhdr, sizeof(bhdr));
+       if (read_bytes(fp, p->buffer + sizeof(bhdr),
+           bhdr.total_length - sizeof(bhdr), 1, errbuf) == -1)
+               return (-1);
+
+       /*
+        * Initialize the cursor.
+        */
+       cursor->data = p->buffer + sizeof(bhdr);
+       cursor->data_remaining = bhdr.total_length - sizeof(bhdr) -
+           sizeof(struct block_trailer);
+       cursor->block_type = bhdr.block_type;
+       return (1);
+}
+
+static void *
+get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
+    char *errbuf)
+{
+       void *data;
+
+       /*
+        * Make sure we have the specified amount of data remaining in
+        * the block data.
+        */
+       if (cursor->data_remaining < chunk_size) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block of type %u in pcap-ng dump file is too short",
+                   cursor->block_type);
+               return (NULL);
+       }
+
+       /*
+        * Return the current pointer, and skip past the chunk.
+        */
+       data = cursor->data;
+       cursor->data += chunk_size;
+       cursor->data_remaining -= chunk_size;
+       return (data);
+}
+
+static struct option_header *
+get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
+{
+       struct option_header *opthdr;
+
+       opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
+       if (opthdr == NULL) {
+               /*
+                * Option header is cut short.
+                */
+               return (NULL);
+       }
+
+       /*
+        * Byte-swap it if necessary.
+        */
+       if (p->sf.swapped) {
+               opthdr->option_code = SWAPSHORT(opthdr->option_code);
+               opthdr->option_length = SWAPSHORT(opthdr->option_length);
+       }
+
+       return (opthdr);
+}
+
+static void *
+get_optvalue_from_block_data(struct block_cursor *cursor,
+    struct option_header *opthdr, char *errbuf)
+{
+       size_t padded_option_len;
+       void *optvalue;
+
+       /* Pad option length to 4-byte boundary */
+       padded_option_len = opthdr->option_length;
+       padded_option_len = ((padded_option_len + 3)/4)*4;
+
+       optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
+       if (optvalue == NULL) {
+               /*
+                * Option value is cut short.
+                */
+               return (NULL);
+       }
+
+       return (optvalue);
+}
+
+static int
+process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
+    u_int64_t *tsoffset, char *errbuf)
+{
+       struct option_header *opthdr;
+       void *optvalue;
+       int saw_tsresol, saw_tsoffset;
+       u_char tsresol_opt;
+       u_int i;
+
+       saw_tsresol = 0;
+       saw_tsoffset = 0;
+       while (cursor->data_remaining != 0) {
+               /*
+                * Get the option header.
+                */
+               opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
+               if (opthdr == NULL) {
+                       /*
+                        * Option header is cut short.
+                        */
+                       return (-1);
+               }
+
+               /*
+                * Get option value.
+                */
+               optvalue = get_optvalue_from_block_data(cursor, opthdr,
+                   errbuf);
+               if (optvalue == NULL) {
+                       /*
+                        * Option value is cut short.
+                        */
+                       return (-1);
+               }
+
+               switch (opthdr->option_code) {
+
+               case OPT_ENDOFOPT:
+                       if (opthdr->option_length != 0) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Interface Description Block has opt_endofopt option with length %u != 0",
+                                   opthdr->option_length);
+                               return (-1);
+                       }
+                       goto done;
+
+               case IF_TSRESOL:
+                       if (opthdr->option_length != 1) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Interface Description Block has if_tsresol option with length %u != 1",
+                                   opthdr->option_length);
+                               return (-1);
+                       }
+                       if (saw_tsresol) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Interface Description Block has more than one if_tsresol option");
+                               return (-1);
+                       }
+                       saw_tsresol = 1;
+                       tsresol_opt = *(u_int *)optvalue;
+                       if (tsresol_opt & 0x80) {
+                               /*
+                                * Resolution is negative power of 2.
+                                */
+                               *tsresol = 1 << (tsresol_opt & 0x7F);
+                       } else {
+                               /*
+                                * Resolution is negative power of 10.
+                                */
+                               *tsresol = 1;
+                               for (i = 0; i < tsresol_opt; i++)
+                                       *tsresol *= 10;
+                       }
+                       if (*tsresol == 0) {
+                               /*
+                                * Resolution is too high.
+                                */
+                               if (tsresol_opt & 0x80) {
+                                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "Interface Description Block if_tsresol option resolution 2^-%u is too high",
+                                           tsresol_opt & 0x7F);
+                               } else {
+                                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "Interface Description Block if_tsresol option resolution 10^-%u is too high",
+                                           tsresol_opt);
+                               }
+                               return (-1);
+                       }
+                       break;
+
+               case IF_TSOFFSET:
+                       if (opthdr->option_length != 8) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Interface Description Block has if_tsoffset option with length %u != 8",
+                                   opthdr->option_length);
+                               return (-1);
+                       }
+                       if (saw_tsoffset) {
+                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Interface Description Block has more than one if_tsoffset option");
+                               return (-1);
+                       }
+                       saw_tsoffset = 1;
+                       memcpy(tsoffset, optvalue, sizeof(*tsoffset));
+                       if (p->sf.swapped)
+                               *tsoffset = SWAPLL(*tsoffset);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+done:
+       return (0);
+}
+
+/*
+ * Check whether this is a pcap-ng savefile and, if it is, extract the
+ * relevant information from the header.
+ */
+int
+pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
+{
+       size_t amt_read;
+       bpf_u_int32 total_length;
+       bpf_u_int32 byte_order_magic;
+       struct block_header *bhdrp;
+       struct section_header_block *shbp;
+       int status;
+       struct block_cursor cursor;
+       struct interface_description_block *idbp;
+
+       /*
+        * Check whether the first 4 bytes of the file are the block
+        * type for a pcap-ng savefile. 
+        */
+       if (magic != BT_SHB) {
+               /*
+                * XXX - check whether this looks like what the block
+                * type would be after being munged by mapping between
+                * UN*X and DOS/Windows text file format and, if it
+                * does, look for the byte-order magic number in
+                * the appropriate place and, if we find it, report
+                * this as possibly being a pcap-ng file transferred
+                * between UN*X and Windows in text file format?
+                */
+               return (0);     /* nope */
+       }
+
+       /*
+        * OK, they are.  However, that's just \n\r\r\n, so it could,
+        * conceivably, be an ordinary text file.
+        *
+        * It could not, however, conceivably be any other type of
+        * capture file, so we can read the rest of the putative
+        * Section Header Block; put the block type in the common
+        * header, read the rest of the common header and the
+        * fixed-length portion of the SHB, and look for the byte-order
+        * magic value.
+        */
+       amt_read = fread(&total_length, 1, sizeof(total_length), fp);
+       if (amt_read < sizeof(total_length)) {
+               if (ferror(fp)) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+                       return (-1);    /* fail */
+               }
+
+               /*
+                * Possibly a weird short text file, so just say
+                * "not pcap-ng".
+                */
+               return (0);
+       }
+       amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
+       if (amt_read < sizeof(byte_order_magic)) {
+               if (ferror(fp)) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+                       return (-1);    /* fail */
+               }
+
+               /*
+                * Possibly a weird short text file, so just say
+                * "not pcap-ng".
+                */
+               return (0);
+       }
+       if (byte_order_magic != BYTE_ORDER_MAGIC) {
+               byte_order_magic = SWAPLONG(byte_order_magic);
+               if (byte_order_magic != BYTE_ORDER_MAGIC) {
+                       /*
+                        * Not a pcap-ng file.
+                        */
+                       return (0);
+               }
+               p->sf.swapped = 1;
+               total_length = SWAPLONG(total_length);
+       }
+
+       /*
+        * Check the sanity of the total length.
+        */
+       if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "Section Header Block in pcap-ng dump file has a length of %u < %lu",
+                   total_length,
+                   (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
+               return (-1);
+       }
+
+       /*
+        * Allocate a buffer into which to read blocks.  We default to
+        * the maximum of:
+        *
+        *      the total length of the SHB for which we read the header;
+        *
+        *      2K, which should be more than large enough for an Enhanced
+        *      Packet Block containing a full-size Ethernet frame, and
+        *      leaving room for some options.
+        *
+        * If we find a bigger block, we reallocate the buffer.
+        */
+       p->bufsize = 2048;
+       if (p->bufsize < total_length)
+               p->bufsize = total_length;
+       p->buffer = malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+               return (-1);
+       }
+
+       /*
+        * Copy the stuff we've read to the buffer, and read the rest
+        * of the SHB.
+        */
+       bhdrp = (struct block_header *)p->buffer;
+       shbp = (struct section_header_block *)(p->buffer + sizeof(struct block_header));
+       bhdrp->block_type = magic;
+       bhdrp->total_length = total_length;
+       shbp->byte_order_magic = byte_order_magic;
+       if (read_bytes(fp,
+           p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+           total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+           1, errbuf) == -1)
+               goto fail;
+
+       if (p->sf.swapped) {
+               /*
+                * Byte-swap the fields we've read.
+                */
+               shbp->major_version = SWAPSHORT(shbp->major_version);
+               shbp->minor_version = SWAPSHORT(shbp->minor_version);
+
+               /*
+                * XXX - we don't care about the section length.
+                */
+       }
+       if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "unknown pcap-ng savefile major version number %u",
+                   shbp->major_version);
+               goto fail;
+       }
+       p->sf.version_major = shbp->major_version;
+       p->sf.version_minor = shbp->minor_version;
+
+       /*
+        * Set the default time stamp resolution and offset.
+        */
+       p->sf.tsresol = 1000000;        /* microsecond resolution */
+       p->sf.tsscale = 1;              /* multiply by 1 to scale to microseconds */
+       p->sf.tsoffset = 0;             /* absolute timestamps */
+
+       /*
+        * Now start looking for an Interface Description Block.
+        */
+       for (;;) {
+               /*
+                * Read the next block.
+                */
+               status = read_block(fp, p, &cursor, errbuf);
+               if (status == 0) {
+                       /* EOF - no IDB in this file */
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "the capture file has no Interface Description Blocks");
+                       goto fail;
+               }
+               if (status == -1)
+                       goto fail;      /* error */
+               switch (cursor.block_type) {
+
+               case BT_IDB:
+                       /*
+                        * Get a pointer to the fixed-length portion of the
+                        * IDB.
+                        */
+                       idbp = get_from_block_data(&cursor, sizeof(*idbp),
+                           errbuf);
+                       if (idbp == NULL)
+                               goto fail;      /* error */
+
+                       /*
+                        * Byte-swap it if necessary.
+                        */
+                       if (p->sf.swapped) {
+                               idbp->linktype = SWAPSHORT(idbp->linktype);
+                               idbp->snaplen = SWAPLONG(idbp->snaplen);
+                       }
+
+                       /*
+                        * Count this interface.
+                        */
+                       p->sf.ifcount++;
+
+                       /*
+                        * Now look for various time stamp options, so
+                        * we know how to interpret the time stamps.
+                        */
+                       if (process_idb_options(p, &cursor, &p->sf.tsresol,
+                           &p->sf.tsoffset, errbuf) == -1)
+                               goto fail;
+
+                       /*
+                        * Compute the scaling factor to convert the
+                        * sub-second part of the time stamp to
+                        * microseconds.
+                        */
+                       if (p->sf.tsresol > 1000000) {
+                               /*
+                                * Higher than microsecond resolution;
+                                * scale down to microseconds.
+                                */
+                               p->sf.tsscale = (p->sf.tsresol / 1000000);
+                       } else {
+                               /*
+                                * Lower than microsecond resolution;
+                                * scale up to microseconds.
+                                */
+                               p->sf.tsscale = (1000000 / p->sf.tsresol);
+                       }
+                       goto done;
+
+               case BT_EPB:
+               case BT_SPB:
+               case BT_PB:
+                       /*
+                        * Saw a packet before we saw any IDBs.  That's
+                        * not valid, as we don't know what link-layer
+                        * encapsulation the packet has.
+                        */
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "the capture file has a packet block before any Interface Description Blocks");
+                       goto fail;
+
+               default:
+                       /*
+                        * Just ignore it.
+                        */
+                       break;
+               }
+       }
+
+done:
+       p->tzoff = 0;   /* XXX - not used in pcap */
+       p->snapshot = idbp->snaplen;
+       p->linktype = linktype_to_dlt(idbp->linktype);
+       p->linktype_ext = 0;
+
+       p->sf.next_packet_op = pcap_ng_next_packet;
+
+       return (1);
+
+fail:
+       free(p->buffer);
+       return (-1);
+}
+
+/*
+ * Read and return the next packet from the savefile.  Return the header
+ * in hdr and a pointer to the contents in data.  Return 0 on success, 1
+ * if there were no more packets, and -1 on an error.
+ */
+static int
+pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
+{
+       struct block_cursor cursor;
+       int status;
+       struct enhanced_packet_block *epbp;
+       struct simple_packet_block *spbp;
+       struct packet_block *pbp;
+       bpf_u_int32 interface_id = 0xFFFFFFFF;
+       struct interface_description_block *idbp;
+       struct section_header_block *shbp;
+       FILE *fp = p->sf.rfile;
+       u_int tsresol;
+       u_int64_t tsoffset;
+       u_int64_t t, sec, frac;
+
+       /*
+        * Look for an Enhanced Packet Block, a Simple Packet Block,
+        * or a Packet Block.
+        */
+       for (;;) {
+               /*
+                * Read the block type and length; those are common
+                * to all blocks.
+                */
+               status = read_block(fp, p, &cursor, p->errbuf);
+               if (status == 0)
+                       return (1);     /* EOF */
+               if (status == -1)
+                       return (-1);    /* error */
+               switch (cursor.block_type) {
+
+               case BT_EPB:
+                       /*
+                        * Get a pointer to the fixed-length portion of the
+                        * EPB.
+                        */
+                       epbp = get_from_block_data(&cursor, sizeof(*epbp),
+                           p->errbuf);
+                       if (epbp == NULL)
+                               return (-1);    /* error */
+
+                       /*
+                        * Byte-swap it if necessary.
+                        */
+                       if (p->sf.swapped) {
+                               /* these were written in opposite byte order */
+                               interface_id = SWAPLONG(epbp->interface_id);
+                               hdr->caplen = SWAPLONG(epbp->caplen);
+                               hdr->len = SWAPLONG(epbp->len);
+                               t = ((u_int64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
+                                   SWAPLONG(epbp->timestamp_low);
+                       } else {
+                               interface_id = epbp->interface_id;
+                               hdr->caplen = epbp->caplen;
+                               hdr->len = epbp->len;
+                               t = ((u_int64_t)epbp->timestamp_high) << 32 |
+                                   epbp->timestamp_low;
+                       }
+                       goto found;
+                       
+               case BT_SPB:
+                       /*
+                        * Get a pointer to the fixed-length portion of the
+                        * SPB.
+                        */
+                       spbp = get_from_block_data(&cursor, sizeof(*spbp),
+                           p->errbuf);
+                       if (spbp == NULL)
+                               return (-1);    /* error */
+
+                       /*
+                        * SPB packets are assumed to have arrived on
+                        * the first interface.
+                        */
+                       interface_id = 0;
+
+                       /*
+                        * Byte-swap it if necessary.
+                        */
+                       if (p->sf.swapped) {
+                               /* these were written in opposite byte order */
+                               hdr->len = SWAPLONG(spbp->len);
+                       } else
+                               hdr->len = spbp->len;
+
+                       /*
+                        * The SPB doesn't give the captured length;
+                        * it's the minimum of the snapshot length
+                        * and the packet length.
+                        */
+                       hdr->caplen = hdr->len;
+                       if (hdr->caplen > p->snapshot)
+                               hdr->caplen = p->snapshot;
+                       t = 0;  /* no time stamps */
+                       goto found;
+
+               case BT_PB:
+                       /*
+                        * Get a pointer to the fixed-length portion of the
+                        * PB.
+                        */
+                       pbp = get_from_block_data(&cursor, sizeof(*pbp),
+                           p->errbuf);
+                       if (pbp == NULL)
+                               return (-1);    /* error */
+
+                       /*
+                        * Byte-swap it if necessary.
+                        */
+                       if (p->sf.swapped) {
+                               /* these were written in opposite byte order */
+                               interface_id = SWAPSHORT(pbp->interface_id);
+                               hdr->caplen = SWAPLONG(pbp->caplen);
+                               hdr->len = SWAPLONG(pbp->len);
+                               t = ((u_int64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
+                                   SWAPLONG(pbp->timestamp_low);
+                       } else {
+                               interface_id = pbp->interface_id;
+                               hdr->caplen = pbp->caplen;
+                               hdr->len = pbp->len;
+                               t = ((u_int64_t)pbp->timestamp_high) << 32 |
+                                   pbp->timestamp_low;
+                       }
+                       goto found;
+
+               case BT_IDB:
+                       /*
+                        * Interface Description Block.  Get a pointer
+                        * to its fixed-length portion.
+                        */
+                       idbp = get_from_block_data(&cursor, sizeof(*idbp),
+                           p->errbuf);
+                       if (idbp == NULL)
+                               return (-1);    /* error */
+
+                       /*
+                        * Byte-swap it if necessary.
+                        */
+                       if (p->sf.swapped) {
+                               idbp->linktype = SWAPSHORT(idbp->linktype);
+                               idbp->snaplen = SWAPLONG(idbp->snaplen);
+                       }
+
+                       /*
+                        * If the link-layer type or snapshot length
+                        * differ from the ones for the first IDB we
+                        * saw, quit.
+                        *
+                        * XXX - just discard packets from those
+                        * interfaces?
+                        */
+                       if (p->linktype != idbp->linktype) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "an interface has a type %u different from the type of the first interface",
+                                   idbp->linktype);
+                               return (-1);
+                       }
+                       if (p->snapshot != idbp->snaplen) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "an interface has a snapshot length %u different from the type of the first interface",
+                                   idbp->snaplen);
+                               return (-1);
+                       }
+
+                       /*
+                        * Count this interface.
+                        */
+                       p->sf.ifcount++;
+
+                       /*
+                        * Set the default time stamp resolution and offset.
+                        */
+                       tsresol = 1000000;      /* microsecond resolution */
+                       tsoffset = 0;           /* absolute timestamps */
+
+                       /*
+                        * Now look for various time stamp options, to
+                        * make sure they're the same.
+                        *
+                        * XXX - we could, in theory, handle multiple
+                        * different resolutions and offsets, but we
+                        * don't do so for now.
+                        */
+                       if (process_idb_options(p, &cursor, &tsresol, &tsoffset,
+                           p->errbuf) == -1)
+                               return (-1);
+                       if (tsresol != p->sf.tsresol) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "an interface has a time stamp resolution different from the time stamp resolution of the first interface");
+                               return (-1);
+                       }
+                       if (tsoffset != p->sf.tsoffset) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "an interface has a time stamp offset different from the time stamp offset of the first interface");
+                               return (-1);
+                       }
+                       break;
+
+               case BT_SHB:
+                       /*
+                        * Section Header Block.  Get a pointer
+                        * to its fixed-length portion.
+                        */
+                       shbp = get_from_block_data(&cursor, sizeof(*shbp),
+                           p->errbuf);
+                       if (shbp == NULL)
+                               return (-1);    /* error */
+
+                       /*
+                        * Assume the byte order of this section is
+                        * the same as that of the previous section.
+                        * We'll check for that later.
+                        */
+                       if (p->sf.swapped) {
+                               shbp->byte_order_magic =
+                                   SWAPLONG(shbp->byte_order_magic);
+                               shbp->major_version =
+                                   SWAPSHORT(shbp->major_version);
+                       }
+
+                       /*
+                        * Make sure the byte order doesn't change;
+                        * pcap_is_swapped() shouldn't change its
+                        * return value in the middle of reading a capture.
+                        */
+                       switch (shbp->byte_order_magic) {
+
+                       case BYTE_ORDER_MAGIC:
+                               /*
+                                * OK.
+                                */
+                               break;
+
+                       case SWAPLONG(BYTE_ORDER_MAGIC):
+                               /*
+                                * Byte order changes.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "the file has sections with different byte orders");
+                               return (-1);
+
+                       default:
+                               /*
+                                * Not a valid SHB.
+                                */
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "the file has a section with a bad byte order magic field");
+                               return (-1);
+                       }
+
+                       /*
+                        * Make sure the major version is the version
+                        * we handle.
+                        */
+                       if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "unknown pcap-ng savefile major version number %u",
+                                   shbp->major_version);
+                               return (-1);
+                       }
+
+                       /*
+                        * Reset the interface count; this section should
+                        * have its own set of IDBs.  If any of them
+                        * don't have the same interface type, snapshot
+                        * length, or resolution as the first interface
+                        * we saw, we'll fail.  (And if we don't see
+                        * any IDBs, we'll fail when we see a packet
+                        * block.)
+                        */
+                       p->sf.ifcount = 0;
+                       break;
+
+               default:
+                       /*
+                        * Not a packet block, IDB, or SHB; ignore it.
+                        */
+                       break;
+               }                
+       }
+
+found:
+       /*
+        * Is the interface ID an interface we know?
+        */
+       if (interface_id >= p->sf.ifcount) {
+               /*
+                * Yes.  Fail.
+                */
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
+                   interface_id);
+               return (-1);
+       }
+
+       /*
+        * Convert the time stamp to a struct timeval.
+        */
+       sec = t / p->sf.tsresol + p->sf.tsoffset;
+       frac = t % p->sf.tsresol;
+       if (p->sf.tsresol > 1000000) {
+               /*
+                * Higher than microsecond resolution; scale down to
+                * microseconds.
+                */
+               frac /= p->sf.tsscale;
+       } else {
+               /*
+                * Lower than microsecond resolution; scale up to
+                * microseconds.
+                */
+               frac *= p->sf.tsscale;
+       }
+       hdr->ts.tv_sec = sec;
+       hdr->ts.tv_usec = frac;
+
+       /*
+        * Get a pointer to the packet data.
+        */
+       *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
+       if (*data == NULL)
+               return (-1);
+
+       if (p->sf.swapped) {
+               /*
+                * Convert pseudo-headers from the byte order of
+                * the host on which the file was saved to our
+                * byte order, as necessary.
+                */
+               switch (p->linktype) {
+
+               case DLT_USB_LINUX:
+                       swap_linux_usb_header(hdr, *data, 0);
+                       break;
+
+               case DLT_USB_LINUX_MMAPPED:
+                       swap_linux_usb_header(hdr, *data, 1);
+                       break;
+               }
+       }
+
+       return (0);
+}
diff --git a/sf-pcap-ng.h b/sf-pcap-ng.h
new file mode 100644 (file)
index 0000000..cc55182
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap-ng.h - pcap-ng-file-format-specific routines
+ *
+ * Used to read pcap-ng savefiles.
+ */
+
+#ifndef sf_pcap_ng_h
+#define        sf_pcap_ng_h
+
+extern int pcap_ng_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
+
+#endif
diff --git a/sf-pcap.c b/sf-pcap.c
new file mode 100644 (file)
index 0000000..2b31a2b
--- /dev/null
+++ b/sf-pcap.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap.c - libpcap-file-format-specific code from savefile.c
+ *     Extraction/creation by Jeffrey Mogul, DECWRL
+ *     Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header$ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#include <sys/types.h>
+#endif /* WIN32 */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "pcap-common.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcap.h"
+
+/*
+ * Setting O_BINARY on DOS/Windows is a bit tricky
+ */
+#if defined(WIN32)
+  #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
+#elif defined(MSDOS)
+  #if defined(__HIGHC__)
+  #define SET_BINMODE(f)  setmode(f, O_BINARY)
+  #else
+  #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
+  #endif
+#endif
+
+/*
+ * Standard libpcap format.
+ */
+#define TCPDUMP_MAGIC          0xa1b2c3d4
+
+/*
+ * Alexey Kuznetzov's modified libpcap format.
+ */
+#define KUZNETZOV_TCPDUMP_MAGIC        0xa1b2cd34
+
+/*
+ * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
+ * for another modified format.
+ */
+#define FMESQUITA_TCPDUMP_MAGIC        0xa1b234cd
+
+/*
+ * Navtel Communcations' format, with nanosecond timestamps,
+ * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
+ */
+#define NAVTEL_TCPDUMP_MAGIC   0xa12b3c4d
+
+/*
+ * Normal libpcap format, except for seconds/nanoseconds timestamps,
+ * as per a request by Ulf Lamping <ulf.lamping@web.de>
+ */
+#define NSEC_TCPDUMP_MAGIC     0xa1b23c4d
+
+/*
+ * Mechanism for storing information about a capture in the upper
+ * 6 bits of a linktype value in a capture file.
+ *
+ * LT_LINKTYPE_EXT(x) extracts the additional information.
+ *
+ * The rest of the bits are for a value describing the link-layer
+ * value.  LT_LINKTYPE(x) extracts that value.
+ */
+#define LT_LINKTYPE(x)         ((x) & 0x03FFFFFF)
+#define LT_LINKTYPE_EXT(x)     ((x) & 0xFC000000)
+
+static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
+
+/*
+ * Check whether this is a pcap savefile and, if it is, extract the
+ * relevant information from the header.
+ */
+int
+pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
+{
+       struct pcap_file_header hdr;
+       size_t amt_read;
+
+       /*
+        * Check whether the first 4 bytes of the file are the magic
+        * number for a pcap savefile, or for a byte-swapped pcap
+        * savefile.
+        */
+       if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
+               magic = SWAPLONG(magic);
+               if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
+                       return (0);     /* nope */
+               p->sf.swapped = 1;
+       }
+
+       /*
+        * They are.  Put the magic number in the header, and read
+        * the rest of the header.
+        */
+       hdr.magic = magic;
+       amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
+           sizeof(hdr) - sizeof(hdr.magic), fp);
+       if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
+               if (ferror(fp)) {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+               } else {
+                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated dump file; tried to read %lu file header bytes, only got %lu",
+                           (unsigned long)sizeof(hdr),
+                           (unsigned long)amt_read);
+               }
+               return (-1);
+       }
+
+       /*
+        * If it's a byte-swapped capture file, byte-swap the header.
+        */
+       if (p->sf.swapped) {
+               hdr.version_major = SWAPSHORT(hdr.version_major);
+               hdr.version_minor = SWAPSHORT(hdr.version_minor);
+               hdr.thiszone = SWAPLONG(hdr.thiszone);
+               hdr.sigfigs = SWAPLONG(hdr.sigfigs);
+               hdr.snaplen = SWAPLONG(hdr.snaplen);
+               hdr.linktype = SWAPLONG(hdr.linktype);
+       }
+
+       if (hdr.version_major < PCAP_VERSION_MAJOR) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "archaic pcap savefile format");
+               return (-1);
+       }
+       p->sf.version_major = hdr.version_major;
+       p->sf.version_minor = hdr.version_minor;
+       p->tzoff = hdr.thiszone;
+       p->snapshot = hdr.snaplen;
+       p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
+       p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
+
+       p->sf.next_packet_op = pcap_next_packet;
+
+       /*
+        * We interchanged the caplen and len fields at version 2.3,
+        * in order to match the bpf header layout.  But unfortunately
+        * some files were written with version 2.3 in their headers
+        * but without the interchanged fields.
+        *
+        * In addition, DG/UX tcpdump writes out files with a version
+        * number of 543.0, and with the caplen and len fields in the
+        * pre-2.3 order.
+        */
+       switch (hdr.version_major) {
+
+       case 2:
+               if (hdr.version_minor < 3)
+                       p->sf.lengths_swapped = SWAPPED;
+               else if (hdr.version_minor == 3)
+                       p->sf.lengths_swapped = MAYBE_SWAPPED;
+               else
+                       p->sf.lengths_swapped = NOT_SWAPPED;
+               break;
+
+       case 543:
+               p->sf.lengths_swapped = SWAPPED;
+               break;
+
+       default:
+               p->sf.lengths_swapped = NOT_SWAPPED;
+               break;
+       }
+
+       if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
+               /*
+                * XXX - the patch that's in some versions of libpcap
+                * changes the packet header but not the magic number,
+                * and some other versions with this magic number have
+                * some extra debugging information in the packet header;
+                * we'd have to use some hacks^H^H^H^H^Hheuristics to
+                * detect those variants.
+                *
+                * Ethereal does that, but it does so by trying to read
+                * the first two packets of the file with each of the
+                * record header formats.  That currently means it seeks
+                * backwards and retries the reads, which doesn't work
+                * on pipes.  We want to be able to read from a pipe, so
+                * that strategy won't work; we'd have to buffer some
+                * data ourselves and read from that buffer in order to
+                * make that work.
+                */
+               p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
+
+               if (p->linktype == DLT_EN10MB) {
+                       /*
+                        * This capture might have been done in raw mode
+                        * or cooked mode.
+                        *
+                        * If it was done in cooked mode, p->snapshot was
+                        * passed to recvfrom() as the buffer size, meaning
+                        * that the most packet data that would be copied
+                        * would be p->snapshot.  However, a faked Ethernet
+                        * header would then have been added to it, so the
+                        * most data that would be in a packet in the file
+                        * would be p->snapshot + 14.
+                        *
+                        * We can't easily tell whether the capture was done
+                        * in raw mode or cooked mode, so we'll assume it was
+                        * cooked mode, and add 14 to the snapshot length.
+                        * That means that, for a raw capture, the snapshot
+                        * length will be misleading if you use it to figure
+                        * out why a capture doesn't have all the packet data,
+                        * but there's not much we can do to avoid that.
+                        */
+                       p->snapshot += 14;
+               }
+       } else
+               p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr);
+
+       /*
+        * Allocate a buffer for the packet data.
+        */
+       p->bufsize = p->snapshot;
+       if (p->bufsize <= 0) {
+               /*
+                * Bogus snapshot length; use 64KiB as a fallback.
+                */
+               p->bufsize = 65536;
+       }
+       p->buffer = malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+               return (-1);
+       }
+
+       return (1);
+}
+
+/*
+ * Read and return the next packet from the savefile.  Return the header
+ * in hdr and a pointer to the contents in data.  Return 0 on success, 1
+ * if there were no more packets, and -1 on an error.
+ */
+static int
+pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
+{
+       struct pcap_sf_patched_pkthdr sf_hdr;
+       FILE *fp = p->sf.rfile;
+       size_t amt_read;
+       bpf_u_int32 t;
+
+       /*
+        * Read the packet header; the structure we use as a buffer
+        * is the longer structure for files generated by the patched
+        * libpcap, but if the file has the magic number for an
+        * unpatched libpcap we only read as many bytes as the regular
+        * header has.
+        */
+       amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp);
+       if (amt_read != p->sf.hdrsize) {
+               if (ferror(fp)) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "error reading dump file: %s",
+                           pcap_strerror(errno));
+                       return (-1);
+               } else {
+                       if (amt_read != 0) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "truncated dump file; tried to read %lu header bytes, only got %lu",
+                                   (unsigned long)p->sf.hdrsize,
+                                   (unsigned long)amt_read);
+                               return (-1);
+                       }
+                       /* EOF */
+                       return (1);
+               }
+       }
+
+       if (p->sf.swapped) {
+               /* these were written in opposite byte order */
+               hdr->caplen = SWAPLONG(sf_hdr.caplen);
+               hdr->len = SWAPLONG(sf_hdr.len);
+               hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec);
+               hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec);
+       } else {
+               hdr->caplen = sf_hdr.caplen;
+               hdr->len = sf_hdr.len;
+               hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
+               hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
+       }
+       /* Swap the caplen and len fields, if necessary. */
+       switch (p->sf.lengths_swapped) {
+
+       case NOT_SWAPPED:
+               break;
+
+       case MAYBE_SWAPPED:
+               if (hdr->caplen <= hdr->len) {
+                       /*
+                        * The captured length is <= the actual length,
+                        * so presumably they weren't swapped.
+                        */
+                       break;
+               }
+               /* FALLTHROUGH */
+
+       case SWAPPED:
+               t = hdr->caplen;
+               hdr->caplen = hdr->len;
+               hdr->len = t;
+               break;
+       }
+
+       if (hdr->caplen > p->bufsize) {
+               /*
+                * This can happen due to Solaris 2.3 systems tripping
+                * over the BUFMOD problem and not setting the snapshot
+                * correctly in the savefile header.  If the caplen isn't
+                * grossly wrong, try to salvage.
+                */
+               static u_char *tp = NULL;
+               static size_t tsize = 0;
+
+               if (hdr->caplen > 65535) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "bogus savefile header");
+                       return (-1);
+               }
+
+               if (tsize < hdr->caplen) {
+                       tsize = ((hdr->caplen + 1023) / 1024) * 1024;
+                       if (tp != NULL)
+                               free((u_char *)tp);
+                       tp = (u_char *)malloc(tsize);
+                       if (tp == NULL) {
+                               tsize = 0;
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "BUFMOD hack malloc");
+                               return (-1);
+                       }
+               }
+               amt_read = fread((char *)tp, 1, hdr->caplen, fp);
+               if (amt_read != hdr->caplen) {
+                       if (ferror(fp)) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "error reading dump file: %s",
+                                   pcap_strerror(errno));
+                       } else {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "truncated dump file; tried to read %u captured bytes, only got %lu",
+                                   hdr->caplen, (unsigned long)amt_read);
+                       }
+                       return (-1);
+               }
+               /*
+                * We can only keep up to p->bufsize bytes.  Since
+                * caplen > p->bufsize is exactly how we got here,
+                * we know we can only keep the first p->bufsize bytes
+                * and must drop the remainder.  Adjust caplen accordingly,
+                * so we don't get confused later as to how many bytes we
+                * have to play with.
+                */
+               hdr->caplen = p->bufsize;
+               memcpy(p->buffer, (char *)tp, p->bufsize);
+       } else {
+               /* read the packet itself */
+               amt_read = fread(p->buffer, 1, hdr->caplen, fp);
+               if (amt_read != hdr->caplen) {
+                       if (ferror(fp)) {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "error reading dump file: %s",
+                                   pcap_strerror(errno));
+                       } else {
+                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "truncated dump file; tried to read %u captured bytes, only got %lu",
+                                   hdr->caplen, (unsigned long)amt_read);
+                       }
+                       return (-1);
+               }
+       }
+       *data = p->buffer;
+
+       if (p->sf.swapped) {
+               /*
+                * Convert pseudo-headers from the byte order of
+                * the host on which the file was saved to our
+                * byte order, as necessary.
+                */
+               switch (p->linktype) {
+
+               case DLT_USB_LINUX:
+                       swap_linux_usb_header(hdr, *data, 0);
+                       break;
+
+               case DLT_USB_LINUX_MMAPPED:
+                       swap_linux_usb_header(hdr, *data, 1);
+                       break;
+               }
+       }
+
+       return (0);
+}
+
+static int
+sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
+{
+       struct pcap_file_header hdr;
+
+       hdr.magic = TCPDUMP_MAGIC;
+       hdr.version_major = PCAP_VERSION_MAJOR;
+       hdr.version_minor = PCAP_VERSION_MINOR;
+
+       hdr.thiszone = thiszone;
+       hdr.snaplen = snaplen;
+       hdr.sigfigs = 0;
+       hdr.linktype = linktype;
+
+       if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
+               return (-1);
+
+       return (0);
+}
+
+/*
+ * Output a packet to the initialized dump file.
+ */
+void
+pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+       register FILE *f;
+       struct pcap_sf_pkthdr sf_hdr;
+
+       f = (FILE *)user;
+       sf_hdr.ts.tv_sec  = h->ts.tv_sec;
+       sf_hdr.ts.tv_usec = h->ts.tv_usec;
+       sf_hdr.caplen     = h->caplen;
+       sf_hdr.len        = h->len;
+       /* XXX we should check the return status */
+       (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f);
+       (void)fwrite(sp, h->caplen, 1, f);
+}
+
+static pcap_dumper_t *
+pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
+{
+
+#if defined(WIN32) || defined(MSDOS)
+       /*
+        * If we're writing to the standard output, put it in binary
+        * mode, as savefiles are binary files.
+        *
+        * Otherwise, we turn off buffering.
+        * XXX - why?  And why not on the standard output?
+        */
+       if (f == stdout)
+               SET_BINMODE(f);
+       else
+               setbuf(f, NULL);
+#endif
+       if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+                   fname, pcap_strerror(errno));
+               if (f != stdout)
+                       (void)fclose(f);
+               return (NULL);
+       }
+       return ((pcap_dumper_t *)f);
+}
+
+/*
+ * Initialize so that sf_write() will output to the file named 'fname'.
+ */
+pcap_dumper_t *
+pcap_dump_open(pcap_t *p, const char *fname)
+{
+       FILE *f;
+       int linktype;
+
+       /*
+        * 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,
+                   "%s: not-yet-activated pcap_t passed to pcap_dump_open",
+                   fname);
+               return (NULL);
+       }
+       linktype = dlt_to_linktype(p->linktype);
+       if (linktype == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "%s: link-layer type %d isn't supported in savefiles",
+                   fname, p->linktype);
+               return (NULL);
+       }
+       linktype |= p->linktype_ext;
+
+       if (fname[0] == '-' && fname[1] == '\0') {
+               f = stdout;
+               fname = "standard output";
+       } else {
+#if !defined(WIN32) && !defined(MSDOS)
+               f = fopen(fname, "w");
+#else
+               f = fopen(fname, "wb");
+#endif
+               if (f == NULL) {
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+                           fname, pcap_strerror(errno));
+                       return (NULL);
+               }
+       }
+       return (pcap_setup_dump(p, linktype, f, fname));
+}
+
+/*
+ * Initialize so that sf_write() will output to the given stream.
+ */
+pcap_dumper_t *
+pcap_dump_fopen(pcap_t *p, FILE *f)
+{      
+       int linktype;
+
+       linktype = dlt_to_linktype(p->linktype);
+       if (linktype == -1) {
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "stream: link-layer type %d isn't supported in savefiles",
+                   p->linktype);
+               return (NULL);
+       }
+       linktype |= p->linktype_ext;
+
+       return (pcap_setup_dump(p, linktype, f, "stream"));
+}
+
+FILE *
+pcap_dump_file(pcap_dumper_t *p)
+{
+       return ((FILE *)p);
+}
+
+long
+pcap_dump_ftell(pcap_dumper_t *p)
+{
+       return (ftell((FILE *)p));
+}
+
+int
+pcap_dump_flush(pcap_dumper_t *p)
+{
+
+       if (fflush((FILE *)p) == EOF)
+               return (-1);
+       else
+               return (0);
+}
+
+void
+pcap_dump_close(pcap_dumper_t *p)
+{
+
+#ifdef notyet
+       if (ferror((FILE *)p))
+               return-an-error;
+       /* XXX should check return from fclose() too */
+#endif
+       (void)fclose((FILE *)p);
+}
diff --git a/sf-pcap.h b/sf-pcap.h
new file mode 100644 (file)
index 0000000..3b3fbe8
--- /dev/null
+++ b/sf-pcap.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap.h - libpcap-file-format-specific routines
+ *     Extraction/creation by Jeffrey Mogul, DECWRL
+ *     Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifndef sf_pcap_h
+#define        sf_pcap_h
+
+extern int pcap_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
+
+#endif
diff --git a/sunatmpos.h b/sunatmpos.h
new file mode 100644 (file)
index 0000000..916017f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Yen Yen Lim and
+        North Dakota State University
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/sunatmpos.h,v 1.1 2002-07-11 09:06:47 guy Exp $ (LBL)
+ */
+
+/* SunATM header for ATM packet */
+#define SUNATM_DIR_POS         0
+#define SUNATM_VPI_POS         1
+#define SUNATM_VCI_POS         2
+#define SUNATM_PKT_BEGIN_POS   4       /* Start of ATM packet */
+
+/* Protocol type values in the bottom for bits of the byte at SUNATM_DIR_POS. */
+#define PT_LANE                0x01    /* LANE */
+#define PT_LLC         0x02    /* LLC encapsulation */
+#define PT_ILMI                0x05    /* ILMI */
+#define PT_QSAAL       0x06    /* Q.SAAL */
diff --git a/tests/filtertest.c b/tests/filtertest.c
new file mode 100644 (file)
index 0000000..a56d1e4
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] _U_ =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005-08-08 17:50:13 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...)
+    __attribute__((noreturn, format (printf, 1, 2)));
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+/*
+ * On Windows, we need to open the file in binary mode, so that
+ * we get all the bytes specified by the size we get from "fstat()".
+ * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
+ * we define it as 0 if it's not defined, so it does nothing.
+ */
+#ifndef O_BINARY
+#define O_BINARY       0
+#endif
+
+static char *
+read_infile(char *fname)
+{
+       register int i, fd, cc;
+       register char *cp;
+       struct stat buf;
+
+       fd = open(fname, O_RDONLY|O_BINARY);
+       if (fd < 0)
+               error("can't open %s: %s", fname, pcap_strerror(errno));
+
+       if (fstat(fd, &buf) < 0)
+               error("can't stat %s: %s", fname, pcap_strerror(errno));
+
+       cp = malloc((u_int)buf.st_size + 1);
+       if (cp == NULL)
+               error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
+                       fname, pcap_strerror(errno));
+       cc = read(fd, cp, (u_int)buf.st_size);
+       if (cc < 0)
+               error("read %s: %s", fname, pcap_strerror(errno));
+       if (cc != buf.st_size)
+               error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+
+       close(fd);
+       /* replace "# comment" with spaces */
+       for (i = 0; i < cc; i++) {
+               if (cp[i] == '#')
+                       while (i < cc && cp[i] != '\n')
+                               cp[i++] = ' ';
+       }
+       cp[cc] = '\0';
+       return (cp);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+       register char **p;
+       register u_int len = 0;
+       char *buf;
+       char *src, *dst;
+
+       p = argv;
+       if (*p == 0)
+               return 0;
+
+       while (*p)
+               len += strlen(*p++) + 1;
+
+       buf = (char *)malloc(len);
+       if (buf == NULL)
+               error("copy_argv: malloc");
+
+       p = argv;
+       dst = buf;
+       while ((src = *p++) != NULL) {
+               while ((*dst++ = *src++) != '\0')
+                       ;
+               dst[-1] = ' ';
+       }
+       dst[-1] = '\0';
+
+       return buf;
+}
+
+int
+main(int argc, char **argv)
+{
+       char *cp;
+       int op;
+       int dflag;
+       char *infile;
+       int Oflag;
+       long snaplen;
+       int dlt;
+       bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN;
+       char *cmdbuf;
+       pcap_t *pd;
+       struct bpf_program fcode;
+
+#ifdef WIN32
+       if(wsockinit() != 0) return 1;
+#endif /* WIN32 */
+
+       dflag = 1;
+       infile = NULL;
+       Oflag = 1;
+       snaplen = 68;
+  
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) {
+               switch (op) {
+
+               case 'd':
+                       ++dflag;
+                       break;
+
+               case 'F':
+                       infile = optarg;
+                       break;
+
+               case 'O':
+                       Oflag = 0;
+                       break;
+
+               case 'm': {
+                       in_addr_t addr;
+
+                       addr = inet_addr(optarg);
+                       if (addr == INADDR_NONE)
+                               error("invalid netmask %s", optarg);
+                       netmask = addr;
+                       break;
+               }
+
+               case 's': {
+                       char *end;
+
+                       snaplen = strtol(optarg, &end, 0);
+                       if (optarg == end || *end != '\0'
+                           || snaplen < 0 || snaplen > 65535)
+                               error("invalid snaplen %s", optarg);
+                       else if (snaplen == 0)
+                               snaplen = 65535;
+                       break;
+               }
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       if (optind >= argc) {
+               usage();
+               /* NOTREACHED */
+       }
+
+       dlt = pcap_datalink_name_to_val(argv[optind]);
+       if (dlt < 0)
+               error("invalid data link type %s", argv[optind]);
+       
+       if (infile)
+               cmdbuf = read_infile(infile);
+       else
+               cmdbuf = copy_argv(&argv[optind+1]);
+
+       pd = pcap_open_dead(dlt, snaplen);
+       if (pd == NULL)
+               error("Can't open fake pcap_t");
+
+       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+               error("%s", pcap_geterr(pd));
+       bpf_dump(&fcode, dflag);
+       pcap_close(pd);
+       exit(0);
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "%s, with %s\n", program_name,
+           pcap_lib_version());
+       (void)fprintf(stderr,
+           "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
+           program_name);
+       exit(1);
+}
diff --git a/tests/findalldevstest.c b/tests/findalldevstest.c
new file mode 100644 (file)
index 0000000..ec7c950
--- /dev/null
@@ -0,0 +1,131 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <pcap.h>
+
+static void ifprint(pcap_if_t *d);
+static char *iptos(bpf_u_int32 in);
+
+int main(int argc, char **argv)
+{
+  pcap_if_t *alldevs;
+  pcap_if_t *d;
+  char *s;
+  bpf_u_int32 net, mask;
+  
+  char errbuf[PCAP_ERRBUF_SIZE+1];
+  if (pcap_findalldevs(&alldevs, errbuf) == -1)
+  {
+    fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+    exit(1);
+  }
+  for(d=alldevs;d;d=d->next)
+  {
+    ifprint(d);
+  }
+
+  if ( (s = pcap_lookupdev(errbuf)) == NULL)
+  {
+    fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf);
+  }
+  else
+  {
+    printf("Preferred device name: %s\n",s);
+  }
+
+  if (pcap_lookupnet(s, &net, &mask, errbuf) < 0)
+  {
+    fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
+  }
+  else
+  {
+    printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
+  }
+  
+  exit(0);
+}
+
+static void ifprint(pcap_if_t *d)
+{
+  pcap_addr_t *a;
+#ifdef INET6
+  char ntop_buf[INET6_ADDRSTRLEN];
+#endif
+
+  printf("%s\n",d->name);
+  if (d->description)
+    printf("\tDescription: %s\n",d->description);
+  printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
+
+  for(a=d->addresses;a;a=a->next) {
+    switch(a->addr->sa_family)
+    {
+      case AF_INET:
+        printf("\tAddress Family: AF_INET\n");
+        if (a->addr)
+          printf("\t\tAddress: %s\n",
+            inet_ntoa(((struct sockaddr_in *)(a->addr))->sin_addr));
+        if (a->netmask)
+          printf("\t\tNetmask: %s\n",
+            inet_ntoa(((struct sockaddr_in *)(a->netmask))->sin_addr));
+        if (a->broadaddr)
+          printf("\t\tBroadcast Address: %s\n",
+            inet_ntoa(((struct sockaddr_in *)(a->broadaddr))->sin_addr));
+        if (a->dstaddr)
+          printf("\t\tDestination Address: %s\n",
+            inet_ntoa(((struct sockaddr_in *)(a->dstaddr))->sin_addr));
+        break;
+#ifdef INET6
+      case AF_INET6:
+        printf("\tAddress Family: AF_INET6\n");
+        if (a->addr)
+          printf("\t\tAddress: %s\n",
+            inet_ntop(AF_INET6,
+               ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
+               ntop_buf, sizeof ntop_buf));
+        if (a->netmask)
+          printf("\t\tNetmask: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
+               ntop_buf, sizeof ntop_buf));
+        if (a->broadaddr)
+          printf("\t\tBroadcast Address: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
+               ntop_buf, sizeof ntop_buf));
+        if (a->dstaddr)
+          printf("\t\tDestination Address: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
+               ntop_buf, sizeof ntop_buf));
+        break;
+#endif
+      default:
+        printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
+        break;
+    }
+  }
+  printf("\n");
+}
+
+/* From tcptraceroute */
+#define IPTOSBUFFERS   12
+static char *iptos(bpf_u_int32 in)
+{
+       static char output[IPTOSBUFFERS][3*4+3+1];
+       static short which;
+       u_char *p;
+
+       p = (u_char *)&in;
+       which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
+       sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+       return output[which];
+}
diff --git a/tests/nonblocktest.c b/tests/nonblocktest.c
new file mode 100644 (file)
index 0000000..70a6bfd
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <poll.h>
+
+char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...);
+static void warning(const char *, ...);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       register int op;
+       bpf_u_int32 localnet, netmask;
+       register char *cp, *cmdbuf, *device;
+       struct bpf_program fcode;
+       char ebuf[PCAP_ERRBUF_SIZE];
+       int status;
+       int packet_count;
+
+       device = NULL;
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "i:")) != -1) {
+               switch (op) {
+
+               case 'i':
+                       device = optarg;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       if (device == NULL) {
+               device = pcap_lookupdev(ebuf);
+               if (device == NULL)
+                       error("%s", ebuf);
+       }
+       *ebuf = '\0';
+       pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+       if (pd == NULL)
+               error("%s", ebuf);
+       else if (*ebuf)
+               warning("%s", ebuf);
+       if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+               localnet = 0;
+               netmask = 0;
+               warning("%s", ebuf);
+       }
+       cmdbuf = copy_argv(&argv[optind]);
+
+       if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+               error("%s", pcap_geterr(pd));
+
+       if (pcap_setfilter(pd, &fcode) < 0)
+               error("%s", pcap_geterr(pd));
+       if (pcap_setnonblock(pd, 1, ebuf) == -1)
+               error("pcap_setnonblock failed: %s", ebuf);
+       printf("Listening on %s\n", device);
+       for (;;) {
+               packet_count = 0;
+               status = pcap_dispatch(pd, -1, countme,
+                   (u_char *)&packet_count);
+               if (status < 0)
+                       break;
+               if (status != 0) {
+                       printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+                           status, packet_count);
+               }
+       }
+       if (status == -2) {
+               /*
+                * We got interrupted, so perhaps we didn't
+                * manage to finish a line we were printing.
+                * Print an extra newline, just in case.
+                */
+               putchar('\n');
+       }
+       (void)fflush(stdout);
+       if (status == -1) {
+               /*
+                * Error.  Report it.
+                */
+               (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+                   program_name, pcap_geterr(pd));
+       }
+       pcap_close(pd);
+       exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+       int *counterp = (int *)user;
+
+       (*counterp)++;
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
+           program_name);
+       exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: WARNING: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+       register char **p;
+       register u_int len = 0;
+       char *buf;
+       char *src, *dst;
+
+       p = argv;
+       if (*p == 0)
+               return 0;
+
+       while (*p)
+               len += strlen(*p++) + 1;
+
+       buf = (char *)malloc(len);
+       if (buf == NULL)
+               error("copy_argv: malloc");
+
+       p = argv;
+       dst = buf;
+       while ((src = *p++) != NULL) {
+               while ((*dst++ = *src++) != '\0')
+                       ;
+               dst[-1] = ' ';
+       }
+       dst[-1] = '\0';
+
+       return buf;
+}
diff --git a/tests/opentest.c b/tests/opentest.c
new file mode 100644 (file)
index 0000000..0c91531
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define MAXIMUM_SNAPLEN                65535
+
+static char *program_name;
+
+/* Forwards */
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...);
+static void warning(const char *, ...);
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       register int op;
+       register char *cp, *device;
+       int dorfmon, dopromisc, snaplen, useactivate, bufsize;
+       char ebuf[PCAP_ERRBUF_SIZE];
+       pcap_t *pd;
+       int status = 0;
+
+       device = NULL;
+       dorfmon = 0;
+       dopromisc = 0;
+       snaplen = MAXIMUM_SNAPLEN;
+       bufsize = 0;
+       useactivate = 0;
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "i:Ips:aB:")) != -1) {
+               switch (op) {
+
+               case 'i':
+                       device = optarg;
+                       break;
+
+               case 'I':
+                       dorfmon = 1;
+                       useactivate = 1;        /* required for rfmon */
+                       break;
+
+               case 'p':
+                       dopromisc = 1;
+                       break;
+
+               case 's': {
+                       char *end;
+
+                       snaplen = strtol(optarg, &end, 0);
+                       if (optarg == end || *end != '\0'
+                           || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
+                               error("invalid snaplen %s", optarg);
+                       else if (snaplen == 0)
+                               snaplen = MAXIMUM_SNAPLEN;
+                       break;
+               }
+
+               case 'B':
+                       bufsize = atoi(optarg)*1024;
+                       if (bufsize <= 0)
+                               error("invalid packet buffer size %s", optarg);
+                       useactivate = 1;        /* required for bufsize */
+                       break;
+
+               case 'a':
+                       useactivate = 1;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       if (useactivate) {
+               pd = pcap_create(device, ebuf);
+               if (pd == NULL)
+                       error("%s", ebuf);
+               status = pcap_set_snaplen(pd, snaplen);
+               if (status != 0)
+                       error("%s: pcap_set_snaplen failed: %s",
+                           device, pcap_statustostr(status));
+               if (dopromisc) {
+                       status = pcap_set_promisc(pd, 1);
+                       if (status != 0)
+                               error("%s: pcap_set_promisc failed: %s",
+                                   device, pcap_statustostr(status));
+               }
+               if (dorfmon) {
+                       status = pcap_set_rfmon(pd, 1);
+                       if (status != 0)
+                               error("%s: pcap_set_rfmon failed: %s",
+                                   device, pcap_statustostr(status));
+               }
+               status = pcap_set_timeout(pd, 1000);
+               if (status != 0)
+                       error("%s: pcap_set_timeout failed: %s",
+                           device, pcap_statustostr(status));
+               if (bufsize != 0) {
+                       status = pcap_set_buffer_size(pd, bufsize);
+                       if (status != 0)
+                               error("%s: pcap_set_buffer_size failed: %s",
+                                   device, pcap_statustostr(status));
+               }
+               status = pcap_activate(pd);
+               if (status < 0) {
+                       /*
+                        * pcap_activate() failed.
+                        */
+                       error("%s: %s\n(%s)", device,
+                           pcap_statustostr(status), pcap_geterr(pd));
+               } else if (status > 0) {
+                       /*
+                        * pcap_activate() succeeded, but it's warning us
+                        * of a problem it had.
+                        */
+                       warning("%s: %s\n(%s)", device,
+                           pcap_statustostr(status), pcap_geterr(pd));
+               }
+       } else {
+               *ebuf = '\0';
+               pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+               if (pd == NULL)
+                       error("%s", ebuf);
+               else if (*ebuf)
+                       warning("%s", ebuf);
+       }
+       pcap_close(pd);
+       exit(status < 0 ? 1 : 0);
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr,
+           "Usage: %s [ -Ipa ] [ -i interface ] [ -s snaplen ] [ -B bufsize ]\n",
+           program_name);
+       exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: WARNING: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+}
diff --git a/tests/reactivatetest.c b/tests/reactivatetest.c
new file mode 100644 (file)
index 0000000..9031a64
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+/* Forwards */
+static void error(const char *, ...);
+
+int
+main(void)
+{
+       char ebuf[PCAP_ERRBUF_SIZE];
+       pcap_t *pd;
+       int status = 0;
+
+       pd = pcap_open_live("lo0", 65535, 0, 1000, ebuf);
+       if (pd == NULL) {
+               pd = pcap_open_live("lo", 65535, 0, 1000, ebuf);
+               if (pd == NULL) {
+                       error("Neither lo0 nor lo could be opened: %s",
+                           ebuf);
+                       return 2;
+               }
+       }
+       status = pcap_activate(pd);
+       if (status != PCAP_ERROR_ACTIVATED) {
+               if (status == 0)
+                       error("pcap_activate() of opened pcap_t succeeded");
+               else if (status == PCAP_ERROR)
+                       error("pcap_activate() of opened pcap_t failed with %s, not PCAP_ERROR_ACTIVATED",
+                           pcap_geterr(pd));
+               else
+                       error("pcap_activate() of opened pcap_t failed with %s, not PCAP_ERROR_ACTIVATED",
+                           pcap_statustostr(status));
+       }
+       return 0;
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "reactivatetest: ");
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
diff --git a/tests/selpolltest.c b/tests/selpolltest.c
new file mode 100644 (file)
index 0000000..d94fb56
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <poll.h>
+
+char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...);
+static void warning(const char *, ...);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       register int op;
+       bpf_u_int32 localnet, netmask;
+       register char *cp, *cmdbuf, *device;
+       int doselect, dopoll, dotimeout, dononblock;
+       struct bpf_program fcode;
+       char ebuf[PCAP_ERRBUF_SIZE];
+       int selectable_fd;
+       int status;
+       int packet_count;
+
+       device = NULL;
+       doselect = 0;
+       dopoll = 0;
+       dotimeout = 0;
+       dononblock = 0;
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "i:sptn")) != -1) {
+               switch (op) {
+
+               case 'i':
+                       device = optarg;
+                       break;
+
+               case 's':
+                       doselect = 1;
+                       break;
+
+               case 'p':
+                       dopoll = 1;
+                       break;
+
+               case 't':
+                       dotimeout = 1;
+                       break;
+
+               case 'n':
+                       dononblock = 1;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       if (doselect && dopoll) {
+               fprintf(stderr, "selpolltest: choose select (-s) or poll (-p), but not both\n");
+               return 1;
+       }
+       if (dotimeout && !doselect && !dopoll) {
+               fprintf(stderr, "selpolltest: timeout (-t) requires select (-s) or poll (-p)\n");
+               return 1;
+       }
+       if (device == NULL) {
+               device = pcap_lookupdev(ebuf);
+               if (device == NULL)
+                       error("%s", ebuf);
+       }
+       *ebuf = '\0';
+       pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+       if (pd == NULL)
+               error("%s", ebuf);
+       else if (*ebuf)
+               warning("%s", ebuf);
+       if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+               localnet = 0;
+               netmask = 0;
+               warning("%s", ebuf);
+       }
+       cmdbuf = copy_argv(&argv[optind]);
+
+       if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+               error("%s", pcap_geterr(pd));
+
+       if (pcap_setfilter(pd, &fcode) < 0)
+               error("%s", pcap_geterr(pd));
+       if (pcap_get_selectable_fd(pd) == -1)
+               error("pcap_get_selectable_fd() fails");
+       if (dononblock) {
+               if (pcap_setnonblock(pd, 1, ebuf) == -1)
+                       error("pcap_setnonblock failed: %s", ebuf);
+       }
+       selectable_fd = pcap_get_selectable_fd(pd);
+       printf("Listening on %s\n", device);
+       if (doselect) {
+               for (;;) {
+                       fd_set setread, setexcept;
+                       struct timeval seltimeout;
+
+                       FD_ZERO(&setread);
+                       FD_SET(selectable_fd, &setread);
+                       FD_ZERO(&setexcept);
+                       FD_SET(selectable_fd, &setexcept);
+                       if (dotimeout) {
+                               seltimeout.tv_sec = 0;
+                               seltimeout.tv_usec = 1000;
+                               status = select(selectable_fd + 1, &setread,
+                                   NULL, &setexcept, &seltimeout);
+                       } else {
+                               status = select(selectable_fd + 1, &setread,
+                                   NULL, &setexcept, NULL);
+                       }
+                       if (status == -1) {
+                               printf("Select returns error (%s)\n",
+                                   strerror(errno));
+                       } else {
+                               if (status == 0)
+                                       printf("Select timed out: ");
+                               else
+                                       printf("Select returned a descriptor: ");
+                               if (FD_ISSET(selectable_fd, &setread))
+                                       printf("readable, ");
+                               else
+                                       printf("not readable, ");
+                               if (FD_ISSET(selectable_fd, &setexcept))
+                                       printf("exceptional condition\n");
+                               else
+                                       printf("no exceptional condition\n");
+                               packet_count = 0;
+                               status = pcap_dispatch(pd, -1, countme,
+                                   (u_char *)&packet_count);
+                               if (status < 0)
+                                       break;
+                               printf("%d packets seen, %d packets counted after select returns\n",
+                                   status, packet_count);
+                       }
+               }
+       } else if (dopoll) {
+               for (;;) {
+                       struct pollfd fd;
+                       int polltimeout;
+
+                       fd.fd = selectable_fd;
+                       fd.events = POLLIN;
+                       if (dotimeout)
+                               polltimeout = 1;
+                       else
+                               polltimeout = -1;
+                       status = poll(&fd, 1, polltimeout);
+                       if (status == -1) {
+                               printf("Poll returns error (%s)\n",
+                                   strerror(errno));
+                       } else {
+                               if (status == 0)
+                                       printf("Poll timed out\n");
+                               else {
+                                       printf("Poll returned a descriptor: ");
+                                       if (fd.revents & POLLIN)
+                                               printf("readable, ");
+                                       else
+                                               printf("not readable, ");
+                                       if (fd.revents & POLLERR)
+                                               printf("exceptional condition, ");
+                                       else
+                                               printf("no exceptional condition, ");
+                                       if (fd.revents & POLLHUP)
+                                               printf("disconnect, ");
+                                       else
+                                               printf("no disconnect, ");
+                                       if (fd.revents & POLLNVAL)
+                                               printf("invalid\n");
+                                       else
+                                               printf("not invalid\n");
+                               }
+                               packet_count = 0;
+                               status = pcap_dispatch(pd, -1, countme,
+                                   (u_char *)&packet_count);
+                               if (status < 0)
+                                       break;
+                               printf("%d packets seen, %d packets counted after poll returns\n",
+                                   status, packet_count);
+                       }
+               }
+       } else {
+               for (;;) {
+                       packet_count = 0;
+                       status = pcap_dispatch(pd, -1, countme,
+                           (u_char *)&packet_count);
+                       if (status < 0)
+                               break;
+                       printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+                           status, packet_count);
+               }
+       }
+       if (status == -2) {
+               /*
+                * We got interrupted, so perhaps we didn't
+                * manage to finish a line we were printing.
+                * Print an extra newline, just in case.
+                */
+               putchar('\n');
+       }
+       (void)fflush(stdout);
+       if (status == -1) {
+               /*
+                * Error.  Report it.
+                */
+               (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+                   program_name, pcap_geterr(pd));
+       }
+       pcap_close(pd);
+       exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+       int *counterp = (int *)user;
+
+       (*counterp)++;
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
+           program_name);
+       exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: WARNING: ", program_name);
+       va_start(ap, fmt);
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+       register char **p;
+       register u_int len = 0;
+       char *buf;
+       char *src, *dst;
+
+       p = argv;
+       if (*p == 0)
+               return 0;
+
+       while (*p)
+               len += strlen(*p++) + 1;
+
+       buf = (char *)malloc(len);
+       if (buf == NULL)
+               error("copy_argv: malloc");
+
+       p = argv;
+       dst = buf;
+       while ((src = *p++) != NULL) {
+               while ((*dst++ = *src++) != '\0')
+                       ;
+               dst[-1] = ' ';
+       }
+       dst[-1] = '\0';
+
+       return buf;
+}