]> The Tcpdump Group git mirrors - libpcap/commitdiff
Initial revision
authormcr <mcr>
Thu, 7 Oct 1999 23:46:40 +0000 (23:46 +0000)
committermcr <mcr>
Thu, 7 Oct 1999 23:46:40 +0000 (23:46 +0000)
53 files changed:
CHANGES [new file with mode: 0644]
FILES [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
README [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]
VERSION [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
bpf/net/bpf.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]
config.guess [new file with mode: 0755]
config.sub [new file with mode: 0755]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
etherent.c [new file with mode: 0644]
ethertype.h [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]
inet.c [new file with mode: 0644]
install-sh [new file with mode: 0755]
lbl/gnuc.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]
linux-include/netinet/if_ether.h [new file with mode: 0644]
linux-include/netinet/ip_var.h [new file with mode: 0644]
mkdep [new file with mode: 0755]
nametoaddr.c [new file with mode: 0644]
optimize.c [new file with mode: 0644]
pcap-bpf.c [new file with mode: 0644]
pcap-dlpi.c [new file with mode: 0644]
pcap-enet.c [new file with mode: 0644]
pcap-int.h [new file with mode: 0644]
pcap-linux.c [new file with mode: 0644]
pcap-namedb.h [new file with mode: 0644]
pcap-nit.c [new file with mode: 0644]
pcap-nit.h [new file with mode: 0644]
pcap-null.c [new file with mode: 0644]
pcap-pf.c [new file with mode: 0644]
pcap-pf.h [new file with mode: 0644]
pcap-snit.c [new file with mode: 0644]
pcap-snoop.c [new file with mode: 0644]
pcap.3 [new file with mode: 0644]
pcap.c [new file with mode: 0644]
pcap.h [new file with mode: 0644]
ppp.h [new file with mode: 0644]
savefile.c [new file with mode: 0644]
scanner.l [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..eb25706
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,267 @@
+@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.47 1999-10-07 23:46:40 mcr Exp $ (LBL)
+
+v0.4 Sat Jul 25 12:40:09 PDT 1998
+
+- Fix endian problem with DLT_NULL devices. From FreeBSD via Bill
+  Fenner ([email protected])
+
+- 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 [email protected] (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 ([email protected])
+
+- 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 ([email protected])
+
+- 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
+
+- Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to
+  Richard Allen ([email protected]) and Steinar Haug ([email protected])
+
+- Fddi supports broadcast as reported by Jeff Macdonald
+  ([email protected]). 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 ([email protected])
+
+- Fix some linux alignment problems.
+
+- Document promisc argument to pcap_open_live(). Reported by Ian Marsh
+
+- Support Metricom radio packets under Linux. Thanks to Kevin Lai
+
+- Bind to interface name under Linux to avoid packets from multiple
+  interfaces on multi-homed hosts. Thanks to Kevin Lai
+
+- Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts
+
+- Fixed an uninitialized memory reference found by Kent Vander Velden
+
+- Fixed lex pattern for IDs to allow leading digits. As reported by
+  Theo de Raadt ([email protected])
+
+- 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 ([email protected])
+
+- 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 ([email protected])
+
+v0.3 Sat Nov 30 20:56:27 PST 1996
+
+- Added Linux support.
+
+- Fixed savefile bugs.
+
+- Solaris x86 fix from Tim Rylance ([email protected])
+
+- Add support for bpf kernel port filters.
+
+- Remove duplicate atalk protocol table entry. Thanks to Christian
+  Hopps ([email protected])
+
+- Fixed pcap_lookupdev() to ignore nonexistent devices. This was
+  reported to happen under BSD/OS by David Vincenzetti
+
+- Avoid solaris compiler warnings. Thanks to Bruce Barnett
+
+v0.2.1 Sun Jul 14 03:02:26 PDT 1996
+
+- Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram
+  ([email protected]) and Rick Jones ([email protected])
+
+- Added support for SINIX. Thanks to Andrej Borsenkow
+
+- Fixes for AIX (although this system is not yet supported). Thanks to
+  John Hawkinson ([email protected])
+
+- 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 ([email protected])
+
+- Fixed padding problems in the pf module.
+
+- Fixed some more alignment problems on the alpha.
+
+- Added explicit netmask support. Thanks to Steve Nuchia
+
+- 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 ([email protected])
+
+- 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
+
+- Removed obsolete reference to pcap_immediate() from the man page.
+  Michael Stolarchuk ([email protected])
+
+- DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig
+
+v0.2 Sun Jun 23 02:28:42 PDT 1996
+
+- Add support for HP-UX. Resulted from code contributed by Tom Murray
+  ([email protected]) and Philippe-Andri Prindeville
+
+- Update INSTALL with a reminder to install include files. Thanks to
+  Mark Andrews ([email protected])
+
+- 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 ([email protected])
+
+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
+  ([email protected]) for pointing this out.
+
+- Removed FDDI ifdef's, they aren't really needed. Resulted from report
+  by Gary Veum ([email protected]).
+
+- 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 ([email protected]).
+
+- Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin
+
+- Port to GNU autoconf.
+
+- Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming
+  Johansen ([email protected]).
+
+- Handle multi-digit interface unit numbers (aka ppa's) under dlpi.
+  Resulted from report by Daniel Ehrlich ([email protected]).
+
+- Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report
+  by Jeff Murphy ([email protected]).
+
+- Add support for "long jumps". Thanks to Jeffrey Mogul
+
+- Fix minor problems when compiling with BDEBUG as noticed by Scott
+  Bertilson ([email protected]).
+
+- Declare sys_errlist "const char *const" to avoid problems under
+  FreeBSD. Resulted from report by [email protected].
+
+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 ([email protected]).
+
+- Fixed configure to test for snoop before dlpi to avoid problems under
+  IRIX 5. Thanks to J. Eric Townsend ([email protected]).
+
+- 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 ([email protected]).
+
+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 ([email protected]).
+
+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
+  ([email protected]) and Danny Mitzel ([email protected]).
+
+- 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
+
+- Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported
+  by Elan Amir ([email protected]).
+
+- 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/FILES b/FILES
new file mode 100644 (file)
index 0000000..daad279
--- /dev/null
+++ b/FILES
@@ -0,0 +1,50 @@
+CHANGES
+FILES
+INSTALL
+Makefile.in
+README
+SUNOS4
+VERSION
+aclocal.m4
+bpf/net/bpf.h
+bpf/net/bpf_filter.c
+bpf_image.c
+config.guess
+config.sub
+configure
+configure.in
+etherent.c
+ethertype.h
+gencode.c
+gencode.h
+grammar.y
+inet.c
+install-sh
+lbl/gnuc.h
+lbl/os-solaris2.h
+lbl/os-sunos4.h
+lbl/os-ultrix4.h
+linux-include/netinet/if_ether.h
+linux-include/netinet/ip_var.h
+mkdep
+nametoaddr.c
+optimize.c
+pcap-bpf.c
+pcap-dlpi.c
+pcap-enet.c
+pcap-int.h
+pcap-linux.c
+pcap-namedb.h
+pcap-nit.c
+pcap-nit.h
+pcap-null.c
+pcap-pf.c
+pcap-pf.h
+pcap-snit.c
+pcap-snoop.c
+pcap.3
+pcap.c
+pcap.h
+ppp.h
+savefile.c
+scanner.l
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..3276b35
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,328 @@
+@(#) $Header: /tcpdump/master/libpcap/Attic/INSTALL,v 1.42 1999-10-07 23:46:40 mcr Exp $ (LBL)
+
+To build libpcap, first customize any paths in Makefile.in, then 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", "make install-incl" and "make
+install-man". 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://prep.ai.mit.edu/pub/gnu/gcc-*.tar.gz
+
+Note well: If you use gcc, you may need to run its "fixincludes"
+script. Running fixincludes is not required with later versions of gcc
+and in some cases (e.g. Solaris 2.5) causes problems when run. The
+configure script will abort with:
+
+    checking for ANSI ioctl definitions... yes
+    configure: error: see the INSTALL for more info
+
+if it detects if the fixincludes needs to be run. If the fixincludes
+test in configure passes, you're probably ok.
+
+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 OSF, 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
+
+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.
+
+It's been reported that 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 promiscous more than one promiscuous mode
+at a time. Finally, testing shows that there can't be more than one
+simultaneous dlpi user per network interface and you cannot capture
+outbound packets.
+
+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 can cause problems since promiscuous
+mode is implemented by twiddlin the interface flags from the libpcap
+application. 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 the Network Research Group at LBNL never
+generated a release with this version number. We note 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. We also note with annoyance that 90% of the Linux
+related bug reports we get are due to changes made to unofficial
+versions of our page. If you are having trouble but aren't using a
+version that came from ftp.ee.lbl.gov, please try that before
+submitting a bug report!
+
+If you use AIX, you may not be able to build libpcap from this release.
+Although AIX 4 ships with tcpdump, it is an old version that predates
+libpcap. 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. Also, it may be necessary to run the configure
+script as root in order for it to detect that bpf is available. Another
+workaround is to use:
+
+    ./configure --with-pcap=bpf
+
+If you use NeXTSTEP, you will not be able to build libpcap from this
+release. We hope to support this operating system in some future
+release of libpcap.
+
+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. Since SCO apparently supports
+dlpi, it's possible the current version works. Meanwhile, sco provides
+a tcpdump binary as part of their "Network/Security Tools" package:
+
+    http://www.sco.com/technology/internet/goodies/#SECURITY
+
+There is also a README that explains how to enable packet capture.
+
+If you use UnixWare, you will not be able to build libpcap from this
+release. We hope to support this operating system in some future
+release of libpcap. Meanwhile, there appears to be an UnixWare port of
+libpcap 0.0 (and tcpdump 3.0) in:
+
+    ftp://ftp1.freebird.org/pub/mirror/freebird/internet/systools/
+
+UnixWare appears to use a hacked version of DLPI.
+
+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://prep.ai.mit.edu/pub/gnu/bison.tar.gz
+
+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
+FILES          - list of files exported as part of the distribution
+INSTALL                - this file
+Makefile.in    - compilation rules (input to the configure script)
+README         - description of distribution
+SUNOS4         - pre-SunOS 4.1 replacement kernel nit modules
+VERSION                - version of this release
+aclocal.m4     - autoconf macros
+bpf/net                - copies of bpf_filter.c and bpf.h
+bpf_filter.c   - symlink to bpf/net/bpf_filter.c
+bpf_image.c    - bpf disassembly routine
+config.guess   - autoconf support
+config.sub     - autoconf support
+configure      - configure script (run this first)
+configure.in   - configure script source
+etherent.c     - /etc/ethers support routines
+ethertype.h    - ethernet protocol types and names definitions
+gencode.c      - bpf code generation routines
+gencode.h      - bpf code generation definitions
+grammar.y      - filter string grammar
+inet.c         - network routines
+install-sh     - BSD style install script
+lbl/gnuc.h     - gcc macros and defines
+lbl/os-*.h     - os dependent defines and prototypes
+linux-include/*        - network include files missing on Linux
+mkdep          - construct Makefile dependency list
+nametoaddr.c   - hostname to address routines
+net            - symlink to bpf/net
+optimize.c     - bpf optimization routines
+pcap-bpf.c     - BSD Packet Filter support
+pcap-dlpi.c    - Data Link Provider Interface support
+pcap-enet.c    - enet support
+pcap-int.h     - internal libpcap definitions
+pcap-namedb.h  - public libpcap name database definitions
+pcap-nit.c     - Network Interface Tap support
+pcap-nit.h     - Network Interface Tap definitions
+pcap-null.c    - dummy monitor support (allows offline use of libpcap)
+pcap-pf.c      - Packet Filter support
+pcap-pf.h      - Packet Filter definitions
+pcap-snit.c    - Streams based Network Interface Tap support
+pcap-snoop.c   - Snoop network monitoring support
+pcap.3         - manual entry
+pcap.c         - pcap utility routines
+pcap.h         - public libpcap definitions
+ppp.h          - Point to Point Protocol definitions
+savefile.c     - offline support
+scanner.l      - filter string scanner
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..bed27b3
--- /dev/null
@@ -0,0 +1,163 @@
+#  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.72 1999-10-07 23:46:40 mcr Exp $ (LBL)
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+# Pathname of directory to install the include files
+INCLDEST = @includedir@
+# Pathname of directory to install the library
+LIBDEST =  @libdir@
+# Pathname of directory to install the man page
+MANDEST = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+CC = @CC@
+CCOPT = @V_CCOPT@
+INCLS = -I. @V_INCLS@
+DEFS = @DEFS@
+
+# Standard CFLAGS
+CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
+
+INSTALL = @INSTALL@
+RANLIB = @V_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) $(CFLAGS) -c $(srcdir)/$*.c
+
+PSRC = pcap-@[email protected]
+CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \
+       etherent.c savefile.c bpf_filter.c bpf_image.c
+GENSRC = scanner.c grammar.c version.c
+
+SRC =  $(PSRC) $(CSRC) $(GENSRC)
+
+# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+# hack the extra indirection
+OBJ =  $(PSRC:.c=.o) $(CSRC:.c=.o) $(GENSRC:.c=.o)
+HDR =  pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \
+       ethertype.h gencode.h gnuc.h
+GENHDR = \
+       tokdefs.h
+
+TAGHDR = \
+       bpf/net/bpf.h
+
+TAGFILES = \
+       $(SRC) $(HDR) $(TAGHDR)
+
+CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c
+
+all: libpcap.a
+
+libpcap.a: $(OBJ)
+       @rm -f $@
+       ar rc $@ $(OBJ)
+       $(RANLIB) $@
+
+scanner.c: $(srcdir)/scanner.l
+       @rm -f $@
+       $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@
+
+scanner.o: scanner.c tokdefs.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) $(CFLAGS) -Dyylval=pcap_lval -c grammar.c
+
+version.o: version.c
+version.c: $(srcdir)/VERSION
+       @rm -f $@
+       sed -e 's/.*/char pcap_version[] = "&";/' $(srcdir)/VERSION > $@
+
+install: force
+       $(INSTALL) -m 444 -o bin -g bin libpcap.a $(DESTDIR)$(LIBDEST)/libpcap.a
+       $(RANLIB) $(DESTDIR)$(LIBDEST)/libpcap.a
+
+install-incl: force
+       $(INSTALL) -m 444 -o bin -g bin $(srcdir)/pcap.h \
+           $(DESTDIR)$(INCLDEST)/pcap.h
+       $(INSTALL) -m 444 -o bin -g bin $(srcdir)/pcap-namedb.h \
+           $(DESTDIR)$(INCLDEST)/pcap-namedb.h
+       $(INSTALL) -m 444 -o bin -g bin $(srcdir)/net/bpf.h \
+           $(DESTDIR)$(INCLDEST)/net/bpf.h
+
+install-man: force
+       $(INSTALL) -m 444 -o bin -g bin $(srcdir)/pcap.3 \
+           $(DESTDIR)$(MANDEST)/man3/pcap.3
+
+clean:
+       rm -f $(CLEANFILES)
+
+distclean:
+       rm -f $(CLEANFILES) Makefile config.cache config.log config.status \
+           gnuc.h os-proto.h bpf_filter.c net
+
+tags: $(TAGFILES)
+       ctags -wtd $(TAGFILES)
+
+tar:   force
+       @cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \
+           list="" ; tar="tar chFFf" ; \
+           for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \
+           echo \
+           "rm -f ../$$name; ln -s $$dir ../$$name" ; \
+            rm -f ../$$name; ln -s $$dir ../$$name ; \
+           echo \
+           "(cd .. ; $$tar - [lots of files]) | compress > /tmp/$$name.tar.Z" ; \
+            (cd .. ; $$tar - $$list) | compress > /tmp/$$name.tar.Z ; \
+           echo \
+           "rm -f ../$$name" ; \
+            rm -f ../$$name
+
+force: /tmp
+depend:        $(GENSRC) force
+       ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..7c40a30
--- /dev/null
+++ b/README
@@ -0,0 +1,49 @@
+@(#) $Header: /tcpdump/master/libpcap/README,v 1.18 1999-10-07 23:46:40 mcr Exp $ (LBL)
+
+LIBPCAP 0.4
+Lawrence Berkeley National Laboratory
+Network Research Group
+ftp://ftp.ee.lbl.gov/libpcap.tar.Z
+
+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.
+
+Note well: this interface is new and is likely to change.
+
+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 is in:
+
+       ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z.
+
+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/386, NetBSD, and FreeBSD.  DEC OSF/1
+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:
+
+       ftp://gatekeeper.dec.com/pub/DEC/net/bpfext42.tar.Z.
+
+Problems, bugs, questions, desirable enhancements, source code
+contributions, etc., should be sent to the email address
+
+ - Steve McCanne
+   Craig Leres
+   Van Jacobson
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/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..bd73f47
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.4
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..a0e489e
--- /dev/null
@@ -0,0 +1,706 @@
+dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.63 1999-10-07 23:46:40 mcr 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 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.12)
+    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 "$target_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
+    AC_PROG_CC
+    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 "$target_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"
+                           V_CCOPT="-Aa $V_CCOPT"
+                           AC_DEFINE(_HPUX_SOURCE)
+                           ;;
+
+                   *)
+                           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 "$target_os" in
+
+           irix*)
+                   V_CCOPT="$V_CCOPT -xansi -signed -g3"
+                   ;;
+
+           osf*)
+                   V_CCOPT="$V_CCOPT -std1 -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,)
+                   fi
+                   ;;
+           esac
+    fi
+])
+
+dnl
+dnl Use pfopen.c if available and pfopen() not in standard libraries
+dnl Require libpcap
+dnl Look for libpcap in ..
+dnl Use the installed libpcap if there is no local version
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_LIBPCAP(pcapdep, incls)
+dnl
+dnl results:
+dnl
+dnl    $1 (pcapdep set)
+dnl    $2 (incls appended)
+dnl    LIBS
+dnl    LBL_LIBS
+dnl
+AC_DEFUN(AC_LBL_LIBPCAP,
+    [AC_REQUIRE([AC_LBL_LIBRARY_NET])
+    dnl
+    dnl save a copy before locating libpcap.a
+    dnl
+    LBL_LIBS="$LIBS"
+    pfopen=/usr/examples/packetfilter/pfopen.c
+    if test -f $pfopen ; then
+           AC_CHECK_FUNCS(pfopen)
+           if test $ac_cv_func_pfopen = "no" ; then
+                   AC_MSG_RESULT(Using $pfopen)
+                   LIBS="$LIBS $pfopen"
+           fi
+    fi
+    AC_MSG_CHECKING(for local pcap library)
+    libpcap=FAIL
+    lastdir=FAIL
+    places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \
+       egrep '/libpcap-[[0-9]]*\.[[0-9]]*(\.[[0-9]]*)?([[ab]][[0-9]]*)?$'`
+    for dir in $places ../libpcap libpcap ; do
+           basedir=`echo $dir | sed -e 's/[[ab]][[0-9]]*$//'`
+           if test $lastdir = $basedir ; then
+                   dnl skip alphas when an actual release is present
+                   continue;
+           fi
+           lastdir=$dir
+           if test -r $dir/pcap.c ; then
+                   libpcap=$dir/libpcap.a
+                   d=$dir
+                   dnl continue and select the last one that exists
+           fi
+    done
+    if test $libpcap = FAIL ; then
+           AC_MSG_RESULT(not found)
+           AC_CHECK_LIB(pcap, main, libpcap="-lpcap")
+           if test $libpcap = FAIL ; then
+                   AC_MSG_ERROR(see the INSTALL doc for more info)
+           fi
+    else
+           $1=$libpcap
+           $2="-I$d $$2"
+           AC_MSG_RESULT($libpcap)
+    fi
+    LIBS="$libpcap $LIBS"
+    case "$target_os" in
+
+    aix*)
+           pseexe="/lib/pse.exp"
+           AC_MSG_CHECKING(for $pseexe)
+           if test -f $pseexe ; then
+                   AC_MSG_RESULT(yes)
+                   LIBS="$LIBS -I:$pseexe"
+           fi
+           ;;
+    esac])
+
+dnl
+dnl Define RETSIGTYPE and RETSIGVAL
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_TYPE_SIGNAL
+dnl
+dnl results:
+dnl
+dnl    RETSIGTYPE (defined)
+dnl    RETSIGVAL (defined)
+dnl
+AC_DEFUN(AC_LBL_TYPE_SIGNAL,
+    [AC_BEFORE([$0], [AC_LBL_LIBPCAP])
+    AC_TYPE_SIGNAL
+    if test "$ac_cv_type_signal" = void ; then
+           AC_DEFINE(RETSIGVAL,)
+    else
+           AC_DEFINE(RETSIGVAL,(0))
+    fi
+    case "$target_os" in
+
+    irix*)
+           AC_DEFINE(_BSD_SIGNALS)
+           ;;
+
+    *)
+           dnl prefer sigset() to sigaction()
+           AC_CHECK_FUNCS(sigset)
+           if test $ac_cv_func_sigset = no ; then
+                   AC_CHECK_FUNCS(sigaction)
+           fi
+           ;;
+    esac])
+
+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)
+    else
+           AC_DEFINE(DECLWAITSTATUS,int)
+    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 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)
+    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 conftest*])
+    AC_MSG_RESULT($ac_cv_lbl_have_run_path)
+    ])
+
+dnl
+dnl Due to the stupid way it's implemented, AC_CHECK_TYPE is nearly useless.
+dnl
+dnl usage:
+dnl
+dnl    AC_LBL_CHECK_TYPE
+dnl
+dnl results:
+dnl
+dnl    int32_t (defined)
+dnl    u_int32_t (defined)
+dnl
+AC_DEFUN(AC_LBL_CHECK_TYPE,
+    [AC_MSG_CHECKING(for $1 using $CC)
+    AC_CACHE_VAL(ac_cv_lbl_have_$1,
+       AC_TRY_COMPILE([
+#      include "confdefs.h"
+#      include <sys/types.h>
+#      if STDC_HEADERS
+#      include <stdlib.h>
+#      include <stddef.h>
+#      endif],
+       [$1 i],
+       ac_cv_lbl_have_$1=yes,
+       ac_cv_lbl_have_$1=no))
+    AC_MSG_RESULT($ac_cv_lbl_have_$1)
+    if test $ac_cv_lbl_have_$1 = no ; then
+           AC_DEFINE($1, $2)
+    fi])
+
+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 "$target_cpu" in
+
+       alpha|hp*|mips|sparc)
+               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 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)
+    fi])
+
+dnl
+dnl If using gcc and the file .devel exists:
+dnl    Compile with -g (if supported) and -Wall
+dnl    If using gcc 2, 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 "$target_os" in
+
+                   irix6*)
+                           V_CCOPT="$V_CCOPT -n32"
+                           ;;
+
+                   *)
+                           ;;
+                   esac
+           fi
+           os=`echo $target_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)
+           else
+                   AC_MSG_WARN(can't find $name)
+           fi
+    fi])
+
+dnl
+dnl Improved version of AC_CHECK_LIB
+dnl
+dnl Thanks to John Hawkinson ([email protected])
+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
+
+define(AC_LBL_CHECK_LIB,
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing both the library and function name,
+dnl because the test really is for library $1 defining function $2, not
+dnl just for library $1.  Separate tests with the same $1 and different $2's
+dnl 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):
+    AC_CHECK_FUNC(gethostbyname, ,
+       # Some OSes (eg. Solaris) place it in libnsl:
+       AC_LBL_CHECK_LIB(nsl, gethostbyname, , 
+           # Some strange OSes (SINIX) have it in libsocket:
+           AC_LBL_CHECK_LIB(socket, gethostbyname, ,
+               # Unfortunately libsocket sometimes depends on libnsl.
+               # AC_CHECK_LIB's API is essentially broken so the
+               # following ugliness is necessary:
+               AC_LBL_CHECK_LIB(socket, gethostbyname,
+                   LIBS="-lsocket -lnsl $LIBS",
+                   AC_CHECK_LIB(resolv, gethostbyname),
+                   -lnsl))))
+    AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
+       AC_LBL_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", ,
+           -lnsl)))
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    AC_CHECK_LIB(str, putmsg)
+    ])
diff --git a/bpf/net/bpf.h b/bpf/net/bpf.h
new file mode 100644 (file)
index 0000000..8d5cd9f
--- /dev/null
@@ -0,0 +1,264 @@
+/*-
+ * 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/bpf/net/Attic/bpf.h,v 1.36 1999-10-07 23:46:41 mcr Exp $ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+
+/*
+ * Alignment macros.  BPF_WORDALIGN rounds up to the next 
+ * even multiple of BPF_ALIGNMENT. 
+ */
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ *  Structure for BIOCSETF.
+ */
+struct bpf_program {
+       u_int bf_len;
+       struct bpf_insn *bf_insns;
+};
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+       u_int bs_recv;          /* number of packets received */
+       u_int bs_drop;          /* number of packets dropped */
+};
+
+/*
+ * Struct return by BIOCVERSION.  This represents the version number of 
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded.  Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+       u_short bv_major;
+       u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * BPF ioctls
+ *
+ * The first set is for compatibility with Sun's pcc style
+ * header files.  If your using gcc, we assume that you
+ * have run fixincludes so the latter set should work.
+ */
+#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__)
+#define        BIOCGBLEN       _IOR(B,102, u_int)
+#define        BIOCSBLEN       _IOWR(B,102, u_int)
+#define        BIOCSETF        _IOW(B,103, struct bpf_program)
+#define        BIOCFLUSH       _IO(B,104)
+#define BIOCPROMISC    _IO(B,105)
+#define        BIOCGDLT        _IOR(B,106, u_int)
+#define BIOCGETIF      _IOR(B,107, struct ifreq)
+#define BIOCSETIF      _IOW(B,108, struct ifreq)
+#define BIOCSRTIMEOUT  _IOW(B,109, struct timeval)
+#define BIOCGRTIMEOUT  _IOR(B,110, struct timeval)
+#define BIOCGSTATS     _IOR(B,111, struct bpf_stat)
+#define BIOCIMMEDIATE  _IOW(B,112, u_int)
+#define BIOCVERSION    _IOR(B,113, struct bpf_version)
+#define BIOCSTCPF      _IOW(B,114, struct bpf_program)
+#define BIOCSUDPF      _IOW(B,115, struct bpf_program)
+#else
+#define        BIOCGBLEN       _IOR('B',102, u_int)
+#define        BIOCSBLEN       _IOWR('B',102, u_int)
+#define        BIOCSETF        _IOW('B',103, struct bpf_program)
+#define        BIOCFLUSH       _IO('B',104)
+#define BIOCPROMISC    _IO('B',105)
+#define        BIOCGDLT        _IOR('B',106, u_int)
+#define BIOCGETIF      _IOR('B',107, struct ifreq)
+#define BIOCSETIF      _IOW('B',108, struct ifreq)
+#define BIOCSRTIMEOUT  _IOW('B',109, struct timeval)
+#define BIOCGRTIMEOUT  _IOR('B',110, struct timeval)
+#define BIOCGSTATS     _IOR('B',111, struct bpf_stat)
+#define BIOCIMMEDIATE  _IOW('B',112, u_int)
+#define BIOCVERSION    _IOR('B',113, struct bpf_version)
+#define BIOCSTCPF      _IOW('B',114, struct bpf_program)
+#define BIOCSUDPF      _IOW('B',115, struct bpf_program)
+#endif
+
+/*
+ * Structure prepended to each packet.
+ */
+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) */
+};
+/*
+ * Because the structure above is not a multiple of 4 bytes, some compilers
+ * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
+ * Only the kernel needs to know about it; applications use bh_hdrlen.
+ */
+#ifdef KERNEL
+#define SIZEOF_BPF_HDR 18
+#endif
+
+/*
+ * Data-link level type codes.
+ */
+#define DLT_NULL       0       /* no link-layer 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       /* IEEE 802 Networks */
+#define DLT_ARCNET     7       /* ARCNET */
+#define DLT_SLIP       8       /* Serial Line IP */
+#define DLT_PPP                9       /* Point-to-point Protocol */
+#define DLT_FDDI       10      /* FDDI */
+#define DLT_ATM_RFC1483        11      /* LLC/SNAP encapsulated atm */
+#define DLT_RAW                12      /* raw IP */
+#define DLT_SLIP_BSDOS 13      /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS  14      /* BSD/OS Point-to-point Protocol */
+
+/*
+ * The instruction encondings.
+ */
+/* 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_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 }
+
+#ifdef KERNEL
+extern u_int bpf_filter();
+extern void bpfattach();
+extern void bpf_tap();
+extern void bpf_mtap();
+#else
+#if __STDC__
+extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+#endif
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#endif
diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c
new file mode 100644 (file)
index 0000000..b82fcf5
--- /dev/null
@@ -0,0 +1,532 @@
+/*-
+ * 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))
+static const char rcsid[] =
+    "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.33 1999-10-07 23:46:41 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <net/bpf.h>
+
+#ifndef KERNEL
+#include <stdlib.h>
+#endif
+
+#define int32 bpf_int32
+#define u_int32 bpf_u_int32
+
+#ifndef LBL_ALIGN
+#if defined(sparc) || defined(mips) || defined(ibm032) || \
+    defined(__alpha) || defined(__hpux)
+#define LBL_ALIGN
+#endif
+#endif
+
+#ifndef LBL_ALIGN
+#include <netinet/in.h>
+
+#define EXTRACT_SHORT(p)       ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p)                (ntohl(*(u_int32 *)p))
+#else
+#define EXTRACT_SHORT(p)\
+       ((u_short)\
+               ((u_short)*((u_char *)p+0)<<8|\
+                (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+               ((u_int32)*((u_char *)p+0)<<24|\
+                (u_int32)*((u_char *)p+1)<<16|\
+                (u_int32)*((u_char *)p+2)<<8|\
+                (u_int32)*((u_char *)p+3)<<0)
+#endif
+
+#ifdef KERNEL
+#include <sys/mbuf.h>
+#define MINDEX(len, m, k) \
+{ \
+       len = m->m_len; \
+       while (k >= len) { \
+               k -= len; \
+               m = m->m_next; \
+               if (m == 0) \
+                       return 0; \
+               len = m->m_len; \
+       } \
+}
+
+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 || m0->m_len + 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
+ */
+u_int
+bpf_filter(pc, p, wirelen, buflen)
+       register struct bpf_insn *pc;
+       register u_char *p;
+       u_int wirelen;
+       register u_int buflen;
+{
+       register u_int32 A, X;
+       register int k;
+       int32 mem[BPF_MEMWORDS];
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (u_int)-1;
+       A = 0;
+       X = 0;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+#ifdef 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) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((struct mbuf *)p, 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) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((struct mbuf *)p, k, &merr);
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if (k >= buflen) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(len, m, k);
+                               A = mtod(m, 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) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((struct mbuf *)p, 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) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((struct mbuf *)p, 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) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(len, m, k);
+                               A = mtod(m, 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) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(len, m, k);
+                               X = (mtod(m, 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:
+                       pc += pc->k;
+                       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;
+               }
+       }
+}
+
+#ifdef KERNEL
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code.  The code must terminate with either an accept or reject. 
+ * 'valid' is an array for use by the routine (it must be at least
+ * 'len' bytes long).  
+ *
+ * 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)
+       struct bpf_insn *f;
+       int len;
+{
+       register int i;
+       register struct bpf_insn *p;
+
+       for (i = 0; i < len; ++i) {
+               /*
+                * Check that that jumps are forward, and within 
+                * the code block.
+                */
+               p = &f[i];
+               if (BPF_CLASS(p->code) == BPF_JMP) {
+                       register int from = i + 1;
+
+                       if (BPF_OP(p->code) == BPF_JA) {
+                               if (from + p->k >= (unsigned)len)
+                                       return 0;
+                       }
+                       else if (from + p->jt >= len || from + p->jf >= len)
+                               return 0;
+               }
+               /*
+                * Check that memory operations use valid addresses.
+                */
+               if ((BPF_CLASS(p->code) == BPF_ST ||
+                    (BPF_CLASS(p->code) == BPF_LD && 
+                     (p->code & 0xe0) == BPF_MEM)) &&
+                   (p->k >= BPF_MEMWORDS || p->k < 0))
+                       return 0;
+               /*
+                * Check for constant division by 0.
+                */
+               if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+                       return 0;
+       }
+       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
+#endif
diff --git a/bpf_dump.c b/bpf_dump.c
new file mode 100644 (file)
index 0000000..33c390f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.9 1999-10-07 23:47:09 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include "interface.h"
+
+extern void bpf_dump(struct bpf_program *, int);
+
+void
+bpf_dump(struct bpf_program *p, int option)
+{
+       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..66265c8
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.22 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+char *
+bpf_image(p, n)
+       struct bpf_insn *p;
+       int n;
+{
+       int v;
+       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)sprintf(operand, fmt, v);
+       (void)sprintf(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/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..e9e4455
--- /dev/null
@@ -0,0 +1,693 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
+
+# Written by Per Bothner <[email protected]>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# 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.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# ([email protected] 8/24/94.)
+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
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    alpha:OSF1:*:*)
+       # 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 alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+       exit 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-cbm-sysv4
+       exit 0;;
+    amiga:NetBSD:*:*)
+      echo m68k-cbm-netbsd${UNAME_RELEASE}
+      exit 0 ;;
+    amiga:OpenBSD:*:*)
+      echo m68k-cbm-openbsd${UNAME_RELEASE}
+      exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+       # [email protected] (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 0 ;;
+    NILE:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:NetBSD:*:*)
+       echo m68k-atari-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:OpenBSD:*:*)
+       echo m68k-atari-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3*:NetBSD:*:*)
+       echo m68k-sun-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3*:OpenBSD:*:*)
+       echo m68k-sun-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:NetBSD:*:*)
+       echo m68k-apple-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-apple-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       sed 's/^        //' << EOF >dummy.c
+       int main (argc, argv) int argc; char **argv; {
+       #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-cc} dummy.c -o dummy \
+         && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && rm dummy.c dummy && exit 0
+       rm -f dummy.c dummy
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+       if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+            -o ${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 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????: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 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i?86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               sed 's/^                //' << EOF >dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+               rm -f dummy.c dummy
+               echo rs6000-ibm-aix3.2.5
+       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 0 ;;
+    *:AIX:*:4)
+       if /usr/sbin/lsattr -EHl proc0 | 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=4.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[3478]??:HP-UX:*:*)
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+           9000/8?? )            HP_ARCH=hppa1.0 ;;
+       esac
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       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-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+       rm -f dummy.c dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i?86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+       echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE}
+       exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+       exit 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE}
+       exit 0 ;;
+    CRAY-2:*:*:*)
+       echo cray2-cray-unicos
+        exit 0 ;;
+    F300:UNIX_System_V:*:*)
+        FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    F301:UNIX_System_V:*:*)
+       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+       exit 0 ;;
+    hp3[0-9][05]:NetBSD:*:*)
+       echo m68k-hp-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp3[0-9][05]:OpenBSD:*:*)
+       echo m68k-hp-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    i?86:BSD/386:*:* | *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+    *:NetBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo i386-pc-cygwin32
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin32
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    *:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us.
+       ld_help_string=`ld --help 2>&1`
+       if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+         echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+         echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
+         echo "powerpc-unknown-linux-gnu" ; exit 0
+       elif test "${UNAME_MACHINE}" = "alpha" ; then
+         echo alpha-unknown-linux-gnu ; exit 0
+       elif test "${UNAME_MACHINE}" = "sparc" ; then
+         echo sparc-unknown-linux-gnu ; exit 0
+       else
+         # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
+         # useful --help.  Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
+         test ! -d /usr/lib/ldscripts/. \
+           && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+         # Determine whether the default compiler is a.out or elf
+         cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+  printf ("%s-pc-linux-gnu\n", argv[1]);
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+         ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+         rm -f dummy.c dummy
+       fi ;;
+# 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.
+    i?86:DYNIX/ptx:4*:*)
+       echo i386-sequent-sysv4
+       exit 0 ;;
+    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    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|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    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 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*: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 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    i?86:LynxOS:2.*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *: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 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <[email protected]>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From [email protected].
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <[email protected]>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+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"); 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`;
+  printf ("%s-next-nextstep%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)
+  printf ("vax-dec-bsd\n"); exit (0);
+#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-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# 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 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/config.sub b/config.sub
new file mode 100755 (executable)
index 0000000..0432524
--- /dev/null
@@ -0,0 +1,927 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+#   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, 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.
+
+# 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.
+
+# 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.
+
+if [ x$1 = x ]
+then
+       echo Configuration name missing. 1>&2
+       echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+       echo "or     $0 ALIAS" 1>&2
+       echo where ALIAS is a recognized configuration type. 1>&2
+       exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+       *local*)
+               echo $1
+               exit 0
+               ;;
+       *)
+       ;;
+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
+  linux-gnu*)
+    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)
+               os=
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -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/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               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
+               ;;
+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.
+       tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
+               | arme[lb] | pyramid \
+               | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+               | alpha | we32k | ns16k | clipper | i370 | sh \
+               | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
+               | pdp11 | mips64el | mips64orion | mips64orionel \
+               | sparc | sparclet | sparclite | sparc64)
+               basic_machine=$basic_machine-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[3456]86)
+         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.
+       vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+             | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+             | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+             | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+             | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+             | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+             | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
+             | mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-cbm
+               ;;
+       amigados)
+               basic_machine=m68k-cbm
+               os=-amigados
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-cbm
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       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 | ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       cray2)
+               basic_machine=cray2-cray
+               os=-unicos
+               ;;
+       [ctj]90-cray)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       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
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-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
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i[3456]86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i[3456]86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i[3456]86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i[3456]86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       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
+               ;;
+       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
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+        pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5)
+               basic_machine=i586-intel
+               ;;
+       pentiumpro | p6)
+               basic_machine=i686-intel
+               ;;
+       pentium-* | p5-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       k5)
+               # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+               basic_machine=i586-amd
+               ;;
+       nexen)
+               # We don't have specific support for Nexgen yet, so just call it a Pentium
+               basic_machine=i586-nexgen
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=rs6000-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/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       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
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       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
+               ;;
+       xmp)
+               basic_machine=xmp-cray
+               os=-unicos
+               ;;
+        xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       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.
+       mips)
+               basic_machine=mips-mips
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sparc)
+               basic_machine=sparc-sun
+               ;;
+        cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       *)
+               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.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -unixware* | svr4*)
+               os=-sysv4
+               ;;
+       -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* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -linux-gnu* | -uxpv*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -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|'`
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -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
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        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
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigados
+               ;;
+       *-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
+               ;;
+       f301-fujitsu)
+               os=-uxpv
+               ;;
+       *)
+               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
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -vxsim* | -vxworks*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..6bd9d5f
--- /dev/null
+++ b/configure
@@ -0,0 +1,2137 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --without-gcc           don't use gcc"
+ac_help="$ac_help
+  --with-pcap=TYPE        use packet capture TYPE"
+ac_help="$ac_help
+  --without-flex          don't use flex"
+ac_help="$ac_help
+  --without-bison         don't use bison"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -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 ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$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" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$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)
+    # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$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" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    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)
+    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" ;;
+
+  -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 ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.12"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=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" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=pcap.c
+
+# 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 its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  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
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says [email protected].
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+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
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+#    same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+#    as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:578: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`$ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:599: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+  case $nonopt in
+  NONE) target_alias=$host_alias ;;
+  *) target_alias=$nonopt ;;
+  esac ;;
+esac
+
+target=`$ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:617: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+  case $nonopt in
+  NONE) build_alias=$host_alias ;;
+  *) build_alias=$nonopt ;;
+  esac ;;
+esac
+
+build=`$ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+umask 002
+
+if test -z "$PWD" ; then
+       PWD=`pwd`
+fi
+
+
+    
+    
+    
+    # Check whether --with-gcc or --without-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 "$target_os" in
+
+           bsdi*)
+                   # Extract the first word of "shlicc2", so it can be a program name with args.
+set dummy shlicc2; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:671: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$SHLICC2"; then
+  ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_SHLICC2="yes"
+      break
+    fi
+  done
+  IFS="$ac_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
+  echo "$ac_t""$SHLICC2" 1>&6
+else
+  echo "$ac_t""no" 1>&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
+    # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:711: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:740: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  ac_prog_rejected=no
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_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 $# -gt 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
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:788: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 798 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:822: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:827: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:836: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+  ac_test_CFLAGS="${CFLAGS+set}"
+  ac_save_CFLAGS="$CFLAGS"
+  CFLAGS=
+  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:851: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+  if test "$ac_test_CFLAGS" = set; then
+    CFLAGS="$ac_save_CFLAGS"
+  elif test $ac_cv_prog_cc_g = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-O2"
+  fi
+else
+  GCC=
+  test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+    if test "$GCC" = yes ; then
+           if test "$SHLICC2" = yes ; then
+                   ac_cv_lbl_gcc_vers=2
+                   V_CCOPT="-O2"
+           else
+                   echo $ac_n "checking gcc version""... $ac_c" 1>&6
+echo "configure:884: checking gcc version" >&5
+                   if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&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
+
+                   echo "$ac_t""$ac_cv_lbl_gcc_vers" 1>&6
+                   if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+                           V_CCOPT="-O2"
+                   fi
+           fi
+    else
+           echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6
+echo "configure:902: checking that $CC handles ansi prototypes" >&5
+           if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 907 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+int frob(int, char *)
+; return 0; }
+EOF
+if { (eval echo configure:914: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_cc_ansi_prototypes=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_cc_ansi_prototypes=no
+fi
+rm -f conftest*
+fi
+
+           echo "$ac_t""$ac_cv_lbl_cc_ansi_prototypes" 1>&6
+           if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
+                   case "$target_os" in
+
+                   hpux*)
+                           echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6
+echo "configure:932: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
+                           savedcflags="$CFLAGS"
+                           CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
+                           if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 939 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+int frob(int, char *)
+; return 0; }
+EOF
+if { (eval echo configure:946: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_cc_hpux_cc_aa=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_cc_hpux_cc_aa=no
+fi
+rm -f conftest*
+fi
+
+                           echo "$ac_t""$ac_cv_lbl_cc_hpux_cc_aa" 1>&6
+                           if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
+                                   { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
+                           fi
+                           CFLAGS="$savedcflags"
+                           V_CCOPT="-Aa $V_CCOPT"
+                           cat >> confdefs.h <<\EOF
+#define _HPUX_SOURCE 1
+EOF
+
+                           ;;
+
+                   *)
+                           { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
+                           ;;
+                   esac
+           fi
+           V_INCLS="$V_INCLS -I/usr/local/include"
+           LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+           case "$target_os" in
+
+           irix*)
+                   V_CCOPT="$V_CCOPT -xansi -signed -g3"
+                   ;;
+
+           osf*)
+                   V_CCOPT="$V_CCOPT -std1 -g3"
+                   ;;
+
+           ultrix*)
+                   echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6
+echo "configure:990: checking that Ultrix $CC hacks const in prototypes" >&5
+                   if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 995 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+struct a { int b; };
+                           void c(const struct a *)
+; return 0; }
+EOF
+if { (eval echo configure:1003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_cc_const_proto=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_cc_const_proto=no
+fi
+rm -f conftest*
+fi
+
+                   echo "$ac_t""$ac_cv_lbl_cc_const_proto" 1>&6
+                   if test $ac_cv_lbl_cc_const_proto = no ; then
+                           cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+                   fi
+                   ;;
+           esac
+    fi
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1028: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 1043 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1060 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1066: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in malloc.h sys/ioccom.h sys/sockio.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1092: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1097 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1102: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+if test "$GCC" = yes ; then
+           echo $ac_n "checking for ANSI ioctl definitions""... $ac_c" 1>&6
+echo "configure:1131: checking for ANSI ioctl definitions" >&5
+           if eval "test \"`echo '$''{'ac_cv_lbl_gcc_fixincludes'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1136 "configure"
+#include "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; }
+EOF
+if { (eval echo configure:1155: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_gcc_fixincludes=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_gcc_fixincludes=no
+fi
+rm -f conftest*
+fi
+
+           echo "$ac_t""$ac_cv_lbl_gcc_fixincludes" 1>&6
+           if test $ac_cv_lbl_gcc_fixincludes = no ; then
+                   # Don't cache failure
+                   unset ac_cv_lbl_gcc_fixincludes
+                   { echo "configure: error: see the INSTALL for more info" 1>&2; exit 1; }
+           fi
+    fi
+
+for ac_func in ether_hostton strerror
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1178: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1183 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* 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_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Check whether --with-pcap or --without-pcap was given.
+if test "${with_pcap+set}" = set; then
+  withval="$with_pcap"
+  :
+fi
+
+echo $ac_n "checking packet capture type""... $ac_c" 1>&6
+echo "configure:1238: checking packet capture type" >&5
+if test ! -z "$with_pcap" ; then
+       V_PCAP="$withval"
+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/net/raw.h ; then
+       V_PCAP=snoop
+elif test -r /usr/include/sys/dlpi.h ; then
+       V_PCAP=dlpi
+elif test -r /usr/include/linux/socket.h ; then
+       V_PCAP=linux
+elif test -c /dev/bpf0 ; then          # check again in case not readable
+       V_PCAP=bpf
+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
+echo "$ac_t""$V_PCAP" 1>&6
+
+case "$V_PCAP" in
+
+dlpi)
+       for ac_hdr in sys/bufmod.h sys/dlpi_ext.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1275: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1280 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+       echo $ac_n "checking for /dev/dlpi device""... $ac_c" 1>&6
+echo "configure:1312: checking for /dev/dlpi device" >&5
+       if test -c /dev/dlpi ; then
+               echo "$ac_t""yes" 1>&6
+               cat >> confdefs.h <<\EOF
+#define HAVE_DEV_DLPI 1
+EOF
+
+       else
+               echo "$ac_t""no" 1>&6
+               dir="/dev/dlpi"
+               echo $ac_n "checking for $dir directory""... $ac_c" 1>&6
+echo "configure:1323: checking for $dir directory" >&5
+               if test -d $dir ; then
+                       echo "$ac_t""yes" 1>&6
+                       cat >> confdefs.h <<EOF
+#define PCAP_DEV_PREFIX "$dir"
+EOF
+
+               else
+                       echo "$ac_t""no" 1>&6
+               fi
+       fi
+       ;;
+
+linux)
+       for ac_hdr in net/if_arp.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1341: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1346 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+       echo $ac_n "checking Linux kernel version""... $ac_c" 1>&6
+echo "configure:1378: checking Linux kernel version" >&5
+       if eval "test \"`echo '$''{'ac_cv_linux_vers'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_linux_vers=`uname -r 2>&1 | \
+               sed -n -e '$s/.* //' -e '$s/\..*//p'`
+fi
+
+       echo "$ac_t""$ac_cv_linux_vers" 1>&6
+       if test $ac_cv_linux_vers -lt 2 ; then
+               { echo "configure: error: version 2 or higher required; see the INSTALL doc for more info" 1>&2; exit 1; }
+       fi
+       ;;
+
+null)
+       echo "configure: warning: cannot determine packet capture interface" 1>&2
+       echo "configure: warning: (see the INSTALL doc for more info)" 1>&2
+       ;;
+
+esac
+
+# Check whether --with-flex or --without-flex was given.
+if test "${with_flex+set}" = set; then
+  withval="$with_flex"
+  :
+fi
+
+    # Check whether --with-bison or --without-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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1419: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$V_LEX"; then
+  ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_V_LEX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+V_LEX="$ac_cv_prog_V_LEX"
+if test -n "$V_LEX"; then
+  echo "$ac_t""$V_LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&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
+           echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6
+echo "configure:1452: checking for flex 2.4 or higher" >&5
+           if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&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
+
+           echo "$ac_t""$ac_cv_lbl_flex_v24" 1>&6
+           if test $ac_cv_lbl_flex_v24 = no ; then
+                   s="2.4 or higher required"
+                   echo "configure: warning: ignoring obsolete flex executable ($s)" 1>&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
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1478: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$V_YACC"; then
+  ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_V_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+V_YACC="$ac_cv_prog_V_YACC"
+if test -n "$V_YACC"; then
+  echo "$ac_t""$V_YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&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
+           echo "configure: warning: don't have both flex and bison; reverting to lex/yacc" 1>&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
+
+case "$target_os" in
+
+aix*)
+               cat >> confdefs.h <<\EOF
+#define _SUN 1
+EOF
+
+       ;;
+
+hpux9*)
+       cat >> confdefs.h <<\EOF
+#define HAVE_HPUX9 1
+EOF
+
+       ;;
+
+hpux10.0*)
+       ;;
+
+hpux10.1*)
+       ;;
+
+hpux*)
+               cat >> confdefs.h <<\EOF
+#define HAVE_HPUX10_20 1
+EOF
+
+       ;;
+
+sinix*)
+       echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6
+echo "configure:1552: checking if SINIX compiler defines sinix" >&5
+       if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1557 "configure"
+#include "confdefs.h"
+
+int main() {
+int i = sinix;
+; return 0; }
+EOF
+if { (eval echo configure:1564: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_cc_sinix_defined=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_cc_sinix_defined=no
+fi
+rm -f conftest*
+fi
+
+           echo "$ac_t""$ac_cv_cc_sinix_defined" 1>&6
+           if test $ac_cv_cc_sinix_defined = no ; then
+                   cat >> confdefs.h <<\EOF
+#define sinix 1
+EOF
+
+           fi
+       ;;
+
+solaris*)
+       cat >> confdefs.h <<\EOF
+#define HAVE_SOLARIS 1
+EOF
+
+       ;;
+
+linux*)
+       V_INCLS="$V_INCLS -Ilinux-include"
+       ;;
+esac
+
+for ac_prog in ranlib
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1602: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_V_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$V_RANLIB"; then
+  ac_cv_prog_V_RANLIB="$V_RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_V_RANLIB="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+V_RANLIB="$ac_cv_prog_V_RANLIB"
+if test -n "$V_RANLIB"; then
+  echo "$ac_t""$V_RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$V_RANLIB" && break
+done
+test -n "$V_RANLIB" || V_RANLIB="@true"
+
+
+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 "$target_os" in
+
+                   irix6*)
+                           V_CCOPT="$V_CCOPT -n32"
+                           ;;
+
+                   *)
+                           ;;
+                   esac
+           fi
+           os=`echo $target_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
+                   cat >> confdefs.h <<\EOF
+#define HAVE_OS_PROTO_H 1
+EOF
+
+           else
+                   echo "configure: warning: can't find $name" 1>&2
+           fi
+    fi
+
+echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6
+echo "configure:1672: checking if sockaddr struct has sa_len member" >&5
+    if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1677 "configure"
+#include "confdefs.h"
+
+#      include <sys/types.h>
+#      include <sys/socket.h>
+int main() {
+u_int i = sizeof(((struct sockaddr *)0)->sa_len)
+; return 0; }
+EOF
+if { (eval echo configure:1686: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_lbl_sockaddr_has_sa_len=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_lbl_sockaddr_has_sa_len=no
+fi
+rm -f conftest*
+fi
+
+    echo "$ac_t""$ac_cv_lbl_sockaddr_has_sa_len" 1>&6
+    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
+           cat >> confdefs.h <<\EOF
+#define HAVE_SOCKADDR_SA_LEN 1
+EOF
+
+    fi
+
+echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6
+echo "configure:1707: checking if unaligned accesses fail" >&5
+    if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$target_cpu" in
+
+       alpha|hp*|mips|sparc)
+               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 conftest* core core.conftest
+               ;;
+       esac
+fi
+
+    echo "$ac_t""$ac_cv_lbl_unaligned_fail" 1>&6
+    if test $ac_cv_lbl_unaligned_fail = yes ; then
+           cat >> confdefs.h <<\EOF
+#define LBL_ALIGN 1
+EOF
+
+    fi
+
+if test "${srcdir}" = "." ; then
+       srcdirprefix=""
+else
+       srcdirprefix="./"
+fi
+
+if test -r ${srcdirprefix}lbl/gnuc.h ; then
+       rm -f gnuc.h
+       ln -s ${srcdirprefix}lbl/gnuc.h gnuc.h
+fi
+
+rm -f bpf_filter.c
+ln -s ${srcdirprefix}bpf/net/bpf_filter.c bpf_filter.c
+rm -f net
+ln -s ${srcdirprefix}bpf/net net
+
+
+
+
+
+
+
+
+# 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
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1803: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      for ac_prog in ginstall installbsd scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           # OSF/1 installbsd also uses dspmsg, but is usable.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+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.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&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_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# 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.
+(set) 2>&1 |
+  case `(ac_space=' '; set) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[    `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.12"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@SHLICC2@%$SHLICC2%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@V_LEX@%$V_LEX%g
+s%@V_YACC@%$V_YACC%g
+s%@V_RANLIB@%$V_RANLIB%g
+s%@V_CCOPT@%$V_CCOPT%g
+s%@V_INCLS@%$V_INCLS%g
+s%@V_PCAP@%$V_PCAP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+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..979ff66
--- /dev/null
@@ -0,0 +1,189 @@
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.67 1999-10-07 23:46:40 mcr 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
+
+AC_INIT(pcap.c)
+
+AC_CANONICAL_SYSTEM
+
+umask 002
+
+if test -z "$PWD" ; then
+       PWD=`pwd`
+fi
+
+AC_LBL_C_INIT(V_CCOPT, V_INCLS)
+
+AC_CHECK_HEADERS(malloc.h sys/ioccom.h sys/sockio.h)
+
+AC_LBL_FIXINCLUDES
+
+AC_CHECK_FUNCS(ether_hostton strerror)
+
+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
+AC_ARG_WITH(pcap, [  --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/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/net/raw.h ; then
+       V_PCAP=snoop
+elif test -r /usr/include/sys/dlpi.h ; then
+       V_PCAP=dlpi
+elif test -r /usr/include/linux/socket.h ; then
+       V_PCAP=linux
+elif test -c /dev/bpf0 ; then          # check again in case not readable
+       V_PCAP=bpf
+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)
+
+case "$V_PCAP" in
+
+dlpi)
+       AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
+       AC_MSG_CHECKING(for /dev/dlpi device)
+       if test -c /dev/dlpi ; then
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_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")
+               else
+                       AC_MSG_RESULT(no)
+               fi
+       fi
+       ;;
+
+linux)
+       AC_CHECK_HEADERS(net/if_arp.h)
+       AC_MSG_CHECKING(Linux kernel version)
+       AC_CACHE_VAL(ac_cv_linux_vers,
+           ac_cv_linux_vers=`uname -r 2>&1 | \
+               sed -n -e '$s/.* //' -e '$s/\..*//p'`)
+       AC_MSG_RESULT($ac_cv_linux_vers)
+       if test $ac_cv_linux_vers -lt 2 ; then
+               AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
+       fi
+       ;;
+
+null)
+       AC_MSG_WARN(cannot determine packet capture interface)
+       AC_MSG_WARN((see the INSTALL doc for more info))
+       ;;
+
+esac
+
+AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_)
+
+case "$target_os" in
+
+aix*)
+       dnl Workaround to enable certain features
+       AC_DEFINE(_SUN)
+       ;;
+
+hpux9*)
+       AC_DEFINE(HAVE_HPUX9)
+       ;;
+
+hpux10.0*)
+       ;;
+
+hpux10.1*)
+       ;;
+
+hpux*)
+       dnl HPUX 10.20 and above is similar to HPUX 9...
+       AC_DEFINE(HAVE_HPUX10_20)
+       ;;
+
+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)
+           fi
+       ;;
+
+solaris*)
+       AC_DEFINE(HAVE_SOLARIS)
+       ;;
+
+linux*)
+       V_INCLS="$V_INCLS -Ilinux-include"
+       ;;
+esac
+
+AC_CHECK_PROGS(V_RANLIB, ranlib, @true)
+
+AC_LBL_DEVEL(V_CCOPT)
+
+AC_LBL_SOCKADDR_SA_LEN
+
+AC_LBL_UNALIGNED_ACCESS
+
+if test "${srcdir}" = "." ; then
+       srcdirprefix=""
+else
+       srcdirprefix="./"
+fi
+
+if test -r ${srcdirprefix}lbl/gnuc.h ; then
+       rm -f gnuc.h
+       ln -s ${srcdirprefix}lbl/gnuc.h gnuc.h
+fi
+
+rm -f bpf_filter.c
+ln -s ${srcdirprefix}bpf/net/bpf_filter.c bpf_filter.c
+rm -f net
+ln -s ${srcdirprefix}bpf/net net
+
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_INCLS)
+AC_SUBST(V_LEX)
+AC_SUBST(V_PCAP)
+AC_SUBST(V_RANLIB)
+AC_SUBST(V_YACC)
+
+AC_PROG_INSTALL
+
+AC_OUTPUT(Makefile)
+
+if test -f .devel ; then
+       make depend
+fi
+exit 0
diff --git a/etherent.c b/etherent.c
new file mode 100644 (file)
index 0000000..c34834c
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.20 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include <pcap-namedb.h>
+
+#include "gnuc.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..f325dd5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.6 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
+
+/* Types missing from some systems */
+
+#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_LOOPBACK
+#define        ETHERTYPE_LOOPBACK      0x9000
+#endif
diff --git a/gencode.c b/gencode.c
new file mode 100644 (file)
index 0000000..b7c8c88
--- /dev/null
+++ b/gencode.c
@@ -0,0 +1,1944 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.94 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdlib.h>
+#include <memory.h>
+#include <setjmp.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "pcap-int.h"
+
+#include "ethertype.h"
+#include "gencode.h"
+#include "ppp.h"
+#include <pcap-namedb.h>
+
+#include "gnuc.h"
+#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;
+
+/* XXX */
+#ifdef PCAP_FDDIPAD
+int    pcap_fddipad = PCAP_FDDIPAD;
+#else
+int    pcap_fddipad;
+#endif
+
+/* VARARGS */
+__dead void
+#if __STDC__
+bpf_error(const char *fmt, ...)
+#else
+bpf_error(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       if (bpf_pcap != NULL)
+               (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap);
+       va_end(ap);
+       longjmp(top_ctx, 1);
+       /* NOTREACHED */
+}
+
+static void init_linktype(int);
+
+static int alloc_reg(void);
+static void free_reg(int);
+
+static struct block *root;
+
+/*
+ * 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 it this ever
+ * goes into a library that would probably not be a good idea.
+ */
+#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(u_int, u_int, bpf_int32);
+static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(u_int, u_int, const u_char *);
+static struct block *gen_uncond(int);
+static inline struct block *gen_true(void);
+static inline struct block *gen_false(void);
+static struct block *gen_linktype(int);
+static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
+static struct block *gen_ehostop(const u_char *, int);
+static struct block *gen_fhostop(const u_char *, int);
+static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
+static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
+static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
+static struct block *gen_ipfrag(void);
+static struct block *gen_portatom(int, bpf_int32);
+struct block *gen_portop(int, int, int);
+static struct block *gen_port(int, int, int);
+static int lookup_proto(const char *, 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_len(int, int);
+
+static void *
+newchunk(n)
+       u_int n;
+{
+       struct chunk *cp;
+       int k, size;
+
+       /* XXX Round up to nearest long. */
+       n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+       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);
+               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);
+
+       strcpy(cp, s);
+       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
+pcap_compile(pcap_t *p, struct bpf_program *program,
+            char *buf, int optimize, bpf_u_int32 mask)
+{
+       extern int n_errors;
+       int len;
+
+       n_errors = 0;
+       root = NULL;
+       bpf_pcap = p;
+       if (setjmp(top_ctx)) {
+               freechunks();
+               return (-1);
+       }
+
+       netmask = mask;
+       snaplen = pcap_snapshot(p);
+
+       lex_init(buf ? buf : "");
+       init_linktype(pcap_datalink(p));
+       (void)pcap_parse();
+
+       if (n_errors)
+               syntax();
+
+       if (root == NULL)
+               root = gen_retblk(snaplen);
+
+       if (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;
+
+       freechunks();
+       return (0);
+}
+
+/*
+ * 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;
+{
+       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(offset, size, v)
+       u_int offset, size;
+       bpf_int32 v;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LD|BPF_ABS|size);
+       s->s.k = offset;
+
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       b->s.k = v;
+
+       return b;
+}
+
+static struct block *
+gen_mcmp(offset, size, v, mask)
+       u_int offset, size;
+       bpf_int32 v;
+       bpf_u_int32 mask;
+{
+       struct block *b = gen_cmp(offset, size, v);
+       struct slist *s;
+
+       if (mask != 0xffffffff) {
+               s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s->s.k = mask;
+               b->stmts->next = s;
+       }
+       return b;
+}
+
+static struct block *
+gen_bcmp(offset, size, v)
+       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(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(offset + size - 2, BPF_H, w);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+               size -= 2;
+       }
+       if (size > 0) {
+               tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+       }
+       return b;
+}
+
+/*
+ * Various code constructs need to know the layout of the data link
+ * layer.  These variables give the necessary offsets.  off_linktype
+ * is set to -1 for no encapsulation, in which case, IP is assumed.
+ */
+static u_int off_linktype;
+static u_int off_nl;
+static int linktype;
+
+static void
+init_linktype(type)
+       int type;
+{
+       linktype = type;
+
+       switch (type) {
+
+       case DLT_EN10MB:
+               off_linktype = 12;
+               off_nl = 14;
+               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_nl = 16;
+               return;
+
+       case DLT_SLIP_BSDOS:
+               /* XXX this may be the same as the DLT_PPP_BSDOS case */
+               off_linktype = -1;
+               /* XXX end */
+               off_nl = 24;
+               return;
+
+       case DLT_NULL:
+               off_linktype = 0;
+               off_nl = 4;
+               return;
+
+       case DLT_PPP:
+               off_linktype = 2;
+               off_nl = 4;
+               return;
+
+       case DLT_PPP_BSDOS:
+               off_linktype = 5;
+               off_nl = 24;
+               return;
+
+       case DLT_FDDI:
+               /*
+                * FDDI doesn't really have a link-level type field.
+                * We assume that SSAP = SNAP is being used and pick
+                * out the encapsulated Ethernet type.
+                */
+               off_linktype = 19;
+#ifdef PCAP_FDDIPAD
+               off_linktype += pcap_fddipad;
+#endif
+               off_nl = 21;
+#ifdef PCAP_FDDIPAD
+               off_nl += pcap_fddipad;
+#endif
+               return;
+
+       case DLT_IEEE802:
+               off_linktype = 20;
+               off_nl = 22;
+               return;
+
+       case DLT_ATM_RFC1483:
+               /*
+                * assume routed, non-ISO PDUs
+                * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
+                */
+               off_linktype = 6;
+               off_nl = 8;
+               return;
+
+       case DLT_RAW:
+               off_linktype = -1;
+               off_nl = 0;
+               return;
+       }
+       bpf_error("unknown data link type 0x%x", linktype);
+       /* NOTREACHED */
+}
+
+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);
+}
+
+static struct block *
+gen_linktype(proto)
+       register int proto;
+{
+       struct block *b0, *b1;
+
+       /* If we're not using encapsulation and checking for IP, we're done */
+       if (off_linktype == -1 && proto == ETHERTYPE_IP)
+               return gen_true();
+
+       switch (linktype) {
+
+       case DLT_SLIP:
+               return gen_false();
+
+       case DLT_PPP:
+               if (proto == ETHERTYPE_IP)
+                       proto = PPP_IP;                 /* XXX was 0x21 */
+               break;
+
+       case DLT_PPP_BSDOS:
+               switch (proto) {
+
+               case ETHERTYPE_IP:
+                       b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
+                       b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
+                       gen_or(b0, b1);
+                       b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
+                       gen_or(b1, b0);
+                       return b0;
+
+               case ETHERTYPE_DN:
+                       proto = PPP_DECNET;
+                       break;
+
+               case ETHERTYPE_ATALK:
+                       proto = PPP_APPLE;
+                       break;
+
+               case ETHERTYPE_NS:
+                       proto = PPP_NS;
+                       break;
+               }
+               break;
+
+       case DLT_NULL:
+               /* XXX */
+               if (proto == ETHERTYPE_IP)
+                       return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
+               else
+                       return gen_false();
+       }
+       return gen_cmp(off_linktype, 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(offset, BPF_W, (bpf_int32)addr, mask);
+       gen_and(b0, b1);
+       return b1;
+}
+
+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(6, 6, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(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;
+       }
+       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(6 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(6 + 1, 6, eaddr);
+#endif
+
+       case Q_DST:
+#ifdef PCAP_FDDIPAD
+               return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(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;
+       }
+       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, base_off)
+       bpf_u_int32 addr;
+       int dir;
+       u_int base_off;
+{
+       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, base_off);
+               b1 = gen_dnhostop(addr, Q_DST, base_off);
+               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, base_off);
+               b1 = gen_dnhostop(addr, Q_DST, base_off);
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               abort();
+       }
+       b0 = gen_linktype(ETHERTYPE_DN);
+       /* Check for pad = 1, long header case */
+       tmp = gen_mcmp(base_off + 2, BPF_H,
+           (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
+       b1 = gen_cmp(base_off + 2 + 1 + offset_lh,
+           BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b1);
+       /* Check for pad = 0, long header case */
+       tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+       b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 1, short header case */
+       tmp = gen_mcmp(base_off + 2, BPF_H,
+           (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
+       b2 = gen_cmp(base_off + 2 + 1 + offset_sh,
+           BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 0, short header case */
+       tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+       b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+
+       /* Combine with test for linktype */
+       gen_and(b0, b1);
+       return b1;
+}
+
+static struct block *
+gen_host(addr, mask, proto, dir)
+       bpf_u_int32 addr;
+       bpf_u_int32 mask;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+               b0 = gen_host(addr, mask, Q_IP, dir);
+               b1 = gen_host(addr, mask, Q_ARP, dir);
+               gen_or(b0, b1);
+               b0 = gen_host(addr, mask, Q_RARP, dir);
+               gen_or(b1, b0);
+               return b0;
+
+       case Q_IP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
+                                 off_nl + 12, off_nl + 16);
+
+       case Q_RARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
+                                 off_nl + 14, off_nl + 24);
+
+       case Q_ARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
+                                 off_nl + 14, off_nl + 24);
+
+       case Q_TCP:
+               bpf_error("'tcp' modifier applied to host");
+
+       case Q_UDP:
+               bpf_error("'udp' modifier applied to host");
+
+       case Q_ICMP:
+               bpf_error("'icmp' modifier applied to host");
+
+       case Q_IGMP:
+               bpf_error("'igmp' modifier applied to host");
+
+       case Q_IGRP:
+               bpf_error("'igrp' modifier applied to host");
+
+       case Q_ATALK:
+               bpf_error("ATALK host filtering not implemented");
+
+       case Q_DECNET:
+               return gen_dnhostop(addr, dir, off_nl);
+
+       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");
+
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+
+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:
+               if (linktype == DLT_EN10MB)
+                       b0 = gen_ehostop(eaddr, Q_OR);
+               else if (linktype == DLT_FDDI)
+                       b0 = gen_fhostop(eaddr, Q_OR);
+               else
+                       bpf_error(
+                           "'gateway' supported only on ethernet or FDDI");
+
+               b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR);
+               while (*alist) {
+                       tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR);
+                       gen_or(b1, tmp);
+                       b1 = tmp;
+               }
+               gen_not(b1);
+               gen_and(b0, b1);
+               return b1;
+       }
+       bpf_error("illegal modifier of 'gateway'");
+       /* NOTREACHED */
+}
+
+struct block *
+gen_proto_abbrev(proto)
+       int proto;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case Q_TCP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_UDP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_ICMP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_IGMP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2);
+               gen_and(b0, b1);
+               break;
+
+#ifndef        IPPROTO_IGRP
+#define        IPPROTO_IGRP    9
+#endif
+       case Q_IGRP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_IGRP);
+               gen_and(b0, b1);
+               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_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;
+
+       default:
+               abort();
+       }
+       return b1;
+}
+
+static struct block *
+gen_ipfrag()
+{
+       struct slist *s;
+       struct block *b;
+
+       /* not ip frag */
+       s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
+       s->s.k = off_nl + 6;
+       b = new_block(JMP(BPF_JSET));
+       b->s.k = 0x1fff;
+       b->stmts = s;
+       gen_not(b);
+
+       return b;
+}
+
+static struct block *
+gen_portatom(off, v)
+       int off;
+       bpf_int32 v;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+       s->s.k = off_nl;
+
+       s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
+       s->next->s.k = off_nl + off;
+
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       b->s.k = v;
+
+       return b;
+}
+
+struct block *
+gen_portop(port, proto, dir)
+       int port, proto, dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip proto 'proto' */
+       tmp = gen_cmp(off_nl + 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 */
+       b0 =  gen_linktype(ETHERTYPE_IP);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+               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);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+
+static int
+lookup_proto(name, proto)
+       register const char *name;
+       register int proto;
+{
+       register int v;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_IP:
+               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)
+                       bpf_error("unknown ether proto '%s'", name);
+               break;
+
+       default:
+               v = PROTO_UNDEF;
+               break;
+       }
+       return v;
+}
+
+static struct block *
+gen_proto(v, proto, dir)
+       int v;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       if (dir != Q_DEFAULT)
+               bpf_error("direction applied to 'proto'");
+
+       switch (proto) {
+       case Q_DEFAULT:
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)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_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 */
+
+       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, **alist;
+       struct block *b, *tmp;
+       int port, real_proto;
+
+       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);
+
+       case Q_DEFAULT:
+       case Q_HOST:
+               if (proto == Q_LINK) {
+                       switch (linktype) {
+
+                       case DLT_EN10MB:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown ether host '%s'", name);
+                               return gen_ehostop(eaddr, dir);
+
+                       case DLT_FDDI:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown FDDI host '%s'", name);
+                               return gen_fhostop(eaddr, dir);
+
+                       default:
+                               bpf_error(
+                       "only ethernet/FDDI supports link-level host name");
+                               break;
+                       }
+               } 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));
+               } else {
+                       alist = pcap_nametoaddr(name);
+                       if (alist == NULL || *alist == NULL)
+                               bpf_error("unknown host '%s'", name);
+                       tproto = proto;
+                       if (off_linktype == -1 && tproto == Q_DEFAULT)
+                               tproto = Q_IP;
+                       b = gen_host(**alist++, 0xffffffff, tproto, dir);
+                       while (*alist) {
+                               tmp = gen_host(**alist++, 0xffffffff,
+                                              tproto, dir);
+                               gen_or(b, tmp);
+                               b = tmp;
+                       }
+                       return b;
+               }
+
+       case Q_PORT:
+               if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
+                       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
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_UDP;
+               }
+               if (proto == Q_TCP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port '%s' is udp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_TCP;
+               }
+               return gen_port(port, real_proto, dir);
+
+       case Q_GATEWAY:
+               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);
+               return gen_gateway(eaddr, alist, proto, dir);
+
+       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_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");
+               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);
+
+       default:
+               bpf_error("Mask syntax for networks only");
+               /* NOTREACHED */
+       }
+}
+
+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);
+               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);
+               }
+
+       case Q_PORT:
+               if (proto == Q_UDP)
+                       proto = IPPROTO_UDP;
+               else if (proto == Q_TCP)
+                       proto = IPPROTO_TCP;
+               else if (proto == Q_DEFAULT)
+                       proto = PROTO_UNDEF;
+               else
+                       bpf_error("illegal qualifier of 'port'");
+
+               return gen_port((int)v, proto, dir);
+
+       case Q_GATEWAY:
+               bpf_error("'gateway' requires a name");
+               /* NOTREACHED */
+
+       case Q_PROTO:
+               return gen_proto((int)v, proto, dir);
+
+       case Q_UNDEF:
+               syntax();
+               /* NOTREACHED */
+
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+}
+
+struct block *
+gen_ecode(eaddr, q)
+       register const u_char *eaddr;
+       struct qual q;
+{
+       if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+               if (linktype == DLT_EN10MB)
+                       return gen_ehostop(eaddr, (int)q.dir);
+               if (linktype == DLT_FDDI)
+                       return gen_fhostop(eaddr, (int)q.dir);
+       }
+       bpf_error("ethernet address used in non-ether expression");
+       /* NOTREACHED */
+}
+
+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;
+}
+
+struct arth *
+gen_load(proto, index, size)
+       int proto;
+       struct arth *index;
+       int size;
+{
+       struct slist *s, *tmp;
+       struct block *b;
+       int regno = alloc_reg();
+
+       free_reg(index->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_LINK:
+               s = xfer_to_x(index);
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               sappend(s, tmp);
+               sappend(index->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:
+               /* XXX Note that we assume a fixed link link header here. */
+               s = xfer_to_x(index);
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               tmp->s.k = off_nl;
+               sappend(s, tmp);
+               sappend(index->s, s);
+
+               b = gen_proto_abbrev(proto);
+               if (index->b)
+                       gen_and(index->b, b);
+               index->b = b;
+               break;
+
+       case Q_TCP:
+       case Q_UDP:
+       case Q_ICMP:
+       case Q_IGMP:
+       case Q_IGRP:
+               s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+               s->s.k = off_nl;
+               sappend(s, xfer_to_a(index));
+               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_nl;
+               sappend(index->s, s);
+
+               gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+               if (index->b)
+                       gen_and(index->b, b);
+               index->b = b;
+               break;
+       }
+       index->regno = regno;
+       s = new_stmt(BPF_ST);
+       s->s.k = regno;
+       sappend(index->s, s);
+
+       return index;
+}
+
+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);
+       s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
+       b = new_block(JMP(code));
+       if (code == BPF_JGT || code == BPF_JGE) {
+               reversed = !reversed;
+               b->s.k = 0x80000000;
+       }
+       if (reversed)
+               gen_not(b);
+
+       sappend(s1, s2);
+       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(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;
+
+/*
+ * 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 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);
+}
+
+struct block *
+gen_less(n)
+       int n;
+{
+       struct block *b;
+
+       b = gen_len(BPF_JGT, n);
+       gen_not(b);
+
+       return b;
+}
+
+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((u_int)idx, BPF_B, (bpf_int32)val);
+
+       case '<':
+               b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
+               b->s.code = JMP(BPF_JGE);
+               gen_not(b);
+               return b;
+
+       case '>':
+               b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
+               b->s.code = JMP(BPF_JGT);
+               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;
+}
+
+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:
+               if (linktype == DLT_EN10MB)
+                       return gen_ehostop(ebroadcast, Q_DST);
+               if (linktype == DLT_FDDI)
+                       return gen_fhostop(ebroadcast, Q_DST);
+               bpf_error("not a broadcast link");
+               break;
+
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               hostmask = ~netmask;
+               b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask);
+               b2 = gen_mcmp(off_nl + 16, BPF_W,
+                             (bpf_int32)(~0 & hostmask), hostmask);
+               gen_or(b1, b2);
+               gen_and(b0, b2);
+               return b2;
+       }
+       bpf_error("only ether/ip broadcast filters supported");
+}
+
+struct block *
+gen_multicast(proto)
+       int proto;
+{
+       register struct block *b0, *b1;
+       register struct slist *s;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_LINK:
+               if (linktype == DLT_EN10MB) {
+                       /* ether[0] & 1 != 0 */
+                       s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+                       s->s.k = 0;
+                       b0 = new_block(JMP(BPF_JSET));
+                       b0->s.k = 1;
+                       b0->stmts = s;
+                       return b0;
+               }
+
+               if (linktype == DLT_FDDI) {
+                       /* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX */
+                       /* fddi[1] & 1 != 0 */
+                       s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+                       s->s.k = 1;
+                       b0 = new_block(JMP(BPF_JSET));
+                       b0->s.k = 1;
+                       b0->stmts = s;
+                       return b0;
+               }
+               /* Link not known to support multicasts */
+               break;
+
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
+               b1->s.code = JMP(BPF_JGE);
+               gen_and(b0, b1);
+               return b1;
+       }
+       bpf_error("only IP multicast filters supported on ethernet/FDDI");
+}
+
+/*
+ * generate command for inbound/outbound.  It's here so we can
+ * make it link-type specific.  'dir' = 0 implies "inbound",
+ * = 1 implies "outbound".
+ */
+struct block *
+gen_inbound(dir)
+       int dir;
+{
+       register struct block *b0;
+
+       b0 = gen_relation(BPF_JEQ,
+                         gen_load(Q_LINK, gen_loadi(0), 1),
+                         gen_loadi(0),
+                         dir);
+       return (b0);
+}
diff --git a/gencode.h b/gencode.h
new file mode 100644 (file)
index 0000000..da34082
--- /dev/null
+++ b/gencode.h
@@ -0,0 +1,179 @@
+/*
+ * 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.36 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
+
+/*XXX*/
+#include "gnuc.h"
+
+/* Address qualifiers. */
+
+#define Q_HOST         1
+#define Q_NET          2
+#define Q_PORT         3
+#define Q_GATEWAY      4
+#define Q_PROTO                5
+
+/* Protocol qualifiers. */
+
+#define Q_LINK         1
+#define Q_IP           2
+#define Q_ARP          3
+#define Q_RARP         4
+#define Q_TCP          5
+#define Q_UDP          6
+#define Q_ICMP         7
+#define Q_IGMP         8
+#define Q_IGRP         9
+
+
+#define        Q_ATALK         10
+#define        Q_DECNET        11
+#define        Q_LAT           12
+#define Q_SCA          13
+#define        Q_MOPRC         14
+#define        Q_MOPDL         15
+
+/* Directional qualifiers. */
+
+#define Q_SRC          1
+#define Q_DST          2
+#define Q_OR           3
+#define Q_AND          4
+
+#define Q_DEFAULT      0
+#define Q_UNDEF                255
+
+struct stmt {
+       int code;
+       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;
+       int longjt;             /* jt branch requires long jump */
+       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_mcode(const char *, const char *, int, struct qual);
+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);
+
+void bpf_optimize(struct block **);
+#if __STDC__
+__dead void bpf_error(const char *, ...)
+    __attribute__((volatile, format (printf, 1, 2)));
+#endif
+
+void finish_parse(struct block *);
+char *sdup(const char *);
+
+struct bpf_insn *icode_to_fcode(struct block *, int *);
+int pcap_parse(void);
+void lex_init(char *);
+void sappend(struct slist *, struct slist *);
+
+/* XXX */
+#define JT(b)  ((b)->et.succ)
+#define JF(b)  ((b)->ef.succ)
diff --git a/grammar.y b/grammar.y
new file mode 100644 (file)
index 0000000..edec0f1
--- /dev/null
+++ b/grammar.y
@@ -0,0 +1,281 @@
+%{
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.56 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include <pcap-namedb.h>
+
+#include "gnuc.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)
+
+int n_errors = 0;
+
+static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror(char *msg)
+{
+       ++n_errors;
+       bpf_error("%s", msg);
+       /* NOTREACHED */
+}
+
+#ifndef YYBISON
+int yyparse(void);
+
+int
+pcap_parse()
+{
+       return (yyparse());
+}
+#endif
+
+%}
+
+%union {
+       int i;
+       bpf_u_int32 h;
+       u_char *e;
+       char *s;
+       struct stmt *stmt;
+       struct arth *a;
+       struct {
+               struct qual q;
+               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
+
+%token  DST SRC HOST GATEWAY
+%token  NET MASK PORT LESS GREATER PROTO BYTE
+%token  ARP RARP IP TCP UDP ICMP IGMP IGRP
+%token  ATALK DECNET LAT SCA MOPRC MOPDL
+%token  TK_BROADCAST TK_MULTICAST
+%token  NUM INBOUND OUTBOUND
+%token  LINK
+%token GEQ LEQ NEQ
+%token ID EID HID
+%token LSH RSH
+%token  LEN
+
+%type  <s> ID
+%type  <e> EID
+%type  <s> HID
+%type  <i> NUM
+
+%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 MASK HID          { $$.b = gen_mcode($1, $3, 0,
+                                   $$.q = $<blk>0.q); }
+       | HID                   {
+                                 /* Decide how to parse HID based on proto */
+                                 $$.q = $<blk>0.q;
+                                 switch ($$.q.proto) {
+                                 case Q_DECNET:
+                                       $$.b = gen_ncode($1, 0, $$.q);
+                                       break;
+                                 default:
+                                       $$.b = gen_ncode($1, 0, $$.q);
+                                       break;
+                                 }
+                               }
+       | EID                   { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
+       | 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 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; }
+       ;
+/* 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; }
+       ;
+/* address type qualifiers */
+aqual:   HOST                  { $$ = Q_HOST; }
+       | NET                   { $$ = Q_NET; }
+       | PORT                  { $$ = Q_PORT; }
+       ;
+/* non-directional address type qualifiers */
+ndaqual:  GATEWAY              { $$ = Q_GATEWAY; }
+       ;
+pname:   LINK                  { $$ = Q_LINK; }
+       | IP                    { $$ = Q_IP; }
+       | ARP                   { $$ = Q_ARP; }
+       | RARP                  { $$ = Q_RARP; }
+       | TCP                   { $$ = Q_TCP; }
+       | UDP                   { $$ = Q_UDP; }
+       | ICMP                  { $$ = Q_ICMP; }
+       | IGMP                  { $$ = Q_IGMP; }
+       | IGRP                  { $$ = Q_IGRP; }
+       | ATALK                 { $$ = Q_ATALK; }
+       | DECNET                { $$ = Q_DECNET; }
+       | LAT                   { $$ = Q_LAT; }
+       | SCA                   { $$ = Q_SCA; }
+       | MOPDL                 { $$ = Q_MOPDL; }
+       | MOPRC                 { $$ = Q_MOPRC; }
+       ;
+other:   pqual TK_BROADCAST    { $$ = gen_broadcast($1); }
+       | pqual TK_MULTICAST    { $$ = gen_multicast($1); }
+       | LESS NUM              { $$ = gen_less($2); }
+       | GREATER NUM           { $$ = gen_greater($2); }
+       | BYTE NUM byteop NUM   { $$ = gen_byteop($3, $2, $4); }
+       | INBOUND               { $$ = gen_inbound(0); }
+       | OUTBOUND              { $$ = gen_inbound(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; }
+       ;
+%%
diff --git a/inet.c b/inet.c
new file mode 100644 (file)
index 0000000..e0462da
--- /dev/null
+++ b/inet.c
@@ -0,0 +1,219 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.22 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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 */
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#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"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(p) ((p)->ifr_name[0] == 'l' && (p)->ifr_name[1] == 'o' && \
+    (isdigit((p)->ifr_name[2]) || (p)->ifr_name[2] == '\0'))
+#endif
+
+/*
+ * 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;
+{
+       register int fd, minunit, n;
+       register char *cp;
+       register struct ifreq *ifrp, *ifend, *ifnext, *mp;
+       struct ifconf ifc;
+       struct ifreq ibuf[16], ifr;
+       static char device[sizeof(ifrp->ifr_name) + 1];
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       ifc.ifc_len = sizeof ibuf;
+       ifc.ifc_buf = (caddr_t)ibuf;
+
+       memset((char *)ibuf, 0, sizeof(ibuf));
+       if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
+           ifc.ifc_len < sizeof(struct ifreq)) {
+               (void)sprintf(errbuf, "SIOCGIFCONF: %s", pcap_strerror(errno));
+               (void)close(fd);
+               return (NULL);
+       }
+       ifrp = ibuf;
+       ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
+
+       mp = NULL;
+       minunit = 666;
+       for (; ifrp < ifend; ifrp = ifnext) {
+#ifdef HAVE_SOCKADDR_SA_LEN
+               n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+               if (n < sizeof(*ifrp))
+                       ifnext = ifrp + 1;
+               else
+                       ifnext = (struct ifreq *)((char *)ifrp + n);
+               if (ifrp->ifr_addr.sa_family != AF_INET)
+                       continue;
+#else
+               ifnext = ifrp + 1;
+#endif
+               /*
+                * Need a template to preserve address info that is
+                * used below to locate the next entry.  (Otherwise,
+                * SIOCGIFFLAGS stomps over it because the requests
+                * are returned in a union.)
+                */
+               strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+                       if (errno == ENXIO)
+                               continue;
+                       (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s",
+                           (int)sizeof(ifr.ifr_name), ifr.ifr_name,
+                           pcap_strerror(errno));
+                       (void)close(fd);
+                       return (NULL);
+               }
+
+               /* Must be up and not the loopback */
+               if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
+                       continue;
+
+               for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
+                       continue;
+               n = atoi(cp);
+               if (n < minunit) {
+                       minunit = n;
+                       mp = ifrp;
+               }
+       }
+       (void)close(fd);
+       if (mp == NULL) {
+               (void)strcpy(errbuf, "no suitable device found");
+               return (NULL);
+       }
+
+       (void)strncpy(device, mp->ifr_name, sizeof(device) - 1);
+       device[sizeof(device) - 1] = '\0';
+       return (device);
+}
+
+int
+pcap_lookupnet(device, netp, maskp, errbuf)
+       register char *device;
+       register bpf_u_int32 *netp, *maskp;
+       register char *errbuf;
+{
+       register int fd;
+       register struct sockaddr_in *sin;
+       struct ifreq ifr;
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)sprintf(errbuf, "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) {
+               (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
+                   device, pcap_strerror(errno));
+               (void)close(fd);
+               return (-1);
+       }
+       sin = (struct sockaddr_in *)&ifr.ifr_addr;
+       *netp = sin->sin_addr.s_addr;
+       if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
+               (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s",
+                   device, pcap_strerror(errno));
+               (void)close(fd);
+               return (-1);
+       }
+       (void)close(fd);
+       *maskp = sin->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)sprintf(errbuf, "inet class for 0x%x unknown",
+                           *netp);
+                       return (-1);
+               }
+       }
+       *netp &= *maskp;
+       return (0);
+}
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/gnuc.h b/lbl/gnuc.h
new file mode 100644 (file)
index 0000000..13841ac
--- /dev/null
@@ -0,0 +1,43 @@
+/* @(#) $Header: /tcpdump/master/libpcap/lbl/Attic/gnuc.h,v 1.3 1999-10-07 23:46:41 mcr Exp $ (LBL) */
+
+/* Define __P() macro, if necessary */
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#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/lbl/os-solaris2.h b/lbl/os-solaris2.h
new file mode 100644 (file)
index 0000000..807ca21
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.18 1999-10-07 23:46:41 mcr Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 5 */
+int    daemon(int, int);
+int    dn_expand(const u_char *, const u_char *, const u_char *, char *, int);
+int    dn_skipname(const u_char *, const u_char *);
+int    flock(int, int);
+int    getdtablesize(void);
+int    gethostname(char *, int);
+int    getpagesize(void);
+char   *getusershell(void);
+char   *getwd(char *);
+int    iruserok(u_int, int, char *, char *);
+#ifdef __STDC__
+struct utmp;
+void   login(struct utmp *);
+#endif
+int    logout(const char *);
+int    res_query(const char *, int, int, u_char *, int);
+int    setenv(const char *, const char *, int);
+#if defined(_STDIO_H) && defined(HAVE_SETLINEBUF)
+int    setlinebuf(FILE *);
+#endif
+int    sigblock(int);
+int    sigsetmask(int);
+char    *strerror(int);
+int    snprintf(char *, size_t, const char *, ...);
+int    strcasecmp(const char *, const char *);
+void   unsetenv(const char *);
+#ifdef __STDC__
+struct timeval;
+#endif
+int    utimes(const char *, struct timeval *);
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/linux-include/netinet/if_ether.h b/linux-include/netinet/if_ether.h
new file mode 100644 (file)
index 0000000..4148ab8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ *     @(#)if_ether.h  8.3 (Berkeley) 5/2/95
+ */
+
+#include <net/if_arp.h>
+
+/*
+ * Ethernet address - 6 octets
+ */
+struct ether_addr {
+       u_char  ether_addr_octet[6];
+};
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+       u_char  ether_dhost[6];
+       u_char  ether_shost[6];
+       u_short ether_type;
+};
+
+#define        ETHERTYPE_PUP           0x0200  /* PUP protocol */
+#define        ETHERTYPE_IP            0x0800  /* IP protocol */
+#define ETHERTYPE_ARP          0x0806  /* Addr. resolution protocol */
+#define ETHERTYPE_REVARP       0x8035  /* reverse Addr. resolution protocol */
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define        ETHERTYPE_TRAIL         0x1000          /* Trailer packet */
+#define        ETHERTYPE_NTRAILER      16
+
+#define        ETHERMTU        1500
+#define        ETHERMIN        (60-14)
+
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  Structure below is adapted
+ * to resolving internet addresses.  Field names used correspond to 
+ * RFC 826.
+ */
+struct ether_arp {
+       struct  arphdr ea_hdr;  /* fixed-size header */
+       u_char  arp_sha[6];     /* sender hardware address */
+       u_char  arp_spa[4];     /* sender protocol address */
+       u_char  arp_tha[6];     /* target hardware address */
+       u_char  arp_tpa[4];     /* target protocol address */
+};
+#define        arp_hrd ea_hdr.ar_hrd
+#define        arp_pro ea_hdr.ar_pro
+#define        arp_hln ea_hdr.ar_hln
+#define        arp_pln ea_hdr.ar_pln
+#define        arp_op  ea_hdr.ar_op
diff --git a/linux-include/netinet/ip_var.h b/linux-include/netinet/ip_var.h
new file mode 100644 (file)
index 0000000..c528b62
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ *
+ *     @(#)ip_var.h    8.2 (Berkeley) 1/9/95
+ */
+
+#include <endian.h>
+
+/*
+ * Overlay for ip header used by other protocols (tcp, udp).
+ */
+struct ipovly {
+       caddr_t ih_next, ih_prev;       /* for protocol sequence q's */
+       u_char  ih_x1;                  /* (unused) */
+       u_char  ih_pr;                  /* protocol */
+       short   ih_len;                 /* protocol length */
+       struct  in_addr ih_src;         /* source internet address */
+       struct  in_addr ih_dst;         /* destination internet address */
+};
+
+/*
+ * Ip reassembly queue structure.  Each fragment
+ * being reassembled is attached to one of these structures.
+ * They are timed out after ipq_ttl drops to 0, and may also
+ * be reclaimed if memory becomes tight.
+ */
+struct ipq {
+       struct  ipq *next,*prev;        /* to other reass headers */
+       u_char  ipq_ttl;                /* time for reass q to live */
+       u_char  ipq_p;                  /* protocol of this fragment */
+       u_short ipq_id;                 /* sequence id for reassembly */
+       struct  ipasfrag *ipq_next,*ipq_prev;
+                                       /* to ip headers of fragments */
+       struct  in_addr ipq_src,ipq_dst;
+};
+
+/*
+ * Ip header, when holding a fragment.
+ *
+ * Note: ipf_next must be at same offset as ipq_next above
+ */
+struct ipasfrag {
+#if BYTE_ORDER == LITTLE_ENDIAN 
+       u_char  ip_hl:4,
+               ip_v:4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN 
+       u_char  ip_v:4,
+               ip_hl:4;
+#endif
+       u_char  ipf_mff;                /* XXX overlays ip_tos: use low bit
+                                        * to avoid destroying tos;
+                                        * copied from (ip_off&IP_MF) */
+       short   ip_len;
+       u_short ip_id;
+       short   ip_off;
+       u_char  ip_ttl;
+       u_char  ip_p;
+       u_short ip_sum;
+       struct  ipasfrag *ipf_next;     /* next fragment */
+       struct  ipasfrag *ipf_prev;     /* previous fragment */
+};
+
+/*
+ * Structure stored in mbuf in inpcb.ip_options
+ * and passed to ip_output when ip options are in use.
+ * The actual length of the options (including ipopt_dst)
+ * is in m_len.
+ */
+#define MAX_IPOPTLEN   40
+
+struct ipoption {
+       struct  in_addr ipopt_dst;      /* first-hop dst if source routed */
+       char    ipopt_list[MAX_IPOPTLEN];       /* options proper */
+};
+
+struct ipstat {
+       n_long  ips_total;              /* total packets received */
+       n_long  ips_badsum;             /* checksum bad */
+       n_long  ips_tooshort;           /* packet too short */
+       n_long  ips_toosmall;           /* not enough data */
+       n_long  ips_badhlen;            /* ip header length < data size */
+       n_long  ips_badlen;             /* ip length < ip header length */
+       n_long  ips_fragments;          /* fragments received */
+       n_long  ips_fragdropped;        /* frags dropped (dups, out of space) */
+       n_long  ips_fragtimeout;        /* fragments timed out */
+       n_long  ips_forward;            /* packets forwarded */
+       n_long  ips_cantforward;        /* packets rcvd for unreachable dest */
+       n_long  ips_redirectsent;       /* packets forwarded on same net */
+       n_long  ips_noproto;            /* unknown or unsupported protocol */
+       n_long  ips_delivered;          /* datagrams delivered to upper level*/
+       n_long  ips_localout;           /* total ip packets generated here */
+       n_long  ips_odropped;           /* lost packets due to nobufs, etc. */
+       n_long  ips_reassembled;        /* total packets reassembled ok */
+       n_long  ips_fragmented;         /* datagrams sucessfully fragmented */
+       n_long  ips_ofragments;         /* output fragments created */
+       n_long  ips_cantfrag;           /* don't fragment flag was set, etc. */
+       n_long  ips_badoptions;         /* error in option processing */
+       n_long  ips_noroute;            /* packets discarded due to no route */
+       n_long  ips_badvers;            /* ip version != 4 */
+       n_long  ips_rawout;             /* total raw ip packets generated */
+};
+
+#ifdef KERNEL
+/* flags passed to ip_output as last parameter */
+#define        IP_FORWARDING           0x1             /* most of ip header exists */
+#define        IP_RAWOUTPUT            0x2             /* raw ip header exists */
+#define        IP_ROUTETOIF            SO_DONTROUTE    /* bypass routing tables */
+#define        IP_ALLOWBROADCAST       SO_BROADCAST    /* can send broadcast packets */
+
+struct ipstat  ipstat;
+struct ipq     ipq;                    /* ip reass. queue */
+u_short        ip_id;                          /* ip packet ctr, for ids */
+int    ip_defttl;                      /* default IP ttl */
+
+int     in_control __P((struct socket *, n_long, caddr_t, struct ifnet *));
+int     ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
+void    ip_deq __P((struct ipasfrag *));
+int     ip_dooptions __P((struct mbuf *));
+void    ip_drain __P((void));
+void    ip_enq __P((struct ipasfrag *, struct ipasfrag *));
+void    ip_forward __P((struct mbuf *, int));
+void    ip_freef __P((struct ipq *));
+void    ip_freemoptions __P((struct ip_moptions *));
+int     ip_getmoptions __P((int, struct ip_moptions *, struct mbuf **));
+void    ip_init __P((void));
+int     ip_mforward __P((struct mbuf *, struct ifnet *));
+int     ip_optcopy __P((struct ip *, struct ip *));
+int     ip_output __P((struct mbuf *,
+           struct mbuf *, struct route *, int, struct ip_moptions *));
+int     ip_pcbopts __P((struct mbuf **, struct mbuf *));
+struct ip *
+        ip_reass __P((struct ipasfrag *, struct ipq *));
+struct in_ifaddr *
+        ip_rtaddr __P((struct in_addr));
+int     ip_setmoptions __P((int, struct ip_moptions **, struct mbuf *));
+void    ip_slowtimo __P((void));
+struct mbuf *
+        ip_srcroute __P((void));
+void    ip_stripoptions __P((struct mbuf *, struct mbuf *));
+int     ip_sysctl __P((int *, n_long, void *, size_t *, void *, size_t));
+void    ipintr __P((void));
+int     rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
+void    rip_init __P((void));
+void    rip_input __P((struct mbuf *));
+int     rip_output __P((struct mbuf *, struct socket *, n_long));
+int     rip_usrreq __P((struct socket *,
+           int, struct mbuf *, struct mbuf *, struct mbuf *));
+#endif
diff --git a/mkdep b/mkdep
new file mode 100755 (executable)
index 0000000..2a9c221
--- /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
+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/nametoaddr.c b/nametoaddr.c
new file mode 100644 (file)
index 0000000..e3e0952
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.48 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>                         /* concession to AIX */
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include <pcap-namedb.h>
+
+#include "gnuc.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;
+}
+
+/*
+ *  Convert net name to internet address.
+ *  Return 0 upon failure.
+ */
+bpf_u_int32
+pcap_nametonetaddr(const char *name)
+{
+       struct netent *np;
+
+       if ((np = getnetbyname(name)) != NULL)
+               return np->n_net;
+       else
+               return 0;
+}
+
+/*
+ * 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;
+       char *other;
+
+       sp = getservbyname(name, (char *)0);
+       if (sp != NULL) {
+               NTOHS(sp->s_port);
+               *port = sp->s_port;
+               *proto = pcap_nametoproto(sp->s_proto);
+               /*
+                * 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.
+                */
+               if (*proto == IPPROTO_TCP)
+                       other = "udp";
+               else
+                       other = "tcp";
+
+               sp = getservbyname(name, other);
+               if (sp != 0) {
+                       NTOHS(sp->s_port);
+#ifdef notdef
+                       if (*port != sp->s_port)
+                               /* Can't handle ambiguous names that refer
+                                  to different port numbers. */
+                               warning("ambiguous port %s in /etc/services",
+                                       name);
+#endif
+                       *proto = PROTO_UNDEF;
+               }
+               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;
+}
+
+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 {
+       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 },
+       { "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;
+}
+
+/* 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((char *)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 has the form "xx:xx:xx:xx:xx:xx" 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 += 1;
+               d = xdtoi(*s++);
+               if (isxdigit(*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 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
+
+#ifndef sgi
+extern int ether_hostton(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((char *)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);
+#endif
+}
diff --git a/optimize.c b/optimize.c
new file mode 100644 (file)
index 0000000..b035d2d
--- /dev/null
@@ -0,0 +1,2004 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.60 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef BDEBUG
+extern int dflag;
+#endif
+
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+#define NOP -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 void opt_blk(struct block *, int);
+static int use_conflict(struct block *, struct block *);
+static void opt_j(struct edge *);
+static struct block *fold_edge(struct block *, struct edge *);
+static inline int eq_blk(struct block *, struct block *);
+static int slength(struct slist *);
+static int count_blocks(struct block *);
+static void number_blks_r(struct block *);
+static 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;
+}
+
+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 (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP)
+               use |= ATOMMASK(A_ATOM);
+
+       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_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;
+       while (1) {
+               s = this_op(s);
+               if (s == 0)
+                       break;
+               next = this_op(s->next);
+               if (next == 0)
+                       break;
+               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))
+                               break;
+
+                       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))
+                               break;
+
+                       tax = this_op(add->next);
+                       if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
+                               break;
+
+                       ild = this_op(tax->next);
+                       if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
+                           BPF_MODE(ild->s.code) != BPF_IND)
+                               break;
+                       /*
+                        * XXX We need to check that X is not
+                        * subsequently used.  We know we can eliminate the
+                        * accumulator modifications since it is defined
+                        * by the last stmt of this sequence.
+                        *
+                        * 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]
+                        *
+                        */
+                       ild->s.k += s->s.k;
+                       s->s.code = NOP;
+                       add->s.code = NOP;
+                       tax->s.code = NOP;
+                       done = 0;
+               }
+               s = next;
+       }
+       /*
+        * 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.
+        */
+       if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
+           !ATOMELEM(b->out_use, A_ATOM)) {
+               val = b->val[X_ATOM];
+               if (vmap[val].is_const) {
+                       int op;
+
+                       b->s.k += vmap[val].const_val;
+                       op = BPF_OP(b->s.code);
+                       if (op == BPF_JGT || op == BPF_JGE) {
+                               struct block *t = JT(b);
+                               JT(b) = JF(b);
+                               JF(b) = t;
+                               b->s.k += 0x80000000;
+                       }
+                       last->s.code = NOP;
+                       done = 0;
+               } else if (b->s.k == 0) {
+                       /*
+                        * sub x  ->    nop
+                        * j  #0        j  x
+                        */
+                       last->s.code = NOP;
+                       b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) |
+                               BPF_X;
+                       done = 0;
+               }
+       }
+       /*
+        * Likewise, a constant subtract can be simplified.
+        */
+       else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
+                !ATOMELEM(b->out_use, A_ATOM)) {
+               int op;
+
+               b->s.k += last->s.k;
+               last->s.code = NOP;
+               op = BPF_OP(b->s.code);
+               if (op == BPF_JGT || op == BPF_JGE) {
+                       struct block *t = JT(b);
+                       JT(b) = JF(b);
+                       JF(b) = t;
+                       b->s.k += 0x80000000;
+               }
+               done = 0;
+       }
+       /*
+        * and #k       nop
+        * jeq #0  ->   jset #k
+        */
+       if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+           !ATOMELEM(b->out_use, A_ATOM) && 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);
+       }
+       /*
+        * 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) {
+                               if (op == BPF_ADD || op == BPF_SUB ||
+                                   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, and -1, etc.
+                */
+               if (alter && vmap[val[A_ATOM]].is_const
+                   && vmap[val[A_ATOM]].const_val == 0) {
+                       if (op == BPF_ADD || op == BPF_OR ||
+                           op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) {
+                               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) {
+                               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;
+
+       /*
+        * Initialize the atom values.
+        * If we have no predecessors, everything is undefined.
+        * Otherwise, we inherent our values from our predecessors.
+        * If any register has an ambiguous value (i.e. control paths are
+        * merging) give it the undefined value of 0.
+        */
+       p = b->in_edges;
+       if (p == 0)
+               memset((char *)b->val, 0, sizeof(b->val));
+       else {
+               memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
+               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];
+       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 with value that is
+        * already there, or if this block is a return,
+        * eliminate all the statements.
+        */
+       if (do_stmts && 
+           ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) ||
+            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 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.  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;
+       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);
+               }
+       }
+       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)
+               opt_dump(root);
+#endif
+       do {
+               done = 1;
+               find_levels(root);
+               find_dom(root);
+               find_closure(root);
+               find_inedges(root);
+               find_ud(root);
+               find_edom(root);
+               opt_blks(root, do_stmts);
+#ifdef BDEBUG
+               if (dflag > 1)
+                       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);
+       opt_root(rootp);
+       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 done;
+ top:
+       done = 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) {
+                       done = 0;
+                       JT(p) = JT(p)->link;
+               }
+               if (JF(p)->link) {
+                       done = 0;
+                       JF(p) = JF(p)->link;
+               }
+       }
+       if (!done)
+               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 int
+slength(s)
+       struct slist *s;
+{
+       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.
+ */
+static int
+count_stmts(p)
+       struct block *p;
+{
+       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;
+}
+
+/*
+ * 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 **)malloc(n * sizeof(*blocks));
+       unMarkAll();
+       n_blocks = 0;
+       number_blks_r(root);
+
+       n_edges = 2 * n_blocks;
+       edges = (struct edge **)malloc(n_edges * sizeof(*edges));
+
+       /*
+        * The number of levels is bounded by the number of nodes.
+        */
+       levels = (struct block **)malloc(n_blocks * sizeof(*levels));
+
+       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));
+       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 *)malloc(maxval * sizeof(*vmap));
+       vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));
+}
+
+/*
+ * 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 */
+
+       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;
+
+       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;
+               ++dst;
+       }
+#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.
+ */
+struct bpf_insn *
+icode_to_fcode(root, lenp)
+       struct block *root;
+       int *lenp;
+{
+       int n;
+       struct bpf_insn *fp;
+
+       /*
+        * Loop doing convert_codr_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);
+           memset((char *)fp, 0, sizeof(*fp) * n);
+           fstart = fp;
+           ftail = fp + n;
+    
+           unMarkAll();
+           if (convert_code_r(root))
+               break;
+           free(fp);
+       }
+
+       return fp;
+}
+
+#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/pcap-bpf.c b/pcap-bpf.c
new file mode 100644 (file)
index 0000000..ae82709
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.31 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       struct bpf_stat s;
+
+       if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
+               sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       ps->ps_recv = s.bs_recv;
+       ps->ps_drop = s.bs_drop;
+       return (0);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       int n = 0;
+       register u_char *bp, *ep;
+
+ again:
+       cc = p->cc;
+       if (p->cc == 0) {
+               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);
+#if defined(sun) && !defined(BSD)
+                       /*
+                        * 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
+                       }
+                       sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+               bp = p->buffer;
+       } else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.
+        */
+#define bhp ((struct bpf_hdr *)bp)
+       ep = bp + cc;
+       while (bp < ep) {
+               register int caplen, hdrlen;
+               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 += BPF_WORDALIGN(caplen + hdrlen);
+               if (++n >= cnt && cnt > 0) {
+                       p->bp = bp;
+                       p->cc = ep - bp;
+                       return (n);
+               }
+       }
+#undef bhp
+       p->cc = 0;
+       return (n);
+}
+
+static inline int
+bpf_open(pcap_t *p, char *errbuf)
+{
+       int fd;
+       int n = 0;
+       char device[sizeof "/dev/bpf000"];
+
+       /*
+        * Go through all the minors and find one that isn't in use.
+        */
+       do {
+               (void)sprintf(device, "/dev/bpf%d", n++);
+               fd = open(device, O_RDONLY);
+       } while (fd < 0 && errno == EBUSY);
+
+       /*
+        * XXX better message for all minors used
+        */
+       if (fd < 0)
+               sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));
+
+       return (fd);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       int fd;
+       struct ifreq ifr;
+       struct bpf_version bv;
+       u_int v;
+       pcap_t *p;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       bzero(p, sizeof(*p));
+       fd = bpf_open(p, ebuf);
+       if (fd < 0)
+               goto bad;
+
+       p->fd = fd;
+       p->snapshot = snaplen;
+
+       if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
+               sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       if (bv.bv_major != BPF_MAJOR_VERSION ||
+           bv.bv_minor < BPF_MINOR_VERSION) {
+               sprintf(ebuf, "kernel bpf filter out of date");
+               goto bad;
+       }
+       v = 32768;      /* XXX this should be a user-accessible hook */
+       /* 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(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+               sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));
+               goto bad;
+       }
+       /* Get the data link layer type. */
+       if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
+               sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));
+               goto bad;
+       }
+#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;
+       }
+#endif
+       p->linktype = v;
+
+       /* set timeout */
+       if (to_ms != 0) {
+               struct timeval to;
+               to.tv_sec = to_ms / 1000;
+               to.tv_usec = (to_ms * 1000) % 1000000;
+               if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
+                       sprintf(ebuf, "BIOCSRTIMEOUT: %s",
+                               pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+       if (promisc)
+               /* set promiscuous mode, okay if it fails */
+               (void)ioctl(p->fd, BIOCPROMISC, NULL);
+
+       if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
+               sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->bufsize = v;
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       return (p);
+ bad:
+       (void)close(fd);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       if (p->sf.rfile != NULL)
+               p->fcode = *fp;
+       else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
+               sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
new file mode 100644 (file)
index 0000000..7d09894
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * 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 ([email protected]),
+ * University College London.
+ */
+
+/*
+ * Packet capture routine for dlpi under SunOS 5
+ *
+ * Notes:
+ *
+ *    - Apparently 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.52 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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_ACK_OBS
+#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>
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef PCAP_DEV_PREFIX
+#define PCAP_DEV_PREFIX "/dev"
+#endif
+
+#define        MAXDLBUF        8192
+
+/* Forwards */
+static int dlattachreq(int, bpf_u_int32, char *);
+static int dlbindack(int, char *, char *);
+static int dlbindreq(int, bpf_u_int32, char *);
+static int dlinfoack(int, char *, char *);
+static int dlinforeq(int, char *);
+static int dlokack(int, const char *, char *, char *);
+static int recv_ack(int, int, const char *, char *, char *);
+static int dlpromisconreq(int, bpf_u_int32, char *);
+#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_SYS_BUFMOD_H
+static int strioctl(int, int, int, char *);
+#endif
+#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
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       *ps = p->md.stat;
+       return (0);
+}
+
+/* XXX Needed by HP-UX (at least) */
+static bpf_u_int32 ctlbuf[MAXDLBUF];
+static struct strbuf ctl = {
+       MAXDLBUF,
+       0,
+       (char *)ctlbuf
+};
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc, n, caplen, origlen;
+       register u_char *bp, *ep, *pk;
+       register struct bpf_insn *fcode;
+#ifdef HAVE_SYS_BUFMOD_H
+       register struct sb_hdr *sbp;
+#ifdef LBL_ALIGN
+       struct sb_hdr sbhdr;
+#endif
+#endif
+       int flags;
+       struct strbuf data;
+       struct pcap_pkthdr pkthdr;
+
+       flags = 0;
+       cc = p->cc;
+       if (cc == 0) {
+               data.buf = (char *)p->buffer + p->offset;
+               data.maxlen = MAXDLBUF;
+               data.len = 0;
+               do {
+                       if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
+                               /* Don't choke when we get ptraced */
+                               if (errno == EINTR) {
+                                       cc = 0;
+                                       continue;
+                               }
+                               strcpy(p->errbuf, pcap_strerror(errno));
+                               return (-1);
+                       }
+                       cc = data.len;
+               } while (cc == 0);
+               bp = p->buffer + p->offset;
+       } else
+               bp = p->bp;
+
+       /* Loop through packets */
+       fcode = p->fcode.bf_insns;
+       ep = bp + cc;
+       n = 0;
+#ifdef HAVE_SYS_BUFMOD_H
+       while (bp < ep) {
+#ifdef LBL_ALIGN
+               if ((long)bp & 3) {
+                       sbp = &sbhdr;
+                       memcpy(sbp, bp, sizeof(*sbp));
+               } else
+#endif
+                       sbp = (struct sb_hdr *)bp;
+               p->md.stat.ps_drop += sbp->sbh_drops;
+               pk = bp + sizeof(*sbp);
+               bp += sbp->sbh_totlen;
+               origlen = sbp->sbh_origlen;
+               caplen = sbp->sbh_msglen;
+#else
+               origlen = cc;
+               caplen = min(p->snapshot, cc);
+               pk = bp;
+               bp += caplen;
+#endif
+               ++p->md.stat.ps_recv;
+               if (bpf_filter(fcode, pk, origlen, caplen)) {
+#ifdef HAVE_SYS_BUFMOD_H
+                       pkthdr.ts = sbp->sbh_timestamp;
+#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 >= cnt && cnt >= 0) {
+                               p->cc = ep - bp;
+                               p->bp = bp;
+                               return (n);
+                       }
+               }
+#ifdef HAVE_SYS_BUFMOD_H
+       }
+#endif
+       p->cc = 0;
+       return (n);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       register char *cp;
+       char *eos;
+       register pcap_t *p;
+       register int ppa;
+       register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+       bpf_u_int32 ss, flag;
+#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
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               strcpy(ebuf, pcap_strerror(errno));
+               return (NULL);
+       }
+       memset(p, 0, sizeof(*p));
+
+       /*
+       ** Determine device and ppa
+       */
+       cp = strpbrk(device, "0123456789");
+       if (cp == NULL) {
+               sprintf(ebuf, "%s missing unit number", device);
+               goto bad;
+       }
+       ppa = strtol(cp, &eos, 10);
+       if (*eos != '\0') {
+               sprintf(ebuf, "%s bad unit number", device);
+               goto bad;
+       }
+
+       if (*device == '/')
+               strcpy(dname, device);
+       else
+               sprintf(dname, "%s/%s", PCAP_DEV_PREFIX, device);
+#ifdef HAVE_DEV_DLPI
+       /* Map network device to /dev/dlpi unit */
+       cp = "/dev/dlpi";
+       if ((p->fd = open(cp, O_RDWR)) < 0) {
+               sprintf(ebuf, "%s: %s", cp, pcap_strerror(errno));
+               goto bad;
+       }
+       /* Map network interface to /dev/dlpi unit */
+       ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf);
+       if (ppa < 0)
+               goto bad;
+#else
+       /* Try device without unit number */
+       strcpy(dname2, dname);
+       cp = strchr(dname, *cp);
+       *cp = '\0';
+       if ((p->fd = open(dname, O_RDWR)) < 0) {
+               if (errno != ENOENT) {
+                       sprintf(ebuf, "%s: %s", dname, pcap_strerror(errno));
+                       goto bad;
+               }
+
+               /* Try again with unit number */
+               if ((p->fd = open(dname2, O_RDWR)) < 0) {
+                       sprintf(ebuf, "%s: %s", dname2, pcap_strerror(errno));
+                       goto bad;
+               }
+               /* XXX Assume unit zero */
+               ppa = 0;
+       }
+#endif
+
+       p->snapshot = snaplen;
+
+       /*
+       ** Attach if "style 2" provider
+       */
+       if (dlinforeq(p->fd, ebuf) < 0 ||
+           dlinfoack(p->fd, (char *)buf, ebuf) < 0)
+               goto bad;
+       infop = &((union DL_primitives *)buf)->info_ack;
+       if (infop->dl_provider_style == DL_STYLE2 &&
+           (dlattachreq(p->fd, ppa, ebuf) < 0 ||
+           dlokack(p->fd, "attach", (char *)buf, ebuf) < 0))
+               goto bad;
+       /*
+       ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if
+       ** using SINIX)
+       */
+#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix)
+       if (dlbindreq(p->fd, 0, ebuf) < 0 ||
+           dlbindack(p->fd, (char *)buf, ebuf) < 0)
+               goto bad;
+#endif
+
+       if (promisc) {
+               /*
+               ** Enable promiscuous
+               */
+               if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||
+                   dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0)
+                       goto bad;
+
+               /*
+               ** Try to enable multicast (you would have thought
+               ** promiscuous would be sufficient). (Skip if using
+               ** HP-UX or SINIX)
+               */
+#if !defined(__hpux) && !defined(sinix)
+               if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||
+                   dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0)
+                       fprintf(stderr,
+                           "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf);
+#endif
+       }
+       /*
+       ** Try to enable sap (when not in promiscuous mode when using
+       ** using HP-UX and never under SINIX)
+       */
+#ifndef sinix
+       if (
+#ifdef __hpux
+           !promisc &&
+#endif
+           (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 ||
+           dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) {
+               /* Not fatal if promisc since the DL_PROMISC_PHYS worked */
+               if (promisc)
+                       fprintf(stderr,
+                           "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf);
+               else
+                       goto bad;
+       }
+#endif
+
+       /*
+       ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous
+       ** options)
+       */
+#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20)
+       if (dlbindreq(p->fd, 0, ebuf) < 0 ||
+           dlbindack(p->fd, (char *)buf, ebuf) < 0)
+               goto bad;
+#endif
+
+       /*
+       ** Determine link type
+       */
+       if (dlinforeq(p->fd, ebuf) < 0 ||
+           dlinfoack(p->fd, (char *)buf, ebuf) < 0)
+               goto bad;
+
+       infop = &((union DL_primitives *)buf)->info_ack;
+       switch (infop->dl_mac_type) {
+
+       case DL_CSMACD:
+       case DL_ETHER:
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               break;
+
+       case DL_FDDI:
+               p->linktype = DLT_FDDI;
+               p->offset = 3;
+               break;
+
+       default:
+               sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type);
+               goto bad;
+       }
+
+#ifdef DLIOCRAW
+       /*
+       ** This is a non standard SunOS hack to get the ethernet header.
+       */
+       if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
+               sprintf(ebuf, "DLIOCRAW: %s", pcap_strerror(errno));
+               goto bad;
+       }
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+       /*
+       ** Another non standard call to get the data nicely buffered
+       */
+       if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
+               sprintf(ebuf, "I_PUSH bufmod: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       /*
+       ** Now that the bufmod is pushed lets configure it.
+       **
+       ** 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 supposed to be fixed in 5.3.2. Also, there is a
+       ** patch available. Ask for bugid 1149065.
+       */
+       ss = snaplen;
+#ifdef HAVE_SOLARIS
+       release = get_release(&osmajor, &osminor, &osmicro);
+       if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
+           getenv("BUFMOD_FIXED") == NULL) {
+               fprintf(stderr,
+               "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",
+                   release);
+               ss = 0;
+       }
+#endif
+       if (ss > 0 &&
+           strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
+               sprintf(ebuf, "SBIOCSSNAP: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       /*
+       ** Set up the bufmod flags
+       */
+       if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) {
+               sprintf(ebuf, "SBIOCGFLAGS: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       flag |= SB_NO_DROPS;
+       if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) {
+               sprintf(ebuf, "SBIOCSFLAGS: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       /*
+       ** Set up the bufmod timeout
+       */
+       if (to_ms != 0) {
+               struct timeval to;
+
+               to.tv_sec = to_ms / 1000;
+               to.tv_usec = (to_ms * 1000) % 1000000;
+               if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
+                       sprintf(ebuf, "SBIOCSTIME: %s", pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+#endif
+
+       /*
+       ** As the last operation flush the read side.
+       */
+       if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+               sprintf(ebuf, "FLUSHR: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       /* Allocate data buffer */
+       p->bufsize = MAXDLBUF * sizeof(bpf_u_int32);
+       p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+
+       return (p);
+bad:
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       p->fcode = *fp;
+       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) {
+               sprintf(ebuf, "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)
+{
+       union   DL_primitives   *dlp;
+       struct  strbuf  ctl;
+       int     flags;
+
+       ctl.maxlen = MAXDLBUF;
+       ctl.len = 0;
+       ctl.buf = bufp;
+
+       flags = 0;
+       if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
+               sprintf(ebuf, "recv_ack: %s getmsg: %s",
+                   what, pcap_strerror(errno));
+               return (-1);
+       }
+
+       dlp = (union 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_BADPPA:
+                       sprintf(ebuf, "recv_ack: %s bad ppa (device unit)",
+                           what);
+                       break;
+
+
+               case DL_SYSERR:
+                       sprintf(ebuf, "recv_ack: %s: %s",
+                           what, pcap_strerror(dlp->error_ack.dl_unix_errno));
+                       break;
+
+               case DL_UNSUPPORTED:
+                       sprintf(ebuf,
+                           "recv_ack: %s: Service not supplied by provider",
+                           what);
+                       break;
+
+               default:
+                       sprintf(ebuf, "recv_ack: %s error 0x%x",
+                           what, (bpf_u_int32)dlp->error_ack.dl_errno);
+                       break;
+               }
+               return (-1);
+
+       default:
+               sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ",
+                   what, (bpf_u_int32)dlp->dl_primitive);
+               return (-1);
+       }
+
+       if (ctl.len < size) {
+               sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)",
+                   what, ctl.len, size);
+               return (-1);
+       }
+       return (ctl.len);
+}
+
+static int
+dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf)
+{
+       dl_attach_req_t req;
+
+       req.dl_primitive = DL_ATTACH_REQ;
+       req.dl_ppa = ppa;
+
+       return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf));
+}
+
+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;
+#ifdef DL_HP_RAWDLS
+       req.dl_max_conind = 1;                  /* XXX magic number */
+       /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */
+       req.dl_sap = 22;
+       req.dl_service_mode = DL_HP_RAWDLS;
+#else
+       req.dl_sap = sap;
+#ifdef DL_CLDLS
+       req.dl_service_mode = DL_CLDLS;
+#endif
+#endif
+
+       return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
+}
+
+static int
+dlbindack(int fd, char *bufp, char *ebuf)
+{
+
+       return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
+}
+
+static int
+dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf)
+{
+       dl_promiscon_req_t req;
+
+       req.dl_primitive = DL_PROMISCON_REQ;
+       req.dl_level = level;
+
+       return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf));
+}
+
+static int
+dlokack(int fd, const char *what, char *bufp, char *ebuf)
+{
+
+       return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
+}
+
+
+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));
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+static int
+strioctl(int fd, int cmd, int len, char *dp)
+{
+       struct strioctl str;
+       int rc;
+
+       str.ic_cmd = cmd;
+       str.ic_timout = -1;
+       str.ic_len = len;
+       str.ic_dp = dp;
+       rc = ioctl(fd, I_STR, &str);
+
+       if (rc < 0)
+               return (rc);
+       else
+               return (str.ic_len);
+}
+#endif
+
+#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(*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_ACK_OBS
+/*
+ * Under HP-UX 10, we can ask for the ppa
+ */
+
+
+/* Determine ppa number that specifies ifname */
+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 *ip;
+       register int i;
+       register u_long majdev;
+       dl_hp_ppa_req_t req;
+       struct stat statbuf;
+       bpf_u_int32 buf[MAXDLBUF];
+
+       if (stat(device, &statbuf) < 0) {
+               sprintf(ebuf, "stat: %s: %s", device, pcap_strerror(errno));
+               return (-1);
+       }
+       majdev = major(statbuf.st_rdev);
+
+       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 ||
+           recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0)
+               return (-1);
+
+       ap = (dl_hp_ppa_ack_t *)buf;
+       ip = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset);
+
+        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 *)ip + ip->dl_next_offset);
+        }
+        if (i == ap->dl_count) {
+                sprintf(ebuf, "can't find PPA for %s", device);
+               return (-1);
+        }
+        if (ip->dl_hdw_state == HDW_DEAD) {
+                sprintf(ebuf, "%s: hardware state: DOWN\n", device);
+               return (-1);
+        }
+        return ((int)ip->dl_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)], tifname[32];
+
+       cp = strrchr(ifname, '/');
+       if (cp != NULL)
+               ifname = cp + 1;
+       if (nlist(path_vmunix, &nl) < 0) {
+               sprintf(ebuf, "nlist %s failed", path_vmunix);
+               return (-1);
+       }
+       if (nl[NL_IFNET].n_value == 0) {
+               sprintf(ebuf, "could't find %s kernel symbol",
+                   nl[NL_IFNET].n_name);
+               return (-1);
+       }
+       kd = open("/dev/kmem", O_RDONLY);
+       if (kd < 0) {
+               sprintf(ebuf, "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(if_name), ebuf) < 0) {
+                       (void)close(kd);
+                       return (-1);
+               }
+               sprintf(tifname, "%.*s%d",
+                   (int)sizeof(if_name), if_name, ifnet.if_unit);
+               if (strcmp(tifname, ifname) == 0)
+                       return (ifnet.if_index);
+       }
+
+       sprintf(ebuf, "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) {
+               sprintf(ebuf, "lseek: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       cc = read(fd, buf, len);
+       if (cc < 0) {
+               sprintf(ebuf, "read: %s", pcap_strerror(errno));
+               return (-1);
+       } else if (cc != len) {
+               sprintf(ebuf, "short read (%d != %d)", cc, len);
+               return (-1);
+       }
+       return (cc);
+}
+#endif
diff --git a/pcap-enet.c b/pcap-enet.c
new file mode 100644 (file)
index 0000000..3f4189b
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Stanford Enetfilter subroutines for tcpdump
+ *
+ * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c
+ * subroutines.
+ *
+ * Rayan Zachariassen, CA*Net
+ */
+
+#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 <net/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-int.h b/pcap-int.h
new file mode 100644 (file)
index 0000000..c5a23d9
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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.18 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
+
+#ifndef pcap_int_h
+#define pcap_int_h
+
+#include <pcap.h>
+
+/*
+ * Savefile
+ */
+struct pcap_sf {
+       FILE *rfile;
+       int swapped;
+       int version_major;
+       int version_minor;
+       u_char *base;
+};
+
+struct pcap_md {
+       struct pcap_stat stat;
+       /*XXX*/
+       int use_bpf;
+       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 */
+#ifdef linux
+       int pad;
+       int skip;
+       char *device;
+#endif
+};
+
+struct pcap {
+       int fd;
+       int snapshot;
+       int linktype;
+       int tzoff;              /* timezone offset */
+       int offset;             /* offset for proper alignment */
+
+       struct pcap_sf sf;
+       struct pcap_md md;
+
+       /*
+        * Read buffer.
+        */
+       int bufsize;
+       u_char *buffer;
+       u_char *bp;
+       int cc;
+
+       /*
+        * Place holder for pcap_next().
+        */
+       u_char *pkt;
+
+       
+       /*
+        * Placeholder for filter code if bpf not in kernel.
+        */
+       struct bpf_program fcode;
+
+       char errbuf[PCAP_ERRBUF_SIZE];
+};
+
+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 *);
+
+/* Ultrix pads to make everything line up on a nice boundary */
+#if defined(ultrix) || defined(__alpha)
+#define       PCAP_FDDIPAD 3
+#endif
+
+/* XXX */
+extern int pcap_fddipad;
+#endif
diff --git a/pcap-linux.c b/pcap-linux.c
new file mode 100644 (file)
index 0000000..e1ff4d1
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.15 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#ifdef HAVE_NET_IF_ARP_H
+#include <net/if_arp.h>
+#else
+#include <linux/if_arp.h>
+#endif
+#include <linux/if_ether.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static struct ifreq saved_ifr;
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+void linux_restore_ifr(void);
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       *ps = p->md.stat;
+       return (0);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc;
+       register int bufsize;
+       register int caplen;
+       register u_char *bp;
+       struct sockaddr from;
+       int fromlen;
+
+       bp = p->buffer + p->offset;
+       bufsize = p->bufsize;
+       if (p->md.pad > 0) {
+               memset(bp, 0, p->md.pad);
+               bp += p->md.pad;
+               bufsize -= p->md.pad;
+       }
+
+again:
+       do {
+               fromlen = sizeof(from);
+               cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen);
+               if (cc < 0) {
+                       /* Don't choke when we get ptraced */
+                       switch (errno) {
+
+                       case EINTR:
+                                       goto again;
+
+                       case EWOULDBLOCK:
+                               return (0);             /* XXX */
+                       }
+                       sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+       } while (strcmp(p->md.device, from.sa_data));
+
+       /* If we need have leading zero bytes, adjust count */
+       cc += p->md.pad;
+       bp = p->buffer + p->offset;
+
+       /* If we need to step over leading junk, adjust count and pointer */
+       cc -= p->md.skip;
+       bp += p->md.skip;
+
+       /* Captured length can't exceed our read buffer size */
+       caplen = cc;
+       if (caplen > bufsize)
+               caplen = bufsize;
+
+       /* Captured length can't exceed the snapshot length */
+       if (caplen > p->snapshot)
+               caplen = p->snapshot;
+
+       if (p->fcode.bf_insns == NULL ||
+           bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
+               struct pcap_pkthdr h;
+
+               ++p->md.stat.ps_recv;
+               /* Get timestamp */
+               if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
+                       sprintf(p->errbuf, "SIOCGSTAMP: %s",
+                           pcap_strerror(errno));
+                       return (-1);
+               }
+               h.len = cc;
+               h.caplen = caplen;
+               (*callback)(user, &h, bp);
+               return (1);
+       }
+       return (0);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       register int fd, broadcast;
+       register pcap_t *p;
+       struct ifreq ifr;
+       struct sockaddr sa;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       memset(p, 0, sizeof(*p));
+       fd = -1;
+
+       fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+       if (fd < 0) {
+               sprintf(ebuf, "socket: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->fd = fd;
+
+       /* Bind to the interface name */
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_family = AF_INET;
+       (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
+       if (bind(p->fd, &sa, sizeof(sa))) {
+               sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
+               goto bad;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
+               sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       broadcast = 0;
+       switch (ifr.ifr_hwaddr.sa_family) {
+
+       case ARPHRD_ETHER:
+       case ARPHRD_METRICOM:
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               ++broadcast;
+               break;
+
+       case ARPHRD_EETHER:
+               p->linktype = DLT_EN3MB;
+               ++broadcast;
+               break;
+
+       case ARPHRD_AX25:
+               p->linktype = DLT_AX25;
+               ++broadcast;
+               break;
+
+       case ARPHRD_PRONET:
+               p->linktype = DLT_PRONET;
+               break;
+
+       case ARPHRD_CHAOS:
+               p->linktype = DLT_CHAOS;
+               break;
+
+       case ARPHRD_IEEE802:
+               p->linktype = DLT_IEEE802;
+               ++broadcast;
+               break;
+
+       case ARPHRD_ARCNET:
+               p->linktype = DLT_ARCNET;
+               ++broadcast;
+               break;
+
+       case ARPHRD_SLIP:
+       case ARPHRD_CSLIP:
+       case ARPHRD_SLIP6:
+       case ARPHRD_CSLIP6:
+       case ARPHRD_PPP:
+               p->linktype = DLT_RAW;
+               break;
+
+       case ARPHRD_LOOPBACK:
+               p->linktype = DLT_NULL;
+               p->md.pad = 2;
+               p->md.skip = 12;
+               break;
+
+#ifdef ARPHRD_FDDI
+       /* Not all versions of the kernel has this define */
+       case ARPHRD_FDDI:
+               p->linktype = DLT_FDDI;
+               ++broadcast;
+               break;
+#endif
+
+#ifdef notdef
+       case ARPHRD_LOCALTLK:
+       case ARPHRD_NETROM:
+       case ARPHRD_APPLETLK:
+       case ARPHRD_DLCI:
+       case ARPHRD_RSRVD:
+       case ARPHRD_ADAPT:
+       case ARPHRD_TUNNEL:
+       case ARPHRD_TUNNEL6:
+       case ARPHRD_FRAD:
+       case ARPHRD_SKIP:
+               /* XXX currently do not know what to do with these... */
+               abort();
+#endif
+
+       default:
+               sprintf(ebuf, "unknown physical layer type 0x%x",
+                   ifr.ifr_hwaddr.sa_family);
+               goto bad;
+       }
+
+       /* Base the buffer size on the interface MTU */
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) {
+               sprintf(ebuf, "SIOCGIFMTU: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* Leave room for link header (which is never large under linux...) */
+       p->bufsize = ifr.ifr_mtu + 64;
+
+       p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+       if (p->buffer == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* XXX */
+       if (promisc && broadcast) {
+               memset(&ifr, 0, sizeof(ifr));
+               strcpy(ifr.ifr_name, device);
+               if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {
+                       sprintf(ebuf, "SIOCGIFFLAGS: %s", pcap_strerror(errno));
+                       goto bad;
+               }
+               saved_ifr = ifr;
+               ifr.ifr_flags |= IFF_PROMISC;
+               if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {
+                       sprintf(ebuf, "SIOCSIFFLAGS: %s", pcap_strerror(errno));
+                       goto bad;
+               }
+               ifr.ifr_flags &= ~IFF_PROMISC;
+               atexit(linux_restore_ifr);
+       }
+
+       p->md.device = strdup(device);
+       if (p->md.device == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->snapshot = snaplen;
+
+       return (p);
+bad:
+       if (fd >= 0)
+               (void)close(fd);
+       if (p->buffer != NULL)
+               free(p->buffer);
+       if (p->md.device != NULL)
+               free(p->md.device);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       p->fcode = *fp;
+       return (0);
+}
+
+void
+linux_restore_ifr(void)
+{
+       register int fd;
+
+       fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
+       if (fd < 0)
+               fprintf(stderr, "linux socket: %s", pcap_strerror(errno));
+       else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
+               fprintf(stderr, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno));
+}
diff --git a/pcap-namedb.h b/pcap-namedb.h
new file mode 100644 (file)
index 0000000..f57c6a2
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.5 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_ethers_h
+#define lib_pcap_ethers_h
+
+/*
+ * 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 *);
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int    pcap_nametoport(const char *, int *, int *);
+int    pcap_nametoproto(const char *);
+int    pcap_nametoeproto(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 *);
+
+#endif
diff --git a/pcap-nit.c b/pcap-nit.c
new file mode 100644 (file)
index 0000000..a2e2a43
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.31 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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"
+
+#include "gnuc.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 *);
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       *ps = p->md.stat;
+       return (0);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc, n;
+       register struct bpf_insn *fcode = p->fcode.bf_insns;
+       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);
+                       sprintf(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) {
+               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:
+                       sprintf(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(fcode, 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
+nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
+{
+       struct nit_ioc nioc;
+
+       bzero((char *)&nioc, 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) {
+               sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       int fd;
+       struct sockaddr_nit snit;
+       register pcap_t *p;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               strcpy(ebuf, pcap_strerror(errno));
+               return (NULL);
+       }
+
+       if (snaplen < 96)
+               /*
+                * NIT requires a snapshot length of at least 96.
+                */
+               snaplen = 96;
+
+       bzero(p, sizeof(*p));
+       p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
+       if (fd < 0) {
+               sprintf(ebuf, "socket: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       snit.snit_family = AF_NIT;
+       (void)strncpy(snit.snit_ifname, device, NITIFSIZ);
+
+       if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
+               sprintf(ebuf, "bind: %s: %s", snit.snit_ifname,
+                       pcap_strerror(errno));
+               goto bad;
+       }
+       p->snapshot = snaplen;
+       nit_setflags(p->fd, promisc, to_ms, ebuf);
+
+       /*
+        * NIT supports only ethernets.
+        */
+       p->linktype = DLT_EN10MB;
+
+       p->bufsize = BUFSPACE;
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               strcpy(ebuf, pcap_strerror(errno));
+               goto bad;
+       }
+       return (p);
+ bad:
+       if (fd >= 0)
+               close(fd);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       p->fcode = *fp;
+       return (0);
+}
diff --git a/pcap-nit.h b/pcap-nit.h
new file mode 100644 (file)
index 0000000..3e7190a
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 1990, 1994
+ *     The 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, Lawrence Berkeley Laboratory,
+ * Berkeley, CA.  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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/Attic/pcap-nit.h,v 1.2 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
diff --git a/pcap-null.c b/pcap-null.c
new file mode 100644 (file)
index 0000000..cbc818b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.7 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+
+#include <string.h>
+
+#include "gnuc.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";
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       (void)sprintf(p->errbuf, "pcap_stats: %s", nosup);
+       return (-1);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+
+       (void)sprintf(p->errbuf, "pcap_read: %s", nosup);
+       return (-1);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+
+       (void)strcpy(ebuf, nosup);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       if (p->sf.rfile == NULL) {
+               (void)sprintf(p->errbuf, "pcap_setfilter: %s", nosup);
+               return (-1);
+       }
+       p->fcode = *fp;
+       return (0);
+}
diff --git a/pcap-pf.c b/pcap-pf.c
new file mode 100644 (file)
index 0000000..542de8a
--- /dev/null
+++ b/pcap-pf.c
@@ -0,0 +1,351 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.54 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#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>
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * 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)
+
+int
+pcap_read(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
+{
+       register u_char *p, *bp;
+       struct bpf_insn *fcode;
+       register int cc, n, buflen, inc;
+       register struct enstamp *sp;
+#ifdef LBL_ALIGN
+       struct enstamp stamp;
+#endif
+#ifdef PCAP_FDDIPAD
+       register int pad;
+#endif
+
+       fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns;
+ 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;
+                       }
+                       sprintf(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
+       if (pc->linktype == DLT_FDDI)
+               pad = pcap_fddipad;
+       else
+               pad = 0;
+#endif
+       while (cc > 0) {
+               if (cc < sizeof(*sp)) {
+                       sprintf(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)) {
+                       sprintf(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;
+#ifdef PCAP_FDDIPAD
+               p += pad;
+               buflen -= pad;
+#endif
+               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.
+                */
+               if (fcode == NULL ||
+                   bpf_filter(fcode, 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
+                       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);
+}
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       ps->ps_recv = p->md.TotAccepted;
+       ps->ps_drop = p->md.TotDrops;
+       ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
+       return (0);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       pcap_t *p;
+       short enmode;
+       int backlog = -1;       /* request the most */
+       struct enfilter Filter;
+       struct endevp devparams;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               sprintf(ebuf, "pcap_open_live: %s", pcap_strerror(errno));
+               return (0);
+       }
+       bzero((char *)p, sizeof(*p));
+       p->fd = pfopen(device, O_RDONLY);
+       if (p->fd < 0) {
+               sprintf(ebuf, "pf open: %s: %s\n\
+your system may not be properly configured; see \"man packetfilter(4)\"\n",
+                       device, pcap_strerror(errno));
+               goto bad;
+       }
+       p->md.OrigMissed = -1;
+       enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
+       if (promisc)
+               enmode |= ENPROMISC;
+       if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
+               sprintf(ebuf, "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) {
+               sprintf(ebuf, "EIOCSETW: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       /* discover interface type */
+       if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
+               sprintf(ebuf, "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;
+               break;
+
+       case ENDT_FDDI:
+               p->linktype = DLT_FDDI;
+               break;
+
+       default:
+               /*
+                * XXX
+                * Currently, the Ultrix packet filter supports only
+                * Ethernet and FDDI.  Eventually, support for SLIP and PPP
+                * (and possibly others: T1?) should be added.
+                */
+#ifdef notdef
+               warning(
+                  "Packet filter data-link type %d unknown, assuming Ethernet",
+                   devparams.end_dev_type);
+#endif
+               p->linktype = DLT_EN10MB;
+               p->offset = 2;
+               break;
+       }
+       /* set truncation */
+#ifdef PCAP_FDDIPAD
+       if (p->linktype == DLT_FDDI)
+               /* packetfilter includes the padding in the snapshot */
+               snaplen += pcap_fddipad;
+#endif
+       if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {
+               sprintf(ebuf, "EIOCTRUNCATE: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->snapshot = snaplen;
+       /* accept all packets */
+       bzero((char *)&Filter, sizeof(Filter));
+       Filter.enf_Priority = 37;       /* anything > 2 */
+       Filter.enf_FilterLen = 0;       /* means "always true" */
+       if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
+               sprintf(ebuf, "EIOCSETF: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       if (to_ms != 0) {
+               struct timeval timeout;
+               timeout.tv_sec = to_ms / 1000;
+               timeout.tv_usec = (to_ms * 1000) % 1000000;
+               if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
+                       sprintf(ebuf, "EIOCSRTIMEOUT: %s",
+                               pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+       p->bufsize = BUFSPACE;
+       p->buffer = (u_char*)malloc(p->bufsize + p->offset);
+
+       return (p);
+ bad:
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       /*
+        * See if BIOCSETF works.  If it does, the kernel supports
+        * BPF-style filters, and we do not need to do post-filtering.
+        */
+       p->md.use_bpf = (ioctl(p->fd, BIOCSETF, (caddr_t)fp) >= 0);
+       if (p->md.use_bpf) {
+               struct bpf_version bv;
+
+               if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) < 0) {
+                       sprintf(p->errbuf, "BIOCVERSION: %s",
+                               pcap_strerror(errno));
+                       return (-1);
+               }
+               else if (bv.bv_major != BPF_MAJOR_VERSION ||
+                        bv.bv_minor < BPF_MINOR_VERSION) {
+                       fprintf(stderr,
+               "requires bpf language %d.%d or higher; kernel is %d.%d",
+                               BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+                             bv.bv_major, bv.bv_minor);
+                       /* don't give up, just be inefficient */
+                       p->md.use_bpf = 0;
+               }
+       } else
+               p->fcode = *fp;
+
+       /*XXX this goes in tcpdump*/
+       if (p->md.use_bpf)
+               fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
+       else
+               fprintf(stderr, "tcpdump: Filtering in user process\n");
+       return (0);
+}
diff --git a/pcap-pf.h b/pcap-pf.h
new file mode 100644 (file)
index 0000000..2f400b9
--- /dev/null
+++ b/pcap-pf.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 1990, 1994
+ *     The 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, Lawrence Berkeley Laboratory,
+ * Berkeley, CA.  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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/Attic/pcap-pf.h,v 1.2 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
diff --git a/pcap-snit.c b/pcap-snit.c
new file mode 100644 (file)
index 0000000..6971d3b
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * 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, [email protected], Columbia University in May, 1989.
+ * This module now handles the STREAMS based NIT.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.45 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#include "gnuc.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 *);
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+
+       *ps = p->md.stat;
+       return (0);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc, n;
+       register struct bpf_insn *fcode = p->fcode.bf_insns;
+       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);
+                       sprintf(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) {
+               ++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(fcode, 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
+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) {
+                       sprintf(ebuf, "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) {
+               sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       struct strioctl si;             /* struct for ioctl() */
+       struct ifreq ifr;               /* interface request struct */
+       int chunksize = CHUNKSIZE;
+       int fd;
+       static char dev[] = "/dev/nit";
+       register pcap_t *p;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               strcpy(ebuf, pcap_strerror(errno));
+               return (NULL);
+       }
+
+       if (snaplen < 96)
+               /*
+                * NIT requires a snapshot length of at least 96.
+                */
+               snaplen = 96;
+
+       bzero(p, sizeof(*p));
+       p->fd = fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               sprintf(ebuf, "%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) {
+               sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       if (ioctl(fd, I_PUSH, "nbuf") < 0) {
+               sprintf(ebuf, "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) {
+               sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* request the interface */
+       strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
+       si.ic_cmd = NIOCBIND;
+       si.ic_len = sizeof(ifr);
+       si.ic_dp = (char *)&ifr;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               sprintf(ebuf, "NIOCBIND: %s: %s",
+                       ifr.ifr_name, pcap_strerror(errno));
+               goto bad;
+       }
+
+       /* set the snapshot length */
+       si.ic_cmd = NIOCSSNAP;
+       si.ic_len = sizeof(snaplen);
+       si.ic_dp = (char *)&snaplen;
+       if (ioctl(fd, I_STR, (char *)&si) < 0) {
+               sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->snapshot = snaplen;
+       if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 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) {
+               strcpy(ebuf, pcap_strerror(errno));
+               goto bad;
+       }
+       return (p);
+ bad:
+       if (fd >= 0)
+               close(fd);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       p->fcode = *fp;
+       return (0);
+}
diff --git a/pcap-snoop.c b/pcap-snoop.c
new file mode 100644 (file)
index 0000000..1ea7fab
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.20 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#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"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       register struct snoopheader *sh;
+       register int datalen;
+       register int caplen;
+       register u_char *cp;
+
+again:
+       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 */
+               }
+               sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       sh = (struct snoopheader *)p->buffer;
+       datalen = sh->snoop_packetlen;
+       caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
+       cp = (u_char *)(sh + 1) + p->offset;            /* XXX */
+
+       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 = sh->snoop_timestamp;
+               h.len = datalen;
+               h.caplen = caplen;
+               (*callback)(user, &h, cp);
+               return (1);
+       }
+       return (0);
+}
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       register struct rawstats *rs;
+       struct rawstats rawstats;
+
+       rs = &rawstats;
+       bzero((char *)rs, sizeof(*rs));
+       if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
+               sprintf(p->errbuf, "SIOCRAWSTATS: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       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 = p->md.stat;
+       return (0);
+}
+
+/* XXX can't disable promiscuous */
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       int fd;
+       struct sockaddr_raw sr;
+       struct snoopfilter sf;
+       u_int v;
+       pcap_t *p;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       bzero((char *)p, sizeof(*p));
+       fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
+       if (fd < 0) {
+               sprintf(ebuf, "snoop socket: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->fd = fd;
+       bzero((char *)&sr, sizeof(sr));
+       sr.sr_family = AF_RAW;
+       (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
+       if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
+               sprintf(ebuf, "snoop bind: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       bzero((char *)&sf, sizeof(sf));
+       if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
+               sprintf(ebuf, "SIOCADDSNOOP: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       v = 64 * 1024;
+       (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
+       if (ioctl(fd, SIOCSNOOPLEN, &snaplen) < 0) {
+               sprintf(ebuf, "SIOCSNOOPLEN: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->snapshot = snaplen;
+       v = 1;
+       if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
+               sprintf(ebuf, "SIOCSNOOPING: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       /*
+        * XXX hack - map device name to link layer type
+        */
+       if (strncmp("et", device, 2) == 0 ||    /* Challenge 10 Mbit */
+           strncmp("ec", device, 2) == 0 ||    /* Indigo/Indy 10 Mbit,
+                                                  O2 10/100 */
+           strncmp("ef", device, 2) == 0 ||    /* O200/2000 10/100 Mbit */
+           strncmp("gfe", device, 3) == 0 ||   /* GIO 100 Mbit */
+           strncmp("fxp", device, 3) == 0 ||   /* Challenge VME Enet */
+           strncmp("ep", device, 2) == 0 ||    /* Challenge 8x10 Mbit EPLEX */
+           strncmp("vfe", device, 3) == 0 ||   /* Challenge VME 100Mbit */
+           strncmp("fa", device, 2) == 0 ||
+           strncmp("qaa", device, 3) == 0) {
+               p->linktype = DLT_EN10MB;
+               p->offset = RAW_HDRPAD(sizeof(struct ether_header));
+       } else if (strncmp("ipg", device, 3) == 0 ||
+                  strncmp("rns", device, 3) == 0 ||    /* O2/200/2000 FDDI */
+                  strncmp("xpi", device, 3) == 0) {
+               p->linktype = DLT_FDDI;
+               p->offset = 3;                          /* XXX yeah? */
+       } else if (strncmp("ppp", device, 3) == 0) {
+               p->linktype = DLT_RAW;
+       } else if (strncmp("lo", device, 2) == 0) {
+               p->linktype = DLT_NULL;
+       } else {
+               sprintf(ebuf, "snoop: unknown physical layer type");
+               goto bad;
+       }
+
+       p->bufsize = 4096;                              /* XXX */
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       return (p);
+ bad:
+       (void)close(fd);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+
+       p->fcode = *fp;
+       return (0);
+}
diff --git a/pcap.3 b/pcap.3
new file mode 100644 (file)
index 0000000..23e5b52
--- /dev/null
+++ b/pcap.3
@@ -0,0 +1,340 @@
+.\" 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 3  "24 June 1998"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_live(char *device, int snaplen,
+.ti +8
+int promisc, int to_ms, char *ebuf)
+pcap_t *pcap_open_offline(char *fname, char *ebuf)
+pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)
+.ft
+.LP
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+char *pcap_lookupdev(char *errbuf)
+int pcap_lookupnet(char *device, bpf_u_int32 *netp,
+.ti +8
+bpf_u_int32 *maskp, char *errbuf)
+.ft
+.LP
+.ft B
+int pcap_dispatch(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user)
+int pcap_loop(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user)
+void pcap_dump(u_char *user, struct pcap_pkthdr *h,
+.ti +8
+u_char *sp)
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+char *str, int optimize, bpf_u_int32 netmask)
+int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+.ft
+.LP
+.ft B
+u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p)
+int pcap_snapshot(pcap_t *p)
+int pcap_is_swapped(pcap_t *p)
+int pcap_major_version(pcap_t *p)
+int pcap_minor_version(pcap_t *p)
+int pcap_stats(pcap_t *p, struct pcap_stat *ps)
+FILE *pcap_file(pcap_t *p)
+int pcap_fileno(pcap_t *p)
+void pcap_perror(pcap_t *p, char *prefix)
+char *pcap_geterr(pcap_t *p)
+char *pcap_strerror(int error)
+.ft
+.LP
+.ft B
+void pcap_close(pcap_t *p)
+void pcap_dump_close(pcap_dumper_t *p)
+.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.
+.PP
+.SH ROUTINES
+.B pcap_open_live()
+is used to obtain a packet capture descriptor to look
+at packets on the network.
+.I device
+is a string that specifies the network device to open.
+.I snaplen
+specifies the maximum number of bytes to capture.
+.I promisc
+specifies if the interface is to be put into promiscuous mode.
+(Note that even if this parameter is false, the interface
+could well be in promiscuous mode for some other reason.)
+.I to_ms
+specifies the read timeout in milliseconds.
+.I ebuf
+is used to return error text and is only set when
+.B pcap_open_live()
+fails and returns
+.BR NULL .
+.PP
+.B pcap_open_offline()
+is called to open a ``savefile'' for reading.
+.I fname
+specifies the name of the file to open. The file has
+the same format as those used by
+.B tcpdump(1)
+and
+.BR tcpslice(1) .
+The name "-" in a synonym for
+.BR stdin .
+.I ebuf
+is used to return error text and is only set when
+.B pcap_open_offline()
+fails and returns
+.BR NULL .
+.PP
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing. The name "-" in a synonym
+for
+.BR stdout .
+.B NULL
+is returned on failure.
+.I p
+is a
+.I pcap
+struct as returned by
+.B pcap_open_offline()
+or
+.BR pcap_open_live() .
+.I fname
+specifies the name of the file to open.
+If
+.B NULL
+is returned,
+.B pcap_geterr()
+can be used to get the error text.
+.PP
+.B pcap_lookupdev()
+returns a pointer to a network device suitable for use with
+.B pcap_open_live()
+and
+.BR pcap_lookupnet() .
+If there is an error,
+.B NULL
+is returned and
+.I errbuf
+is filled in with with an appropriate error message.
+.PP
+.B pcap_lookupnet()
+is used to determine the network number and mask
+associated with the network device
+.BR device .
+Both
+.I netp
+and
+.I maskp
+are
+.I bpf_u_int32
+pointers.
+A return of -1 indicates an error in which case
+.I errbuf
+is filled in with with an appropriate error message.
+.PP
+.B pcap_dispatch()
+is used to collect and process packets.
+.I cnt
+specifies the maximum number of packets to process before returning. A
+.I cnt
+of -1 processes all the packets received in one buffer. A
+.I cnt
+of 0 processes all packets until an error occurs,
+.B EOF
+is reached, or the read times out (when doing live reads and a non-zero
+read timeout is specified).
+.I callback
+specifies a routine to be called with three arguments:
+a
+.I u_char
+pointer which is passed in from
+.BR pcap_dispatch() ,
+a pointer to the
+.I pcap_pkthdr
+struct (which precede the actual network headers and data),
+and a
+.I u_char
+pointer to the packet data. The number of packets read is returned.
+Zero is returned when
+.B EOF
+is reached in a ``savefile.'' A return of -1 indicates
+an error in which case
+.B pcap_perror()
+or
+.BR pcap_geterr()
+may be used to display the error text.
+.PP
+.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
+.BR pcap_dispatch() .
+.PP
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program.
+.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 netmask of the local net.
+.PP
+.B pcap_setfilter()
+is used to specify a filter program.
+.I fp
+is a pointer to an array of
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile() .
+.B \-1
+is returned on failure;
+.B 0
+is returned on success.
+.PP
+.B pcap_loop()
+is similar to
+.B pcap_dispatch()
+except it keeps reading packets until
+.I cnt
+packets are processed or an error occurs.
+It does
+.B not
+return when live read timeouts occur.
+Rather, specifying a non-zero read timeout to
+.B pcap_open_live()
+and then calling
+.B pcap_dispatch()
+allows the reception and processing of any packets that arrive when the
+timeout occurs.
+A negative
+.I cnt
+causes
+.B pcap_loop()
+to loop forever (or at least until an error occurs).
+.PP
+.B pcap_next()
+returns a
+.I u_char
+pointer to the next packet.
+.PP
+.B pcap_datalink()
+returns the link layer type, e.g.
+.BR DLT_EN10MB .
+.PP
+.B pcap_snapshot()
+returns the snapshot length specified when
+.B pcap_open_live
+was called.
+.PP
+.B pcap_is_swapped()
+returns true if the current ``savefile'' uses a different byte order
+than the current system.
+.PP
+.B pcap_major_version()
+returns the major number of the version of the pcap used to write the
+savefile.
+.PP
+.B pcap_minor_version()
+returns the minor number of the version of the pcap used to write the
+savefile.
+.PP
+.B pcap_file()
+returns the name of the ``savefile.''
+.PP
+.B int pcap_stats()
+returns 0 and fills in a
+.B pcap_stat
+struct. The values represent packet statistics from the start of the
+run to the time of the call. If there is an error or the under lying
+packet capture doesn't support packet statistics, -1 is returned and
+the error text can be obtained with
+.B pcap_perror()
+or
+.BR pcap_geterr() .
+.PP
+.B pcap_fileno()
+returns the file descriptor number of the ``savefile.''
+.PP
+.B pcap_perror()
+prints the text of the last pcap library error on
+.BR stderr ,
+prefixed by
+.IR prefix .
+.PP
+.B pcap_geterr()
+returns the error text pertaining to the last pcap library error.
+.PP
+.B pcap_strerror()
+is provided in case
+.BR strerror (1)
+isn't available.
+.PP
+.B pcap_close()
+closes the files associated with
+.I p
+and deallocates resources.
+.PP
+.B pcap_dump_close()
+closes the ``savefile.''
+.PP
+.SH SEE ALSO
+tcpdump(1), tcpslice(1)
+.SH AUTHORS
+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 via anonymous ftp:
+.LP
+.RS
+.I ftp://ftp.ee.lbl.gov/libpcap.tar.Z
+.RE
+.SH BUGS
+Please send bug reports to [email protected].
diff --git a/pcap.c b/pcap.c
new file mode 100644 (file)
index 0000000..0f1848e
--- /dev/null
+++ b/pcap.c
@@ -0,0 +1,206 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.29 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+int
+pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+
+       if (p->sf.rfile != NULL)
+               return (pcap_offline_read(p, cnt, callback, user));
+       return (pcap_read(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)
+                       n = pcap_offline_read(p, cnt, callback, user);
+               else {
+                       /*
+                        * XXX keep reading until we get something
+                        * (or an error occurs)
+                        */
+                       do {
+                               n = pcap_read(p, cnt, callback, user);
+                       } while (n == 0);
+               }
+               if (n <= 0)
+                       return (n);
+               if (cnt > 0) {
+                       cnt -= n;
+                       if (cnt <= 0)
+                               return (0);
+               }
+       }
+}
+
+struct singleton {
+       struct pcap_pkthdr *hdr;
+       const u_char *pkt;
+};
+
+
+static void
+pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
+{
+       struct singleton *sp = (struct singleton *)userData;
+       *sp->hdr = *h;
+       sp->pkt = pkt;
+}
+
+const u_char *
+pcap_next(pcap_t *p, struct pcap_pkthdr *h)
+{
+       struct singleton s;
+
+       s.hdr = h;
+       if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
+               return (0);
+       return (s.pkt);
+}
+
+int
+pcap_datalink(pcap_t *p)
+{
+       return (p->linktype);
+}
+
+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)
+{
+       return (p->fd);
+}
+
+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);
+}
+
+/*
+ * Not all systems have strerror().
+ */
+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[20];
+
+       if ((unsigned int)errnum < sys_nerr)
+               return ((char *)sys_errlist[errnum]);
+       (void)sprintf(ebuf, "Unknown error: %d", errnum);
+       return(ebuf);
+#endif
+}
+
+void
+pcap_close(pcap_t *p)
+{
+       /*XXX*/
+       if (p->fd >= 0)
+               close(p->fd);
+       if (p->sf.rfile != NULL) {
+               (void)fclose(p->sf.rfile);
+               if (p->sf.base != NULL)
+                       free(p->sf.base);
+       } else if (p->buffer != NULL)
+               free(p->buffer);
+#ifdef linux
+       if (p->md.device != NULL)
+               free(p->md.device);
+#endif
+       
+       free(p);
+}
diff --git a/pcap.h b/pcap.h
new file mode 100644 (file)
index 0000000..cffbad8
--- /dev/null
+++ b/pcap.h
@@ -0,0 +1,137 @@
+/*
+ * 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.21 1999-10-07 23:46:40 mcr Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_h
+#define lib_pcap_h
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+
+#include <stdio.h>
+
+#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;
+
+/*
+ * 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.
+ */
+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 (DLT_*) */
+};
+
+/*
+ * Each packet in the dump file is prepended with this generic header.
+ * This gets around the problem of different headers for different
+ * packet interfaces.
+ */
+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 XXX not yet supported */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+                            const u_char *);
+
+char   *pcap_lookupdev(char *);
+int    pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+pcap_t *pcap_open_live(char *, int, int, int, char *);
+pcap_t *pcap_open_offline(const char *, char *);
+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_stats(pcap_t *, struct pcap_stat *);
+int    pcap_setfilter(pcap_t *, struct bpf_program *);
+void   pcap_perror(pcap_t *, char *);
+char   *pcap_strerror(int);
+char   *pcap_geterr(pcap_t *);
+int    pcap_compile(pcap_t *, struct bpf_program *, char *, int,
+           bpf_u_int32);
+/* XXX */
+int    pcap_freecode(pcap_t *, struct bpf_program *);
+int    pcap_datalink(pcap_t *);
+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 *);
+void   pcap_dump_close(pcap_dumper_t *);
+void   pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+/* XXX this guy lives in the bpf tree */
+u_int  bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+char   *bpf_image(struct bpf_insn *, int);
+#endif
diff --git a/ppp.h b/ppp.h
new file mode 100644 (file)
index 0000000..c932b1e
--- /dev/null
+++ b/ppp.h
@@ -0,0 +1,50 @@
+/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.7 1999-10-07 23:46:40 mcr 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 */
+
+/* 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_HELLO      0x0201  /* 802.1d Hello Packets */
+#define PPP_LUXCOM     0x0231  /* Luxcom */
+#define PPP_SNS                0x0233  /* Sigma Network Systems */
+
+#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_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/savefile.c b/savefile.c
new file mode 100644 (file)
index 0000000..708c95d
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.37 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/*
+ * 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 packets are always written in network byte order.
+ *
+ * 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) )
+
+#define SFERR_TRUNC            1
+#define SFERR_BADVERSION       2
+#define SFERR_BADF             3
+#define SFERR_EOF              4 /* not really an error, just a status */
+
+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);
+}
+
+static void
+swap_hdr(struct pcap_file_header *hp)
+{
+       hp->version_major = SWAPSHORT(hp->version_major);
+       hp->version_minor = SWAPSHORT(hp->version_minor);
+       hp->thiszone = SWAPLONG(hp->thiszone);
+       hp->sigfigs = SWAPLONG(hp->sigfigs);
+       hp->snaplen = SWAPLONG(hp->snaplen);
+       hp->linktype = SWAPLONG(hp->linktype);
+}
+
+pcap_t *
+pcap_open_offline(const char *fname, char *errbuf)
+{
+       register pcap_t *p;
+       register FILE *fp;
+       struct pcap_file_header hdr;
+       int linklen;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               strcpy(errbuf, "out of swap");
+               return (NULL);
+       }
+
+       memset((char *)p, 0, sizeof(*p));
+       /*
+        * Set this field so we don't close stdin in pcap_close!
+        */
+       p->fd = -1;
+
+       if (fname[0] == '-' && fname[1] == '\0')
+               fp = stdin;
+       else {
+               fp = fopen(fname, "r");
+               if (fp == NULL) {
+                       sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+       if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
+               sprintf(errbuf, "fread: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       if (hdr.magic != TCPDUMP_MAGIC) {
+               if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) {
+                       sprintf(errbuf, "bad dump file format");
+                       goto bad;
+               }
+               p->sf.swapped = 1;
+               swap_hdr(&hdr);
+       }
+       if (hdr.version_major < PCAP_VERSION_MAJOR) {
+               sprintf(errbuf, "archaic file format");
+               goto bad;
+       }
+       p->tzoff = hdr.thiszone;
+       p->snapshot = hdr.snaplen;
+       p->linktype = hdr.linktype;
+       p->sf.rfile = fp;
+       p->bufsize = hdr.snaplen;
+
+       /* Align link header as required for proper data alignment */
+       /* XXX should handle all types */
+       switch (p->linktype) {
+
+       case DLT_EN10MB:
+               linklen = 14;
+               break;
+
+       case DLT_FDDI:
+               linklen = 13 + 8;       /* fddi_header + llc */
+               break;
+
+       case DLT_NULL:
+       default:
+               linklen = 0;
+               break;
+       }
+
+       p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT);
+       p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT);
+       p->sf.version_major = hdr.version_major;
+       p->sf.version_minor = hdr.version_minor;
+#ifdef PCAP_FDDIPAD
+       /* XXX padding only needed for kernel fcode */
+       pcap_fddipad = 0;
+#endif
+
+       return (p);
+ bad:
+       free(p);
+       return (NULL);
+}
+
+/*
+ * Read sf_readfile and return the next packet.  Return the header in hdr
+ * and the contents in buf.  Return 0 on success, SFERR_EOF if there were
+ * no more packets, and SFERR_TRUNC if a partial packet was encountered.
+ */
+static int
+sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
+{
+       FILE *fp = p->sf.rfile;
+
+       /* read the stamp */
+       if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
+               /* probably an EOF, though could be a truncated packet */
+               return (1);
+       }
+
+       if (p->sf.swapped) {
+               /* these were written in opposite byte order */
+               hdr->caplen = SWAPLONG(hdr->caplen);
+               hdr->len = SWAPLONG(hdr->len);
+               hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
+               hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
+       }
+       /*
+        * 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.
+        */
+       if (p->sf.version_minor < 3 ||
+           (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) {
+               int t = hdr->caplen;
+               hdr->caplen = hdr->len;
+               hdr->len = t;
+       }
+
+       if (hdr->caplen > buflen) {
+               /*
+                * 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 int tsize = 0;
+
+               if (hdr->caplen > 65535) {
+                       sprintf(p->errbuf, "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;
+                               sprintf(p->errbuf, "BUFMOD hack malloc");
+                               return (-1);
+                       }
+               }
+               if (fread((char *)tp, hdr->caplen, 1, fp) != 1) {
+                       sprintf(p->errbuf, "truncated dump file");
+                       return (-1);
+               }
+               /*
+                * We can only keep up to buflen bytes.  Since caplen > buflen
+                * is exactly how we got here, we know we can only keep the
+                * first buflen 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 = buflen;
+               memcpy((char *)buf, (char *)tp, buflen);
+
+       } else {
+               /* read the packet itself */
+
+               if (fread((char *)buf, hdr->caplen, 1, fp) != 1) {
+                       sprintf(p->errbuf, "truncated dump file");
+                       return (-1);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Print out packets stored in the file initialized by sf_read_init().
+ * 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 = p->fcode.bf_insns;
+       int status = 0;
+       int n = 0;
+
+       while (status == 0) {
+               struct pcap_pkthdr h;
+
+               status = sf_next_packet(p, &h, p->buffer, p->bufsize);
+               if (status) {
+                       if (status == 1)
+                               return (0);
+                       return (status);
+               }
+
+               if (fcode == NULL ||
+                   bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
+                       (*callback)(user, &h, p->buffer);
+                       if (++n >= cnt && cnt > 0)
+                               break;
+               }
+       }
+       /*XXX this breaks semantics tcpslice expects */
+       return (n);
+}
+
+/*
+ * 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;
+
+       f = (FILE *)user;
+       /* XXX we should check the return status */
+       (void)fwrite((char *)h, sizeof(*h), 1, f);
+       (void)fwrite((char *)sp, h->caplen, 1, 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;
+       if (fname[0] == '-' && fname[1] == '\0')
+               f = stdout;
+       else {
+               f = fopen(fname, "w");
+               if (f == NULL) {
+                       sprintf(p->errbuf, "%s: %s",
+                           fname, pcap_strerror(errno));
+                       return (NULL);
+               }
+       }
+       (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot);
+       return ((pcap_dumper_t *)f);
+}
+
+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/scanner.l b/scanner.l
new file mode 100644 (file)
index 0000000..a556aee
--- /dev/null
+++ b/scanner.l
@@ -0,0 +1,203 @@
+%{
+/*
+ * 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[] =
+    "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.56 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include <pcap-namedb.h>
+#include "tokdefs.h"
+
+#include "gnuc.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_UNPUT
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max)\
+ {\
+       char *src = in_buffer;\
+       int i;\
+\
+       if (*src == 0)\
+               result = YY_NULL;\
+       else {\
+               for (i = 0; *src && i < max; ++i)\
+                       buf[i] = *src++;\
+               in_buffer += i;\
+               result = i;\
+       }\
+ }
+#else
+#undef getc
+#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
+#endif
+
+#define yylval pcap_lval
+extern YYSTYPE yylval;
+
+static char *in_buffer;
+
+%}
+
+N              ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B              ([0-9A-Fa-f][0-9A-Fa-f]?)
+
+%a 3000
+
+%%
+dst            return DST;
+src            return SRC;
+
+link|ether|ppp|slip  return LINK;
+fddi           return LINK;
+arp            return ARP;
+rarp           return RARP;
+ip             return IP;
+tcp            return TCP;
+udp            return UDP;
+icmp           return ICMP;
+igmp           return IGMP;
+igrp           return IGRP;
+
+atalk          return ATALK;
+decnet         return DECNET;
+lat            return LAT;
+sca            return SCA;
+moprc          return MOPRC;
+mopdl          return MOPDL;
+
+host           return HOST;
+net            return NET;
+mask           return MASK;
+port           return PORT;
+proto          return PROTO;
+
+gateway                return GATEWAY;
+
+less           return LESS;
+greater                return GREATER;
+byte           return BYTE;
+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;
+
+[ \n\t]                        ;
+[+\-*/:\[\]!<>()&|=]   return yytext[0];
+">="                   return GEQ;
+"<="                   return LEQ;
+"!="                   return NEQ;
+"=="                   return '=';
+"<<"                   return LSH;
+">>"                   return RSH;
+{N}                    { yylval.i = stoi((char *)yytext); return NUM; }
+({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})        {
+                       yylval.s = sdup((char *)yytext); return HID; }
+{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
+                         return EID; }
+{B}:+({B}:+)+          { bpf_error("bogus ethernet address %s", yytext); }
+[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!<>()&|=]+i {
+                       bpf_error("illegal token: %s\n", yytext); }
+.                      { bpf_error("illegal char '%c'", *yytext); }
+%%
+void
+lex_init(buf)
+       char *buf;
+{
+       in_buffer = buf;
+}
+
+/*
+ * 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;
+}
+