aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2005-05-29 17:46:52 +0000
committerSam Leffler <sam@FreeBSD.org>2005-05-29 17:46:52 +0000
commit04fb274578a5def82f89c3a522b3f28c8916aa1f (patch)
treeb733a54335042f876f8969020dc9dc4408f485f4
parentfeb4ecdbac00a57548c3e75b168107e9c470f354 (diff)
downloadsrc-04fb274578a5def82f89c3a522b3f28c8916aa1f.tar.gz
src-04fb274578a5def82f89c3a522b3f28c8916aa1f.zip
Virgin import of libpcap v0.9.1 (alpha 096) from tcpdump.org
Notes
Notes: svn path=/vendor/libpcap/dist/; revision=146768
-rw-r--r--contrib/libpcap/CHANGES2
-rw-r--r--contrib/libpcap/CREDITS7
-rw-r--r--contrib/libpcap/FILES21
-rw-r--r--contrib/libpcap/INSTALL.txt10
-rw-r--r--contrib/libpcap/Makefile.in52
-rw-r--r--contrib/libpcap/README8
-rw-r--r--contrib/libpcap/README.hpux8
-rw-r--r--contrib/libpcap/README.macosx43
-rw-r--r--contrib/libpcap/VERSION2
-rw-r--r--contrib/libpcap/aclocal.m437
-rw-r--r--contrib/libpcap/bpf/net/bpf_filter.c2
-rw-r--r--contrib/libpcap/bpf_dump.c2
-rw-r--r--contrib/libpcap/bpf_image.c2
-rw-r--r--contrib/libpcap/config.h.in189
-rwxr-xr-xcontrib/libpcap/configure1500
-rwxr-xr-xcontrib/libpcap/configure.in428
-rw-r--r--contrib/libpcap/etherent.c2
-rw-r--r--contrib/libpcap/ethertype.h8
-rw-r--r--contrib/libpcap/fad-getad.c11
-rw-r--r--contrib/libpcap/fad-gifc.c55
-rw-r--r--contrib/libpcap/fad-glifc.c63
-rw-r--r--contrib/libpcap/fad-null.c2
-rw-r--r--contrib/libpcap/fad-win32.c47
-rw-r--r--contrib/libpcap/gencode.c626
-rw-r--r--contrib/libpcap/gencode.h3
-rw-r--r--contrib/libpcap/grammar.y8
-rw-r--r--contrib/libpcap/inet.c65
-rw-r--r--contrib/libpcap/nametoaddr.c48
-rw-r--r--contrib/libpcap/optimize.c248
-rw-r--r--contrib/libpcap/pcap-bpf.c274
-rw-r--r--contrib/libpcap/pcap-bpf.h92
-rw-r--r--contrib/libpcap/pcap-dag.c844
-rw-r--r--contrib/libpcap/pcap-dlpi.c334
-rw-r--r--contrib/libpcap/pcap-dos.c1473
-rw-r--r--contrib/libpcap/pcap-dos.h227
-rw-r--r--contrib/libpcap/pcap-enet.c2
-rw-r--r--contrib/libpcap/pcap-int.h36
-rw-r--r--contrib/libpcap/pcap-linux.c139
-rw-r--r--contrib/libpcap/pcap-namedb.h7
-rw-r--r--contrib/libpcap/pcap-nit.c57
-rw-r--r--contrib/libpcap/pcap-null.c2
-rw-r--r--contrib/libpcap/pcap-pf.c115
-rw-r--r--contrib/libpcap/pcap-snit.c75
-rw-r--r--contrib/libpcap/pcap-snoop.c80
-rw-r--r--contrib/libpcap/pcap-win32.c429
-rw-r--r--contrib/libpcap/pcap.372
-rw-r--r--contrib/libpcap/pcap.c166
-rw-r--r--contrib/libpcap/pcap.h75
-rw-r--r--contrib/libpcap/pcap1.h302
-rw-r--r--contrib/libpcap/pf.h6
-rw-r--r--contrib/libpcap/ppp.h8
-rw-r--r--contrib/libpcap/savefile.c298
-rw-r--r--contrib/libpcap/scanner.l3
53 files changed, 7271 insertions, 1344 deletions
diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES
index 01b1581e8059..015836d7fb59 100644
--- a/contrib/libpcap/CHANGES
+++ b/contrib/libpcap/CHANGES
@@ -1,4 +1,4 @@
-@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.56.4.3 2004/03/30 14:29:16 mcr Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59 2004/03/30 14:42:50 mcr Exp $ (LBL)
Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release
diff --git a/contrib/libpcap/CREDITS b/contrib/libpcap/CREDITS
index fadf77f545d0..870ec5050dcb 100644
--- a/contrib/libpcap/CREDITS
+++ b/contrib/libpcap/CREDITS
@@ -21,12 +21,16 @@ Additional people who have contributed patches:
Brian Ginsbach <ginsbach@cray.com>
Charles M. Hannum <mycroft@netbsd.org>
Chris G. Demetriou <cgd@netbsd.org>
+ Chris Lightfoot <cwrl@users.sourceforge.net>
Chris Pepper <pepper@mail.reppep.com>
Darren Reed <darrenr@reed.wattle.id.au>
David Kaelbling <drk@sgi.com>
David Young <dyoung@ojctech.com>
+ Dean Gaudet <dean@arctic.org>
Don Ebright <Don.Ebright@compuware.com>
+ Dug Song <dugsong@monkey.org>
Eric Anderson <anderse@hpl.hp.com>
+ Erik de Castro Lopo <erik.de.castro.lopo@sensorynetworks.com>
Franz Schaefer <schaefer@mond.at>
Gianluca Varenni <varenni@netgroup-serv.polito.it>
Gisle Vanem <giva@bgnett.no>
@@ -54,9 +58,12 @@ Additional people who have contributed patches:
Love Hörnquist-Åstrand <lha@stacken.kth.se>
Maciej W. Rozycki <macro@ds2.pg.gda.pl>
Marcus Felipe Pereira <marcus@task.com.br>
+ Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>
Martin Husemann <martin@netbsd.org>
+ Matthew Luckie <mjl@luckie.org.nz>
Mike Wiacek <mike@iroot.net>
Monroe Williams <monroe@pobox.com>
+ Nicolas Dade <ndade@nsd.dyndns.org>
Octavian Cerna <tavy@ylabs.com>
Olaf Kirch <okir@caldera.de>
Onno van der Linden <onno@simplex.nl>
diff --git a/contrib/libpcap/FILES b/contrib/libpcap/FILES
index 4f8193c604bc..95b75cf5694e 100644
--- a/contrib/libpcap/FILES
+++ b/contrib/libpcap/FILES
@@ -1,4 +1,6 @@
CHANGES
+ChmodBPF/ChmodBPF
+ChmodBPF/StartupParameters.plist
CREDITS
FILES
INSTALL.txt
@@ -9,6 +11,7 @@ README.aix
README.dag
README.hpux
README.linux
+README.macosx
README.tru64
README.Win32
SUNOS4/nit_if.o.sparc
@@ -48,16 +51,33 @@ lbl/os-solaris2.h
lbl/os-sunos4.h
lbl/os-ultrix4.h
llc.h
+missing/snprintf.c
mkdep
+msdos/bin2c.c
+msdos/common.dj
+msdos/makefile
+msdos/makefile.dj
+msdos/makefile.wc
+msdos/ndis2.c
+msdos/ndis2.h
+msdos/ndis_0.asm
+msdos/pkt_rx0.asm
+msdos/pkt_rx1.s
+msdos/pktdrvr.c
+msdos/pktdrvr.h
+msdos/readme.dos
nametoaddr.c
nlpid.h
optimize.c
packaging/pcap.spec
+packaging/pcap.spec.in
pcap-bpf.c
pcap-bpf.h
pcap-dag.c
pcap-dag.h
pcap-dlpi.c
+pcap-dos.c
+pcap-dos.h
pcap-enet.c
pcap-int.h
pcap-linux.c
@@ -80,7 +100,6 @@ rawss7.h
savefile.c
scanner.l
sll.h
-snprintf.c
sunatmpos.h
Win32/Include/Gnuc.h
Win32/Include/addrinfo.h
diff --git a/contrib/libpcap/INSTALL.txt b/contrib/libpcap/INSTALL.txt
index 5a1310b2bb43..2f9075d89215 100644
--- a/contrib/libpcap/INSTALL.txt
+++ b/contrib/libpcap/INSTALL.txt
@@ -1,4 +1,4 @@
-@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.7.2.2 2003/12/15 02:05:00 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12 2004/12/18 08:52:08 guy Exp $ (LBL)
To build libpcap, run "./configure" (a shell script). The configure
script will determine your system attributes and generate an
@@ -295,6 +295,8 @@ timestamp resolution if it finds it's running on a SS-1).
FILES
-----
CHANGES - description of differences between releases
+ChmodBPF/* - Mac OS X startup item to set ownership and permissions
+ on /dev/bpf*
CREDITS - people that have helped libpcap along
FILES - list of files exported as part of the distribution
INSTALL.txt - this file
@@ -305,6 +307,7 @@ README.aix - notes on using libpcap on AIX
README.dag - notes on using libpcap to capture on Endace DAG devices
README.hpux - notes on using libpcap on HP-UX
README.linux - notes on using libpcap on Linux
+README.macosx - notes on using libpcap on Mac OS X
README.tru64 - notes on using libpcap on Digital/Tru64 UNIX
README.Win32 - notes on using libpcap on Win32 systems (with WinPcap)
SUNOS4 - pre-SunOS 4.1 replacement kernel nit modules
@@ -336,7 +339,9 @@ inet.c - network routines
install-sh - BSD style install script
lbl/os-*.h - OS-dependent defines and prototypes
llc.h - 802.2 LLC SAP definitions
+missing/* - replacements for missing library functions
mkdep - construct Makefile dependency list
+msdos/* - drivers for MS-DOS capture support
nametoaddr.c - hostname to address routines
nlpid.h - OSI network layer protocol identifier definitions
net - symlink to bpf/net
@@ -347,6 +352,8 @@ pcap-bpf.h - BPF definitions
pcap-dag.c - Endace DAG device capture support
pcap-dag.h - Endace DAG device capture support
pcap-dlpi.c - Data Link Provider Interface support
+pcap-dos.c - MS-DOS capture support
+pcap-dos.h - headers for MS-DOS capture support
pcap-enet.c - enet support
pcap-int.h - internal libpcap definitions
pcap-linux.c - Linux packet socket support
@@ -369,6 +376,5 @@ rawss7.h - information on DLT_ types for SS7
savefile.c - offline support
scanner.l - filter string scanner
sll.h - definitions for Linux cooked mode fake link-layer header
-snprintf.c - snprintf and vsnprintf for platforms that lack them
sunatmpos.h - definitions for SunATM capturing
Win32 - headers and routines for building on Win32 systems
diff --git a/contrib/libpcap/Makefile.in b/contrib/libpcap/Makefile.in
index 2671eb88e2c8..0ed0cb045f8a 100644
--- a/contrib/libpcap/Makefile.in
+++ b/contrib/libpcap/Makefile.in
@@ -17,7 +17,7 @@
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
-# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.96.2.1 2003/12/15 01:42:23 guy Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.99 2003/12/15 01:35:03 guy Exp $ (LBL)
#
# Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -46,6 +46,7 @@ CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
DEFS = @DEFS@ @V_DEFS@
LIBS = @V_LIBS@
+DYEXT = @DYEXT@
# Standard CFLAGS
CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
@@ -103,6 +104,24 @@ libpcap.a: $(OBJ)
ar rc $@ $(OBJ) $(LIBS)
$(RANLIB) $@
+shared: libpcap.$(DYEXT)
+
+#
+# XXX - this works with GNU ld, but won't necessarily work with native
+# ld on, for example, various SVR4-flavored platforms, or Digital UNIX.
+#
+libpcap.so: $(OBJ)
+ @rm -f $@
+ ld -shared -o $@.`cat VERSION` $(OBJ)
+
+# the following rule succeeds, but the result is untested.
+libpcap.dylib: $(OBJ)
+ rm -f libpcap*.dylib
+ $(CC) -dynamiclib -undefined error -o libpcap.`cat VERSION`.dylib $(OBJ) \
+ -install_name $(libdir)/libpcap.0.dylib -compatibility_version `cat VERSION` \
+ -current_version `cat VERSION`
+
+
scanner.c: $(srcdir)/scanner.l
@rm -f $@
$(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@
@@ -151,7 +170,7 @@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
bpf_filter.o: bpf_filter.c
$(CC) $(CFLAGS) -c bpf_filter.c
-install:
+install: libpcap.a
[ -d $(DESTDIR)$(libdir) ] || \
(mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
$(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
@@ -168,6 +187,13 @@ install:
$(INSTALL_DATA) $(srcdir)/pcap.3 \
$(DESTDIR)$(mandir)/man3/pcap.3
+install-shared: install-shared-$(DYEXT)
+install-shared-so: libpcap.so
+ $(INSTALL_PROGRAM) libpcap.so.`cat VERSION` $(DESTDIR)$(libdir)/libpcap.so.`cat VERSION`
+install-shared-dylib: libpcap.dylib
+ $(INSTALL_PROGRAM) libpcap.`cat VERSION`.dylib $(DESTDIR)$(libdir)/libpcap.`cat VERSION`.dylib
+ VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.0.dylib; ln -sf libpcap.0.dylib libpcap.dylib
+
uninstall:
rm -f $(DESTDIR)$(libdir)/libpcap.a
rm -f $(DESTDIR)$(includedir)/pcap.h
@@ -176,16 +202,21 @@ uninstall:
rm -f $(DESTDIR)$(mandir)/man3/pcap.3
clean:
- rm -f $(CLEANFILES)
+ rm -f $(CLEANFILES) libpcap*.dylib libpcap.so*
-distclean:
- rm -f $(CLEANFILES) Makefile config.cache config.log config.status \
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
config.h gnuc.h os-proto.h bpf_filter.c stamp-h stamp-h.in
+ rm -rf autom4te.cache
tags: $(TAGFILES)
ctags -wtd $(TAGFILES)
-tar:
+packaging/pcap.spec: packaging/pcap.spec.in VERSION
+ RPMVERSION=`cat VERSION | sed s/-.*//g`; \
+ sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $< > $@
+
+tar: Makefile packaging/pcap.spec
@cwd=`pwd` ; dir=`basename $$cwd` ; name=libpcap-`cat VERSION` ; \
list="" ; tar="tar chf" ; \
for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \
@@ -193,11 +224,16 @@ tar:
"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 ; \
+ "(cd .. ; $$tar - [lots of files]) | gzip -c > /tmp/$$name.tar.gz" ; \
+ (cd .. ; $$tar - $$list) | gzip -c > /tmp/$$name.tar.gz ; \
echo \
"rm -f ../$$name" ; \
rm -f ../$$name
depend: $(GENSRC) $(GENHDR) bpf_filter.c
./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
+
+Makefile: Makefile.in config.status
+ ./config.status
+ @echo your Makefile was out of date, now run $(MAKE) again
+ exit 1
diff --git a/contrib/libpcap/README b/contrib/libpcap/README
index 35ab2f8aca35..90571a150525 100644
--- a/contrib/libpcap/README
+++ b/contrib/libpcap/README
@@ -1,6 +1,6 @@
-@(#) $Header: /tcpdump/master/libpcap/README,v 1.27.2.1 2003/11/15 23:29:19 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/README,v 1.30 2004/10/12 02:02:28 guy Exp $ (LBL)
-LIBPCAP 0.8
+LIBPCAP 0.9
Now maintained by "The Tcpdump Group"
See www.tcpdump.org
@@ -11,8 +11,8 @@ Anonymous CVS is available via:
(password "anoncvs")
cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout libpcap
-Version 0.8 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_8rel1":
- cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_8rel1 libpcap
+Version 0.9 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_9rel1":
+ cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_9rel1 libpcap
Please send patches against the master copy to patches@tcpdump.org.
diff --git a/contrib/libpcap/README.hpux b/contrib/libpcap/README.hpux
index d6d27a207658..88c27f8a2581 100644
--- a/contrib/libpcap/README.hpux
+++ b/contrib/libpcap/README.hpux
@@ -1,3 +1,7 @@
+For HP-UX 11i (11.11) and later, there are no known issues with
+promiscuous mode under HP-UX. If you are using a earlier version of
+HP-UX and cannot upgrade, please continue reading.
+
HP-UX patches to fix packet capture problems
Note that packet-capture programs such as tcpdump may, on HP-UX, not be
@@ -182,6 +186,10 @@ An additional note, from Jost Martin, for HP-UX 10.20:
/sbin/rc2.d/S350hack_ip_stack pointing to this script.
Now all this is done on every reboot.
+According to Rick Jones, the global promiscuous switch also has to be
+turned on for HP-UX 11.00, but not for 11i - and, in fact, the switch
+doesn't even exist on 11i.
+
Here's the "hack_ip_stack" script:
-----------------------------------Cut Here-------------------------------------
diff --git a/contrib/libpcap/README.macosx b/contrib/libpcap/README.macosx
new file mode 100644
index 000000000000..25794d88594b
--- /dev/null
+++ b/contrib/libpcap/README.macosx
@@ -0,0 +1,43 @@
+As with other systems using BPF, Mac OS X allows users with read access
+to the BPF devices to capture packets with libpcap and allows users with
+write access to the BPF devices to send packets with libpcap.
+
+On some systems that use BPF, the BPF devices live on the root file
+system, and the permissions and/or ownership on those devices can be
+changed to give users other than root permission to read or write those
+devices.
+
+On newer versions of FreeBSD, the BPF devices live on devfs, and devfs
+can be configured to set the permissions and/or ownership of those
+devices to give users other than root permission to read or write those
+devices.
+
+On Mac OS X, the BPF devices live on devfs, but the OS X version of
+devfs is based on an older (non-default) FreeBSD devfs, and that version
+of devfs cannot be configured to set the permissions and/or ownership of
+those devices.
+
+Therefore, we supply a "startup item" for OS X that will change the
+ownership of the BPF devices so that the "admin" group owns them, and
+will change the permission of the BPF devices to rw-rw----, so that all
+users in the "admin" group - i.e., all users with "Allow user to
+administer this computer" turned on - have both read and write access to
+them.
+
+The startup item is in the ChmodBPF directory in the source tree. A
+/Library/StartupItems directory should be created if it doesn't already
+exist, and the ChmodBPF directory should be copied to the
+/Library/StartupItems directory (copy the entire directory, so that
+there's a /Library/StartupItems/ChmodBPF directory, containing all the
+files in the source tree's ChmodBPF directory; don't copy the individual
+items in that directory to /Library/StartupItems).
+
+If you want to give a particular user permission to access the BPF
+devices, rather than giving all administrative users permission to
+access them, you can have the ChmodBPF/ChmodBPF script change the
+ownership of /dev/bpf* without changing the permissions. If you want to
+give a particular user permission to read and write the BPF devices and
+give the administrative users permission to read but not write the BPF
+devices, you can have the script change the owner to that user, the
+group to "admin", and the permissions to rw-r-----. Other possibilities
+are left as an exercise for the reader.
diff --git a/contrib/libpcap/VERSION b/contrib/libpcap/VERSION
index ee94dd834b53..e80fc25b571f 100644
--- a/contrib/libpcap/VERSION
+++ b/contrib/libpcap/VERSION
@@ -1 +1 @@
-0.8.3
+0.9-PRE-CVS
diff --git a/contrib/libpcap/aclocal.m4 b/contrib/libpcap/aclocal.m4
index f366afd11081..3c26c71dcfdf 100644
--- a/contrib/libpcap/aclocal.m4
+++ b/contrib/libpcap/aclocal.m4
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.81.2.2 2003/11/16 09:45:51 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.85 2005/03/27 03:27:09 guy Exp $ (LBL)
dnl
dnl Copyright (c) 1995, 1996, 1997, 1998
dnl The Regents of the University of California. All rights reserved.
@@ -166,8 +166,13 @@ AC_DEFUN(AC_LBL_C_INIT,
# at least some versions of HP's C compiler can inline that, but can't
# inline a function that returns a struct pointer.
#
+# Make sure we use the V_CCOPT flags, because some of those might
+# disable inlining.
+#
AC_DEFUN(AC_LBL_C_INLINE,
[AC_MSG_CHECKING(for inline)
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$V_CCOPT"
AC_CACHE_VAL(ac_cv_lbl_inline, [
ac_cv_lbl_inline=""
ac_lbl_cc_inline=no
@@ -195,6 +200,7 @@ AC_DEFUN(AC_LBL_C_INLINE,
if test "$ac_lbl_cc_inline" = yes ; then
ac_cv_lbl_inline=$ac_lbl_inline
fi])
+ CFLAGS="$save_CFLAGS"
if test ! -z "$ac_cv_lbl_inline" ; then
AC_MSG_RESULT($ac_cv_lbl_inline)
else
@@ -822,23 +828,20 @@ 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)))
+ # Some OSes (eg. Solaris) place it in libnsl
+ # Some strange OSes (SINIX) have it in libsocket:
+ AC_SEARCH_LIBS(gethostbyname, nsl socket resolv)
+ # Unfortunately libsocket sometimes depends on libnsl and
+ # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
+ if test "$ac_cv_search_gethostbyname" = "no"
+ then
+ AC_CHECK_LIB(socket, gethostbyname,
+ LIBS="-lsocket -lnsl $LIBS", , -lnsl)
+ fi
+ AC_SEARCH_LIBS(socket, socket, ,
+ AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))
# DLPI needs putmsg under HPUX so test for -lstr while we're at it
- AC_CHECK_LIB(str, putmsg)
+ AC_SEARCH_LIBS(putmsg, str)
])
dnl
diff --git a/contrib/libpcap/bpf/net/bpf_filter.c b/contrib/libpcap/bpf/net/bpf_filter.c
index a2cfbc19df03..40df32a8b39f 100644
--- a/contrib/libpcap/bpf/net/bpf_filter.c
+++ b/contrib/libpcap/bpf/net/bpf_filter.c
@@ -40,7 +40,7 @@
#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.43.2.1 2003/11/15 23:26:49 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.44 2003/11/15 23:24:07 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/bpf_dump.c b/contrib/libpcap/bpf_dump.c
index 99aa0a01573b..303602e20772 100644
--- a/contrib/libpcap/bpf_dump.c
+++ b/contrib/libpcap/bpf_dump.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.13.2.1 2003/11/15 23:26:37 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14 2003/11/15 23:23:57 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/bpf_image.c b/contrib/libpcap/bpf_image.c
index b1d76fe7d86b..7f31d9c973f7 100644
--- a/contrib/libpcap/bpf_image.c
+++ b/contrib/libpcap/bpf_image.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.25.2.1 2003/11/15 23:26:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.26 2003/11/15 23:23:57 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/config.h.in b/contrib/libpcap/config.h.in
index 1c41d048b1eb..2ecdbc16f474 100644
--- a/contrib/libpcap/config.h.in
+++ b/contrib/libpcap/config.h.in
@@ -1,8 +1,4 @@
-/* config.h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define to empty if the keyword does not work. */
-#undef const
-
+/* config.h.in. Generated from configure.in by autoheader. */
/* Long story short: aclocal.m4 depends on autoconf 2.13
* implementation details wrt "const"; newer versions
* have different implementation details so for now we
@@ -11,114 +7,171 @@
*/
#undef const
-/* Define if you have the ether_hostton function. */
-#undef HAVE_ETHER_HOSTTON
+/* Enable optimizer debugging */
+#undef BDEBUG
-/* Define if you have the snprintf function. */
-#undef HAVE_SNPRINTF
+/* define if you have the DAG API */
+#undef HAVE_DAG_API
-/* Define if you have the strerror function. */
-#undef HAVE_STRERROR
+/* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
+ don't. */
+#undef HAVE_DECL_ETHER_HOSTTON
-/* Define if you have the strlcpy function. */
-#undef HAVE_STRLCPY
+/* define if you have a /dev/dlpi */
+#undef HAVE_DEV_DLPI
-/* Define if you have the vsnprintf function. */
-#undef HAVE_VSNPRINTF
+/* Define to 1 if you have the `ether_hostton' function. */
+#undef HAVE_ETHER_HOSTTON
+
+/* on HP-UX 10.20 */
+#undef HAVE_HPUX10_20
+
+/* on HP-UX 9.x */
+#undef HAVE_HPUX9
+
+/* if ppa_info_t_dl_module_id exists */
+#undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
-/* Define if you have the <ifaddrs.h> header file. */
-#undef HAVE_IFADDRS_H
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
-/* Define if you have the <limits.h> header file. */
+/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
-/* Define if you have the <netinet/if_ether.h> header file. */
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netinet/ether.h> header file. */
+#undef HAVE_NETINET_ETHER_H
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
-/* Define if you have the <sys/bufmod.h> header file. */
+/* if there's an os_proto.h */
+#undef HAVE_OS_PROTO_H
+
+/* define if you have a /proc/net/dev */
+#undef HAVE_PROC_NET_DEV
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* if struct sockaddr has sa_len */
+#undef HAVE_SOCKADDR_SA_LEN
+
+/* if struct sockaddr_storage exists */
+#undef HAVE_SOCKADDR_STORAGE
+
+/* On solaris */
+#undef HAVE_SOLARIS
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
#undef HAVE_SYS_BUFMOD_H
-/* Define if you have the <sys/dlpi_ext.h> header file. */
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
#undef HAVE_SYS_DLPI_EXT_H
-/* Define if you have the <sys/ioccom.h> header file. */
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
#undef HAVE_SYS_IOCCOM_H
-/* Define if you have the <sys/sockio.h> header file. */
+/* Define to 1 if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
-/* needed on HP-UX */
-#undef _HPUX_SOURCE
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
-/* Define as token for inline if inlining supported */
-#undef inline
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* if if_packet.h has tpacket_stats defined */
+#undef HAVE_TPACKET_STATS
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* define if version.h is generated in the build procedure */
+#undef HAVE_VERSION_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
/* define if your compiler has __attribute__ */
#undef HAVE___ATTRIBUTE__
-/* if we have u_int8_t */
-#undef u_int8_t
+/* IPv6 */
+#undef INET6
-/* if we have u_int16_t */
-#undef u_int16_t
+/* if unaligned access fails */
+#undef LBL_ALIGN
-/* if we have u_int32_t */
-#undef u_int32_t
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
/* do not use protochain */
#undef NO_PROTOCHAIN
-/* IPv6 */
-#undef INET6
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
-/* Enable optimizer debugging */
-#undef BDEBUG
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
-/* Enable parser debugging */
-#undef YYDEBUG
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
-/* define if you have a /dev/dlpi */
-#undef HAVE_DEV_DLPI
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
/* /dev/dlpi directory */
#undef PCAP_DEV_PREFIX
-/* if if_packet.h has tpacket_stats defined */
-#undef HAVE_TPACKET_STATS
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
-/* define if you have a /proc/net/dev */
-#undef HAVE_PROC_NET_DEV
+/* Enable parser debugging */
+#undef YYDEBUG
-/* define if you have a DAG API */
-#undef HAVE_DAG_API
+/* needed on HP-UX */
+#undef _HPUX_SOURCE
/* define on AIX to get certain functions */
#undef _SUN
-/* on HP-UX 9.x */
-#undef HAVE_HPUX9
-
-/* on HP-UX 10.20 */
-#undef HAVE_HPUX10_20
+/* Define as token for inline if inlining supported */
+#undef inline
/* on sinix */
#undef sinix
-/* On solaris */
-#undef HAVE_SOLARIS
-
-/* if there's an os_proto.h */
-#undef HAVE_OS_PROTO_H
-
-/* if struct sockaddr has sa_len */
-#undef HAVE_SOCKADDR_SA_LEN
-
-/* if struct sockaddr_storage exists */
-#undef HAVE_SOCKADDR_STORAGE
-
-/* if ppa_info_t_dl_module_id exists */
-#undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
+/* if we have u_int16_t */
+#undef u_int16_t
-/* if unaligned access fails */
-#undef LBL_ALIGN
+/* if we have u_int32_t */
+#undef u_int32_t
+/* if we have u_int8_t */
+#undef u_int8_t
diff --git a/contrib/libpcap/configure b/contrib/libpcap/configure
index a0abec5e50b3..ba01786b9a71 100755
--- a/contrib/libpcap/configure
+++ b/contrib/libpcap/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 1.100.2.4 .
+# From configure.in Revision: 1.120 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.57.
#
@@ -309,7 +309,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os SHLICC2 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LIBOBJS V_LEX V_YACC RANLIB ac_ct_RANLIB V_CCOPT V_DEFS V_INCLS V_LIBS V_PCAP V_FINDALLDEVS V_RANLIB SSRC DYEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -855,7 +855,9 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-gcc don't use gcc
--with-pcap=TYPE use packet capture TYPE
- --with-dag=DIR include DAG support (located in directory DIR, if supplied). default=yes, on BSD and Linux, if present
+ --with-dag[=DIR] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)
+ --with-dag-includes=DIR Endace DAG include directory
+ --with-dag-libraries=DIR Endace DAG library directory
--without-flex don't use flex
--without-bison don't use bison
@@ -2534,6 +2536,8 @@ _ACEOF
echo "$as_me:$LINENO: checking for inline" >&5
echo $ECHO_N "checking for inline... $ECHO_C" >&6
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$V_CCOPT"
if test "${ac_cv_lbl_inline+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
@@ -2599,6 +2603,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
fi
fi
+ CFLAGS="$save_CFLAGS"
if test ! -z "$ac_cv_lbl_inline" ; then
echo "$as_me:$LINENO: result: $ac_cv_lbl_inline" >&5
echo "${ECHO_T}$ac_cv_lbl_inline" >&6
@@ -3331,8 +3336,7 @@ done
-
-for ac_header in sys/ioccom.h sys/sockio.h ifaddrs.h limits.h
+for ac_header in sys/ioccom.h sys/sockio.h limits.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -3526,6 +3530,75 @@ fi
done
+if test "$ac_cv_header_netinet_if_ether_h" != yes; then
+ #
+ # The simple test didn't work.
+ # Do we need to include <net/if.h> first?
+ # Unset ac_cv_header_netinet_if_ether_h so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ { echo "$as_me:$LINENO: Rechecking with some additional includes" >&5
+echo "$as_me: Rechecking with some additional includes" >&6;}
+ unset ac_cv_header_netinet_if_ether_h
+
+for ac_header in netinet/if_ether.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+fi
if test "$GCC" = yes ; then
echo "$as_me:$LINENO: checking for ANSI ioctl definitions" >&5
@@ -3596,8 +3669,7 @@ echo "$as_me: error: see the INSTALL for more info" >&2;}
-
-for ac_func in ether_hostton strerror strlcpy
+for ac_func in strerror strlcpy
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -3773,6 +3845,873 @@ if test $needsnprintf = yes; then
LIBOBJS="$LIBOBJS snprintf.$ac_objext"
fi
+#
+# Do this before checking for ether_hostton(), as it's a
+# "gethostbyname() -ish function".
+#
+
+ # Most operating systems have gethostbyname() in the default searched
+ # libraries (i.e. libc):
+ # Some OSes (eg. Solaris) place it in libnsl
+ # Some strange OSes (SINIX) have it in libsocket:
+ echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5
+echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6
+if test "${ac_cv_search_gethostbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_gethostbyname=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_gethostbyname="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_gethostbyname" = no; then
+ for ac_lib in nsl socket resolv; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_gethostbyname="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_search_gethostbyname" >&6
+if test "$ac_cv_search_gethostbyname" != no; then
+ test "$ac_cv_search_gethostbyname" = "none required" || LIBS="$ac_cv_search_gethostbyname $LIBS"
+
+fi
+
+ # Unfortunately libsocket sometimes depends on libnsl and
+ # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
+ if test "$ac_cv_search_gethostbyname" = "no"
+ then
+ echo "$as_me:$LINENO: checking for gethostbyname in -lsocket" >&5
+echo $ECHO_N "checking for gethostbyname in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_gethostbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_socket_gethostbyname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_gethostbyname=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_gethostbyname" >&6
+if test $ac_cv_lib_socket_gethostbyname = yes; then
+ LIBS="-lsocket -lnsl $LIBS"
+fi
+
+ fi
+ echo "$as_me:$LINENO: checking for library containing socket" >&5
+echo $ECHO_N "checking for library containing socket... $ECHO_C" >&6
+if test "${ac_cv_search_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_socket=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket ();
+int
+main ()
+{
+socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_socket="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_socket" = no; then
+ for ac_lib in socket; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket ();
+int
+main ()
+{
+socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_socket="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_socket" >&5
+echo "${ECHO_T}$ac_cv_search_socket" >&6
+if test "$ac_cv_search_socket" != no; then
+ test "$ac_cv_search_socket" = "none required" || LIBS="$ac_cv_search_socket $LIBS"
+
+else
+ echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket ();
+int
+main ()
+{
+socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_socket_socket=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+ LIBS="-lsocket -lnsl $LIBS"
+fi
+
+fi
+
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ echo "$as_me:$LINENO: checking for library containing putmsg" >&5
+echo $ECHO_N "checking for library containing putmsg... $ECHO_C" >&6
+if test "${ac_cv_search_putmsg+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_putmsg=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char putmsg ();
+int
+main ()
+{
+putmsg ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_putmsg="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_putmsg" = no; then
+ for ac_lib in str; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char putmsg ();
+int
+main ()
+{
+putmsg ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_putmsg="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_putmsg" >&5
+echo "${ECHO_T}$ac_cv_search_putmsg" >&6
+if test "$ac_cv_search_putmsg" != no; then
+ test "$ac_cv_search_putmsg" = "none required" || LIBS="$ac_cv_search_putmsg $LIBS"
+
+fi
+
+
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it, but not declare it in any header file.
+# Some might have it, but declare it in <netinet/if_ether.h>.
+# Some might have it, but declare it in <netinet/ether.h>
+# (And some might have it but document it as something declared in
+# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
+#
+# Before you is a C compiler.
+#
+
+for ac_func in ether_hostton
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* 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 ();
+/* 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
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ether_hostton" = yes; then
+ #
+ # OK, we have ether_hostton(). Do we have <netinet/if_ether.h>?
+ #
+ if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+ #
+ # Yes. Does it declare ether_hostton()?
+ #
+ echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5
+echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_ether_hostton+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+
+int
+main ()
+{
+#ifndef ether_hostton
+ char *p = (char *) ether_hostton;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_have_decl_ether_hostton=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_have_decl_ether_hostton=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5
+echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6
+if test $ac_cv_have_decl_ether_hostton = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ETHER_HOSTTON 1
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ETHER_HOSTTON 0
+_ACEOF
+
+
+fi
+
+
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/ether.h>, as on Linux?
+ #
+
+for ac_header in netinet/ether.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ if test "$ac_cv_header_netinet_ether_h" = yes; then
+ #
+ # We have it - does it declare ether_hostton()?
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ echo "$as_me:$LINENO: checking whether ether_hostton is declared" >&5
+echo $ECHO_N "checking whether ether_hostton is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_ether_hostton+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netinet/ether.h>
+
+
+int
+main ()
+{
+#ifndef ether_hostton
+ char *p = (char *) ether_hostton;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_have_decl_ether_hostton=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_have_decl_ether_hostton=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_decl_ether_hostton" >&5
+echo "${ECHO_T}$ac_cv_have_decl_ether_hostton" >&6
+if test $ac_cv_have_decl_ether_hostton = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ETHER_HOSTTON 1
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ETHER_HOSTTON 0
+_ACEOF
+
+
+fi
+
+
+ fi
+ fi
+fi
+
echo "$as_me:$LINENO: checking if --disable-protochain option is specified" >&5
echo $ECHO_N "checking if --disable-protochain option is specified... $ECHO_C" >&6
# Check whether --enable-protochain or --disable-protochain was given.
@@ -3846,7 +4785,15 @@ fi
echo "$as_me:$LINENO: result: $V_PCAP" >&5
echo "${ECHO_T}$V_PCAP" >&6
-echo "$as_me:$LINENO: checking for getifaddrs" >&5
+if test "$V_PCAP" = null
+then
+ #
+ # We can't capture, so we can't open any capture
+ # devices, so we won't return any interfaces.
+ #
+ V_FINDALLDEVS=null
+else
+ echo "$as_me:$LINENO: checking for getifaddrs" >&5
echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6
if test "${ac_cv_func_getifaddrs+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3920,30 +4867,187 @@ echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5
echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6
if test $ac_cv_func_getifaddrs = yes; then
- #
- # We have "getifaddrs()", so we use that to get the list
- #
- V_FINDALLDEVS=getad
+ #
+ # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+ # as well, just in case some platform is really weird.
+ #
+ if test "${ac_cv_header_ifaddrs_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for ifaddrs.h" >&5
+echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6
+if test "${ac_cv_header_ifaddrs_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5
+echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking ifaddrs.h usability" >&5
+echo $ECHO_N "checking ifaddrs.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <ifaddrs.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking ifaddrs.h presence" >&5
+echo $ECHO_N "checking ifaddrs.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ifaddrs.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: ifaddrs.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: ifaddrs.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: ifaddrs.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: ifaddrs.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: ifaddrs.h: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for ifaddrs.h" >&5
+echo $ECHO_N "checking for ifaddrs.h... $ECHO_C" >&6
+if test "${ac_cv_header_ifaddrs_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_ifaddrs_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_ifaddrs_h" >&5
+echo "${ECHO_T}$ac_cv_header_ifaddrs_h" >&6
+
+fi
+if test $ac_cv_header_ifaddrs_h = yes; then
+
+ #
+ # We have the header, so we use "getifaddrs()" to
+ # get the list of interfaces.
+ #
+ V_FINDALLDEVS=getad
else
- #
- # Well, we don't have "getifaddrs()", so we have to use some
- # other mechanism; determine what that mechanism is.
- #
- # The first thing we use is the type of capture mechanism,
- # which is somewhat of a proxy for the OS we're using.
- #
- case "$V_PCAP" in
+ #
+ # We don't have the header - give up.
+ # XXX - we could also fall back on some other
+ # mechanism, but, for now, this'll catch this
+ # problem so that we can at least try to figure
+ # out something to do on systems with "getifaddrs()"
+ # but without "ifaddrs.h", if there is something
+ # we can do on those systems.
+ #
+ { { echo "$as_me:$LINENO: error: Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." >&5
+echo "$as_me: error: Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+
+
+
+else
- dlpi)
#
- # This might be Solaris 8 or later, with SIOCGLIFCONF,
- # or it might be some other OS, with just SIOCGIFCONF.
+ # Well, we don't have "getifaddrs()", so we have to use
+ # some other mechanism; determine what that mechanism is.
+ #
+ # The first thing we use is the type of capture mechanism,
+ # which is somewhat of a proxy for the OS we're using.
#
- echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
+ case "$V_PCAP" in
+
+ dlpi)
+ #
+ # This might be Solaris 8 or later, with
+ # SIOCGLIFCONF, or it might be some other OS
+ # or some older version of Solaris, with
+ # just SIOCGIFCONF.
+ #
+ echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6
- if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
+ if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
@@ -3954,10 +5058,10 @@ cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/param.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>
+ #include <sys/file.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
int
main ()
{
@@ -3988,35 +5092,28 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
- echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
+ echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6
- if test $ac_cv_lbl_have_siocglifconf = yes ; then
- V_FINDALLDEVS=glifc
- else
+ if test $ac_cv_lbl_have_siocglifconf = yes ; then
+ V_FINDALLDEVS=glifc
+ else
+ V_FINDALLDEVS=gifc
+ fi
+ ;;
+
+ *)
+ #
+ # Assume we just have SIOCGIFCONF.
+ # (XXX - on at least later Linux kernels, there's
+ # another mechanism, and we should be using that
+ # instead.)
+ #
V_FINDALLDEVS=gifc
- fi
- ;;
-
- null)
- #
- # We can't capture, so we can't open any capture
- # devices, so we won't return any interfaces.
- #
- V_FINDALLDEVS=null
- ;;
-
- *)
- #
- # Assume we just have SIOCGIFCONF.
- # (XXX - on at least later Linux kernels, there's
- # another mechanism, and we should be using that
- # instead.)
- #
- V_FINDALLDEVS=gifc
- ;;
- esac
+ ;;
+ esac
fi
+fi
echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5
echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6
@@ -4362,6 +5459,7 @@ fi
echo "$as_me:$LINENO: result: $ac_cv_lbl_proc_net_dev" >&5
echo "${ECHO_T}$ac_cv_lbl_proc_net_dev" >&6
+# Check for Endace DAG card support.
# Check whether --with-dag or --without-dag was given.
if test "${with_dag+set}" = set; then
@@ -4369,12 +5467,14 @@ if test "${with_dag+set}" = set; then
if test "$withval" = no
then
+ # User doesn't want DAG support.
want_dag=no
elif test "$withval" = yes
then
+ # User wants DAG support but hasn't specified a directory.
want_dag=yes
- dag_root=
else
+ # User wants DAG support and has specified a directory, so use the provided value.
want_dag=yes
dag_root=$withval
fi
@@ -4385,10 +5485,31 @@ else
# Use DAG API if present, otherwise don't
#
want_dag=ifpresent
- dag_root=/root/dag
fi;
-ac_cv_lbl_dag_api=no
+
+
+# Check whether --with-dag-includes or --without-dag-includes was given.
+if test "${with_dag_includes+set}" = set; then
+ withval="$with_dag_includes"
+
+ # User wants DAG support and has specified a header directory, so use the provided value.
+ want_dag=yes
+ dag_include_dir=$withval
+
+fi;
+
+
+# Check whether --with-dag-libraries or --without-dag-libraries was given.
+if test "${with_dag_libraries+set}" = set; then
+ withval="$with_dag_libraries"
+
+ # User wants DAG support and has specified a library directory, so use the provided value.
+ want_dag=yes
+ dag_lib_dir=$withval
+
+fi;
+
case "$V_PCAP" in
linux|bpf|dag)
#
@@ -4404,8 +5525,8 @@ linux|bpf|dag)
# If they expressed no preference, don't include it.
#
if test $want_dag = yes; then
- { { echo "$as_me:$LINENO: error: DAG support only available with 'linux' 'bpf' and 'dag' packet capture types" >&5
-echo "$as_me: error: DAG support only available with 'linux' 'bpf' and 'dag' packet capture types" >&2;}
+ { { echo "$as_me:$LINENO: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&5
+echo "$as_me: error: DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" >&2;}
{ (exit 1); exit 1; }; }
elif test $want_dag = yes; then
want_dag=no
@@ -4413,63 +5534,240 @@ echo "$as_me: error: DAG support only available with 'linux' 'bpf' and 'dag' pac
;;
esac
-if test "$with_dag" != no; then
- echo "$as_me:$LINENO: checking whether we have DAG API" >&5
-echo $ECHO_N "checking whether we have DAG API... $ECHO_C" >&6
+ac_cv_lbl_dag_api=no
+if test "$want_dag" != no; then
+
+ echo "$as_me:$LINENO: checking whether we have DAG API headers" >&5
+echo $ECHO_N "checking whether we have DAG API headers... $ECHO_C" >&6
+ # If necessary, set default paths for DAG API headers and libraries.
if test -z "$dag_root"; then
- dag_root=$srcdir/../dag
+ dag_root=/usr/local
fi
- if test -r "$dag_root/tools" -a -r "$dag_root/include"; then
- dag_tools_dir="$dag_root/tools"
+ if test -z "$dag_include_dir"; then
dag_include_dir="$dag_root/include"
- else
- dag_tools_dir="$dag_root"
- dag_include_dir="$dag_root"
fi
- ac_cv_lbl_dag_api=no
- if test -r "$dag_include_dir/dagapi.h" -a -r "$dag_tools_dir/dagapi.o" -a -r "$dag_tools_dir/dagopts.o"; then
- V_INCLS="$V_INCLS -I $dag_include_dir"
- V_LIBS="$V_LIBS $dag_tools_dir/dagapi.o $dag_tools_dir/dagopts.o"
- if test "$V_PCAP" != dag ; then
- SSRC="pcap-dag.c"
+ if test -z "$dag_lib_dir"; then
+ dag_lib_dir="$dag_root/lib"
+ fi
+
+ if test -z "$dag_tools_dir"; then
+ dag_tools_dir="$dag_root/tools"
fi
+
+ if test -r $dag_include_dir/dagapi.h; then
ac_cv_lbl_dag_api=yes
fi
- if test -r "$dag_root/lib/dagreg.c"; then # DAG 2.5.x
- if test -r "$dag_tools_dir/dagreg.o"; then
- V_LIBS="$V_LIBS $dag_tools_dir/dagreg.o"
- else
+ echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5
+echo "${ECHO_T}$ac_cv_lbl_dag_api ($dag_include_dir)" >&6
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ echo "$as_me:$LINENO: checking dagapi.o" >&5
+echo $ECHO_N "checking dagapi.o... $ECHO_C" >&6
+ dagapi_obj=no
+ if test -r $dag_tools_dir/dagapi.o; then
+
+ # 2.4.x.
+ dagapi_obj=$dag_tools_dir/dagapi.o
+
+ elif test -r $dag_lib_dir/dagapi.o; then
+
+ # 2.5.x.
+ dagapi_obj=$dag_lib_dir/dagapi.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # 2.5.x.
+ ar x $dag_lib_dir/libdag.a dagapi.o
+ if test -r ./dagapi.o; then
+ dagapi_obj=./dagapi.o
+ fi
+ fi
+
+ if test $dagapi_obj = no; then
+ echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5
+echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6
ac_cv_lbl_dag_api=no
+ else
+ echo "$as_me:$LINENO: result: yes ($dagapi_obj)" >&5
+echo "${ECHO_T}yes ($dagapi_obj)" >&6
fi
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ echo "$as_me:$LINENO: checking dagopts.o" >&5
+echo $ECHO_N "checking dagopts.o... $ECHO_C" >&6
+ dagopts_obj=no
+ if test -r $dag_tools_dir/dagopts.o; then
+
+ # 2.4.x.
+ dagopts_obj=$dag_tools_dir/dagopts.o
+
+ elif test -r $dag_lib_dir/dagopts.o; then
+
+ # 2.5.x.
+ dagopts_obj=$dag_lib_dir/dagopts.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # 2.5.x.
+ ar x $dag_lib_dir/libdag.a dagopts.o
+ if test -r ./dagopts.o; then
+ dagopts_obj=./dagopts.o
fi
- dag_version=
- if test $ac_cv_lbl_dag_api = yes -a -r "$dag_root/VERSION"; then
- dag_version=" (`cat $dag_root/VERSION`)"
fi
- echo "$as_me:$LINENO: result: $ac_cv_lbl_dag_api$dag_version" >&5
-echo "${ECHO_T}$ac_cv_lbl_dag_api$dag_version" >&6
- if test $ac_cv_lbl_dag_api = no; then
- if test "$want_dag" = yes; then
- { { echo "$as_me:$LINENO: error: DAG API not found under directory $dag_root; use --without-dag" >&5
-echo "$as_me: error: DAG API not found under directory $dag_root; use --without-dag" >&2;}
- { (exit 1); exit 1; }; }
+
+ if test $dagopts_obj = no; then
+ echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&5
+echo "${ECHO_T}no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)" >&6
+ ac_cv_lbl_dag_api=no
+ else
+ echo "$as_me:$LINENO: result: yes ($dagopts_obj)" >&5
+echo "${ECHO_T}yes ($dagopts_obj)" >&6
+ fi
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ # Under 2.5.x only we need to add dagreg.o.
+ if test -r $dag_include_dir/dagreg.h; then
+
+ echo "$as_me:$LINENO: checking dagreg.o" >&5
+echo $ECHO_N "checking dagreg.o... $ECHO_C" >&6
+ dagreg_obj=no
+ if test -r $dag_lib_dir/dagreg.o; then
+
+ # Object file is ready and waiting.
+ dagreg_obj=$dag_lib_dir/dagreg.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # Extract from libdag.a.
+ ar x $dag_lib_dir/libdag.a dagreg.o
+ if test -r ./dagreg.o; then
+ dagreg_obj=./dagreg.o
fi
+ fi
+
+ if test $dagreg_obj = no; then
+ echo "$as_me:$LINENO: result: no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&5
+echo "${ECHO_T}no (checked $dag_lib_dir $dag_lib_dir/libdag.a)" >&6
+ ac_cv_lbl_dag_api=no
else
+ echo "$as_me:$LINENO: result: yes ($dagreg_obj)" >&5
+echo "${ECHO_T}yes ($dagreg_obj)" >&6
+ fi
+ fi
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ V_INCLS="$V_INCLS -I$dag_include_dir"
+ V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj"
+ if test $V_PCAP != dag ; then
+ SSRC="pcap-dag.c"
+ fi
+
+ # See if we can find a general version string.
+ # Don't need to save and restore LIBS to prevent -ldag being included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ echo "$as_me:$LINENO: checking for dag_attach_stream in -ldag" >&5
+echo $ECHO_N "checking for dag_attach_stream in -ldag... $ECHO_C" >&6
+if test "${ac_cv_lib_dag_dag_attach_stream+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dag_attach_stream ();
+int
+main ()
+{
+dag_attach_stream ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dag_dag_attach_stream=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dag_dag_attach_stream=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_attach_stream" >&5
+echo "${ECHO_T}$ac_cv_lib_dag_dag_attach_stream" >&6
+if test $ac_cv_lib_dag_dag_attach_stream = yes; then
+ dag_version="2.5.x"
+else
+ dag_version="2.4.x"
+fi
+
+ LDFLAGS=$saved_ldflags
+
+ # See if we can find a specific version string.
+ echo "$as_me:$LINENO: checking the DAG API version" >&5
+echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6
+ if test -r "$dag_root/VERSION"; then
+ dag_version="`cat $dag_root/VERSION`"
+ fi
+ echo "$as_me:$LINENO: result: $dag_version" >&5
+echo "${ECHO_T}$dag_version" >&6
cat >>confdefs.h <<\_ACEOF
#define HAVE_DAG_API 1
_ACEOF
- fi
fi
-if test "$V_PCAP" = dag -a "$ac_cv_lbl_dag_api" = no; then
- { { echo "$as_me:$LINENO: error: Specifying the capture type as 'dag' requires the DAG API to be present; use --with-dag=DIR" >&5
-echo "$as_me: error: Specifying the capture type as 'dag' requires the DAG API to be present; use --with-dag=DIR" >&2;}
+if test $ac_cv_lbl_dag_api = no; then
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ { { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5
+echo "$as_me: error: DAG API requested, but not found at $dag_root: use --without-dag" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but the DAG API wasn't found.
+ { { echo "$as_me:$LINENO: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&5
+echo "$as_me: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&2;}
{ (exit 1); exit 1; }; }
+ fi
fi
@@ -4640,6 +5938,7 @@ echo "$as_me: error: Your operating system's lex is insufficient to compile
fi
fi
+DYEXT="so"
case "$host_os" in
aix*)
@@ -4734,6 +6033,11 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
+ ;;
esac
if test -n "$ac_tool_prefix"; then
@@ -5121,6 +6425,16 @@ _ACEOF
fi
+#
+# Makefile.in includes rules to generate version.h, so we assume
+# that it will be generated if autoconf is used.
+#
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_VERSION_H 1
+_ACEOF
+
+
rm -f net
ln -s ${srcdir}/bpf/net net
@@ -5135,6 +6449,7 @@ ln -s ${srcdir}/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:
@@ -5862,6 +7177,7 @@ s,@V_PCAP@,$V_PCAP,;t t
s,@V_FINDALLDEVS@,$V_FINDALLDEVS,;t t
s,@V_RANLIB@,$V_RANLIB,;t t
s,@SSRC@,$SSRC,;t t
+s,@DYEXT@,$DYEXT,;t t
s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
s,@INSTALL_DATA@,$INSTALL_DATA,;t t
diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.in
index 48464992b987..d970fd55141b 100755
--- a/contrib/libpcap/configure.in
+++ b/contrib/libpcap/configure.in
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.100.2.4 2004/03/28 21:43:34 fenner Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120 2005/03/27 22:26:25 guy Exp $ (LBL)
dnl
dnl Copyright (c) 1994, 1995, 1996, 1997
dnl The Regents of the University of California. All rights reserved.
@@ -6,7 +6,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_REVISION($Revision: 1.100.2.4 $)
+AC_REVISION($Revision: 1.120 $)
AC_PREREQ(2.50)
AC_INIT(pcap.c)
@@ -26,13 +26,30 @@ dnl in "AC_LBL_FIXINCLUDES" in "aclocal.m4" uses it, so we have to
dnl test for it and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise
dnl "AC_LBL_FIXINCLUDES" won't work on some platforms such as Solaris.
dnl
-AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h ifaddrs.h limits.h)
+AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h)
AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
#include <sys/socket.h>])
+if test "$ac_cv_header_netinet_if_ether_h" != yes; then
+ #
+ # The simple test didn't work.
+ # Do we need to include <net/if.h> first?
+ # Unset ac_cv_header_netinet_if_ether_h so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ AC_MSG_NOTICE([Rechecking with some additional includes])
+ unset ac_cv_header_netinet_if_ether_h
+ AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>])
+fi
AC_LBL_FIXINCLUDES
-AC_CHECK_FUNCS(ether_hostton strerror strlcpy)
+AC_CHECK_FUNCS(strerror strlcpy)
needsnprintf=no
AC_CHECK_FUNCS(vsnprintf snprintf,,
@@ -41,6 +58,75 @@ if test $needsnprintf = yes; then
AC_LIBOBJ(snprintf)
fi
+#
+# Do this before checking for ether_hostton(), as it's a
+# "gethostbyname() -ish function".
+#
+AC_LBL_LIBRARY_NET
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it, but not declare it in any header file.
+# Some might have it, but declare it in <netinet/if_ether.h>.
+# Some might have it, but declare it in <netinet/ether.h>
+# (And some might have it but document it as something declared in
+# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
+#
+# Before you is a C compiler.
+#
+AC_CHECK_FUNCS(ether_hostton)
+if test "$ac_cv_func_ether_hostton" = yes; then
+ #
+ # OK, we have ether_hostton(). Do we have <netinet/if_ether.h>?
+ #
+ if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+ #
+ # Yes. Does it declare ether_hostton()?
+ #
+ AC_CHECK_DECLS(ether_hostton,
+ [
+ AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if netinet/if_ether.h declares `ether_hostton'])
+ ],,
+ [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+#include <netinet/if_ether.h>
+ ])
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/ether.h>, as on Linux?
+ #
+ AC_CHECK_HEADERS(netinet/ether.h)
+ if test "$ac_cv_header_netinet_ether_h" = yes; then
+ #
+ # We have it - does it declare ether_hostton()?
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ AC_CHECK_DECLS(ether_hostton,
+ [
+ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if netinet/ether.h declares `ether_hostton'])
+ ],,
+ [
+#include <netinet/ether.h>
+ ])
+ fi
+ fi
+fi
+
dnl to pacify those who hate protochain insn
AC_MSG_CHECKING(if --disable-protochain option is specified)
AC_ARG_ENABLE(protochain, [ --disable-protochain disable \"protochain\" insn])
@@ -105,65 +191,88 @@ fi
AC_MSG_RESULT($V_PCAP)
dnl
-dnl Now figure out how we get a list of interfaces and addresses.
+dnl Now figure out how we get a list of interfaces and addresses,
+dnl if we support capturing. Don't bother if we don't support
+dnl capturing.
dnl
-AC_CHECK_FUNC(getifaddrs,[
+if test "$V_PCAP" = null
+then
#
- # We have "getifaddrs()", so we use that to get the list
+ # We can't capture, so we can't open any capture
+ # devices, so we won't return any interfaces.
#
- V_FINDALLDEVS=getad
-],[
- #
- # Well, we don't have "getifaddrs()", so we have to use some
- # other mechanism; determine what that mechanism is.
- #
- # The first thing we use is the type of capture mechanism,
- # which is somewhat of a proxy for the OS we're using.
- #
- case "$V_PCAP" in
-
- dlpi)
- #
- # This might be Solaris 8 or later, with SIOCGLIFCONF,
- # or it might be some other OS, with just SIOCGIFCONF.
+ V_FINDALLDEVS=null
+else
+ AC_CHECK_FUNC(getifaddrs,[
#
- AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
- AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
- AC_TRY_COMPILE(
- [#include <sys/param.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>],
- [ioctl(0, SIOCGLIFCONF, (char *)0);],
- ac_cv_lbl_have_siocglifconf=yes,
- ac_cv_lbl_have_siocglifconf=no))
- AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
- if test $ac_cv_lbl_have_siocglifconf = yes ; then
- V_FINDALLDEVS=glifc
- else
- V_FINDALLDEVS=gifc
- fi
- ;;
-
- null)
+ # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+ # as well, just in case some platform is really weird.
#
- # We can't capture, so we can't open any capture
- # devices, so we won't return any interfaces.
+ AC_CHECK_HEADER(ifaddrs.h,[
+ #
+ # We have the header, so we use "getifaddrs()" to
+ # get the list of interfaces.
+ #
+ V_FINDALLDEVS=getad
+ ],[
+ #
+ # We don't have the header - give up.
+ # XXX - we could also fall back on some other
+ # mechanism, but, for now, this'll catch this
+ # problem so that we can at least try to figure
+ # out something to do on systems with "getifaddrs()"
+ # but without "ifaddrs.h", if there is something
+ # we can do on those systems.
+ #
+ AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.])
+ ])
+ ],[
#
- V_FINDALLDEVS=null
- ;;
-
- *)
+ # Well, we don't have "getifaddrs()", so we have to use
+ # some other mechanism; determine what that mechanism is.
#
- # Assume we just have SIOCGIFCONF.
- # (XXX - on at least later Linux kernels, there's
- # another mechanism, and we should be using that
- # instead.)
+ # The first thing we use is the type of capture mechanism,
+ # which is somewhat of a proxy for the OS we're using.
#
- V_FINDALLDEVS=gifc
- ;;
- esac])
+ case "$V_PCAP" in
+
+ dlpi)
+ #
+ # This might be Solaris 8 or later, with
+ # SIOCGLIFCONF, or it might be some other OS
+ # or some older version of Solaris, with
+ # just SIOCGIFCONF.
+ #
+ AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
+ AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
+ AC_TRY_COMPILE(
+ [#include <sys/param.h>
+ #include <sys/file.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <sys/sockio.h>],
+ [ioctl(0, SIOCGLIFCONF, (char *)0);],
+ ac_cv_lbl_have_siocglifconf=yes,
+ ac_cv_lbl_have_siocglifconf=no))
+ AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
+ if test $ac_cv_lbl_have_siocglifconf = yes ; then
+ V_FINDALLDEVS=glifc
+ else
+ V_FINDALLDEVS=gifc
+ fi
+ ;;
+
+ *)
+ #
+ # Assume we just have SIOCGIFCONF.
+ # (XXX - on at least later Linux kernels, there's
+ # another mechanism, and we should be using that
+ # instead.)
+ #
+ V_FINDALLDEVS=gifc
+ ;;
+ esac])
+fi
AC_MSG_CHECKING(if --enable-ipv6 option is specified)
AC_ARG_ENABLE(ipv6, [ --enable-ipv6 build IPv6-capable version])
@@ -249,16 +358,19 @@ if test $ac_cv_lbl_proc_net_dev = yes; then
fi
AC_MSG_RESULT($ac_cv_lbl_proc_net_dev)
-AC_ARG_WITH(dag, [ --with-dag[=DIR] include DAG support (located in directory DIR, if supplied). [default=yes, on BSD and Linux, if present]],
+# Check for Endace DAG card support.
+AC_ARG_WITH([dag], [ --with-dag[[=DIR]] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)],
[
if test "$withval" = no
then
+ # User doesn't want DAG support.
want_dag=no
elif test "$withval" = yes
then
+ # User wants DAG support but hasn't specified a directory.
want_dag=yes
- dag_root=
else
+ # User wants DAG support and has specified a directory, so use the provided value.
want_dag=yes
dag_root=$withval
fi
@@ -267,9 +379,22 @@ AC_ARG_WITH(dag, [ --with-dag[=DIR] include DAG support (located in dire
# Use DAG API if present, otherwise don't
#
want_dag=ifpresent
- dag_root=/root/dag
])
-ac_cv_lbl_dag_api=no
+
+AC_ARG_WITH([dag-includes], [ --with-dag-includes=DIR Endace DAG include directory],
+[
+ # User wants DAG support and has specified a header directory, so use the provided value.
+ want_dag=yes
+ dag_include_dir=$withval
+],[])
+
+AC_ARG_WITH([dag-libraries], [ --with-dag-libraries=DIR Endace DAG library directory],
+[
+ # User wants DAG support and has specified a library directory, so use the provided value.
+ want_dag=yes
+ dag_lib_dir=$withval
+],[])
+
case "$V_PCAP" in
linux|bpf|dag)
#
@@ -285,60 +410,167 @@ linux|bpf|dag)
# If they expressed no preference, don't include it.
#
if test $want_dag = yes; then
- AC_MSG_ERROR(DAG support only available with 'linux' 'bpf' and 'dag' packet capture types)
+ AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types])
elif test $want_dag = yes; then
want_dag=no
fi
;;
esac
-if test "$with_dag" != no; then
- AC_MSG_CHECKING(whether we have DAG API)
+ac_cv_lbl_dag_api=no
+if test "$want_dag" != no; then
+
+ AC_MSG_CHECKING([whether we have DAG API headers])
+ # If necessary, set default paths for DAG API headers and libraries.
if test -z "$dag_root"; then
- dag_root=$srcdir/../dag
+ dag_root=/usr/local
fi
- if test -r "$dag_root/tools" -a -r "$dag_root/include"; then
- dag_tools_dir="$dag_root/tools"
+ if test -z "$dag_include_dir"; then
dag_include_dir="$dag_root/include"
- else
- dag_tools_dir="$dag_root"
- dag_include_dir="$dag_root"
fi
- ac_cv_lbl_dag_api=no
- if test -r "$dag_include_dir/dagapi.h" -a -r "$dag_tools_dir/dagapi.o" -a -r "$dag_tools_dir/dagopts.o"; then
- V_INCLS="$V_INCLS -I $dag_include_dir"
- V_LIBS="$V_LIBS $dag_tools_dir/dagapi.o $dag_tools_dir/dagopts.o"
- if test "$V_PCAP" != dag ; then
- SSRC="pcap-dag.c"
+ if test -z "$dag_lib_dir"; then
+ dag_lib_dir="$dag_root/lib"
+ fi
+
+ if test -z "$dag_tools_dir"; then
+ dag_tools_dir="$dag_root/tools"
fi
+
+ if test -r $dag_include_dir/dagapi.h; then
ac_cv_lbl_dag_api=yes
fi
- if test -r "$dag_root/lib/dagreg.c"; then # DAG 2.5.x
- if test -r "$dag_tools_dir/dagreg.o"; then
- V_LIBS="$V_LIBS $dag_tools_dir/dagreg.o"
- else
+ AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)])
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ AC_MSG_CHECKING([dagapi.o])
+ dagapi_obj=no
+ if test -r $dag_tools_dir/dagapi.o; then
+
+ # 2.4.x.
+ dagapi_obj=$dag_tools_dir/dagapi.o
+
+ elif test -r $dag_lib_dir/dagapi.o; then
+
+ # 2.5.x.
+ dagapi_obj=$dag_lib_dir/dagapi.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # 2.5.x.
+ ar x $dag_lib_dir/libdag.a dagapi.o
+ if test -r ./dagapi.o; then
+ dagapi_obj=./dagapi.o
+ fi
+ fi
+
+ if test $dagapi_obj = no; then
+ AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)])
ac_cv_lbl_dag_api=no
+ else
+ AC_MSG_RESULT([yes ($dagapi_obj)])
fi
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ AC_MSG_CHECKING([dagopts.o])
+ dagopts_obj=no
+ if test -r $dag_tools_dir/dagopts.o; then
+
+ # 2.4.x.
+ dagopts_obj=$dag_tools_dir/dagopts.o
+
+ elif test -r $dag_lib_dir/dagopts.o; then
+
+ # 2.5.x.
+ dagopts_obj=$dag_lib_dir/dagopts.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # 2.5.x.
+ ar x $dag_lib_dir/libdag.a dagopts.o
+ if test -r ./dagopts.o; then
+ dagopts_obj=./dagopts.o
fi
- dag_version=
- if test $ac_cv_lbl_dag_api = yes -a -r "$dag_root/VERSION"; then
- dag_version=" (`cat $dag_root/VERSION`)"
fi
- AC_MSG_RESULT($ac_cv_lbl_dag_api$dag_version)
- if test $ac_cv_lbl_dag_api = no; then
- if test "$want_dag" = yes; then
- AC_MSG_ERROR(DAG API not found under directory $dag_root; use --without-dag)
+
+ if test $dagopts_obj = no; then
+ AC_MSG_RESULT([no (checked $dag_lib_dir $dag_tools_dir $dag_lib_dir/libdag.a)])
+ ac_cv_lbl_dag_api=no
+ else
+ AC_MSG_RESULT([yes ($dagopts_obj)])
+ fi
+fi
+
+if test $ac_cv_lbl_dag_api = yes; then
+
+ # Under 2.5.x only we need to add dagreg.o.
+ if test -r $dag_include_dir/dagreg.h; then
+
+ AC_MSG_CHECKING([dagreg.o])
+ dagreg_obj=no
+ if test -r $dag_lib_dir/dagreg.o; then
+
+ # Object file is ready and waiting.
+ dagreg_obj=$dag_lib_dir/dagreg.o
+
+ elif test -r $dag_lib_dir/libdag.a; then
+
+ # Extract from libdag.a.
+ ar x $dag_lib_dir/libdag.a dagreg.o
+ if test -r ./dagreg.o; then
+ dagreg_obj=./dagreg.o
fi
+ fi
+
+ if test $dagreg_obj = no; then
+ AC_MSG_RESULT([no (checked $dag_lib_dir $dag_lib_dir/libdag.a)])
+ ac_cv_lbl_dag_api=no
else
- AC_DEFINE(HAVE_DAG_API, 1, [define if you have a DAG API])
+ AC_MSG_RESULT([yes ($dagreg_obj)])
+ fi
fi
fi
-if test "$V_PCAP" = dag -a "$ac_cv_lbl_dag_api" = no; then
- AC_MSG_ERROR(Specifying the capture type as 'dag' requires the DAG API to be present; use --with-dag=DIR)
+if test $ac_cv_lbl_dag_api = yes; then
+
+ V_INCLS="$V_INCLS -I$dag_include_dir"
+ V_LIBS="$V_LIBS $dagapi_obj $dagopts_obj $dagreg_obj"
+ if test $V_PCAP != dag ; then
+ SSRC="pcap-dag.c"
+ fi
+
+ # See if we can find a general version string.
+ # Don't need to save and restore LIBS to prevent -ldag being included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"])
+ LDFLAGS=$saved_ldflags
+
+ # See if we can find a specific version string.
+ AC_MSG_CHECKING([the DAG API version])
+ if test -r "$dag_root/VERSION"; then
+ dag_version="`cat $dag_root/VERSION`"
+ fi
+ AC_MSG_RESULT([$dag_version])
+ AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+fi
+
+if test $ac_cv_lbl_dag_api = no; then
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag])
+ fi
+
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but the DAG API wasn't found.
+ AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)])
+ fi
fi
@@ -360,6 +592,7 @@ if test "$V_LEX" = lex ; then
fi
fi
+DYEXT="so"
case "$host_os" in
aix*)
@@ -378,7 +611,12 @@ hpux10.1*)
;;
hpux*)
- dnl HPUX 10.20 and above is similar to HPUX 9...
+ dnl HPUX 10.20 and above is similar to HPUX 9, but
+ dnl not the same....
+ dnl
+ dnl XXX - DYEXT should be set to "sl" if this is building
+ dnl for 32-bit PA-RISC, but should be left as "so" for
+ dnl 64-bit PA-RISC or, I suspect, IA-64.
AC_DEFINE(HAVE_HPUX10_20,1,[on HP-UX 10.20])
;;
@@ -399,6 +637,11 @@ sinix*)
solaris*)
AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
+ ;;
esac
AC_PROG_RANLIB
@@ -413,6 +656,12 @@ AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
AC_LBL_UNALIGNED_ACCESS
+#
+# Makefile.in includes rules to generate version.h, so we assume
+# that it will be generated if autoconf is used.
+#
+AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure])
+
rm -f net
ln -s ${srcdir}/bpf/net net
@@ -426,6 +675,7 @@ AC_SUBST(V_FINDALLDEVS)
AC_SUBST(V_RANLIB)
AC_SUBST(V_YACC)
AC_SUBST(SSRC)
+AC_SUBST(DYEXT)
AC_PROG_INSTALL
diff --git a/contrib/libpcap/etherent.c b/contrib/libpcap/etherent.c
index 11f34f2e165d..9d299557f0d0 100644
--- a/contrib/libpcap/etherent.c
+++ b/contrib/libpcap/etherent.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.21.6.1 2003/11/15 23:26:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.22 2003/11/15 23:23:57 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/ethertype.h b/contrib/libpcap/ethertype.h
index 3af5576e8160..f2589361ddfe 100644
--- a/contrib/libpcap/ethertype.h
+++ b/contrib/libpcap/ethertype.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.12 2001/01/14 21:26:52 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.13 2004/06/16 08:20:28 hannes Exp $ (LBL)
*/
/*
@@ -102,6 +102,12 @@
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6 0x86dd
#endif
+#ifndef ETHERTYPE_MPLS
+#define ETHERTYPE_MPLS 0x8847
+#endif
+#ifndef ETHERTYPE_MPLS_MULTI
+#define ETHERTYPE_MPLS_MULTI 0x8848
+#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
diff --git a/contrib/libpcap/fad-getad.c b/contrib/libpcap/fad-getad.c
index 55a6bf13b742..e9ec4099a17a 100644
--- a/contrib/libpcap/fad-getad.c
+++ b/contrib/libpcap/fad-getad.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.7.2.2 2004/03/11 23:04:52 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10 2004/11/04 07:26:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -58,6 +58,10 @@ static const char rcsid[] _U_ =
#include "os-proto.h"
#endif
+#ifdef AF_PACKET
+# include <linux/if_packet.h>
+#endif
+
/*
* This is fun.
*
@@ -101,6 +105,11 @@ get_sa_len(struct sockaddr *addr)
return (sizeof (struct sockaddr_in6));
#endif
+#ifdef AF_PACKET
+ case AF_PACKET:
+ return (sizeof (struct sockaddr_ll));
+#endif
+
default:
return (sizeof (struct sockaddr));
}
diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c
index 0214d59d0217..4ed02f9a0e53 100644
--- a/contrib/libpcap/fad-gifc.c
+++ b/contrib/libpcap/fad-gifc.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.4.2.1 2003/11/15 23:26:39 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8 2005/01/29 10:34:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -255,6 +255,9 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
struct ifconf ifc;
char *buf = NULL;
unsigned buf_size;
+#ifdef HAVE_SOLARIS
+ char *p, *q;
+#endif
struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
struct sockaddr *netmask, *broadaddr, *dstaddr;
size_t netmask_size, broadaddr_size, dstaddr_size;
@@ -324,6 +327,28 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
ifnext = (struct ifreq *)((char *)ifrp + n);
/*
+ * XXX - The 32-bit compatibility layer for Linux on IA-64
+ * is slightly broken. It correctly converts the structures
+ * to and from kernel land from 64 bit to 32 bit but
+ * doesn't update ifc.ifc_len, leaving it larger than the
+ * amount really used. This means we read off the end
+ * of the buffer and encounter an interface with an
+ * "empty" name. Since this is highly unlikely to ever
+ * occur in a valid case we can just finish looking for
+ * interfaces if we see an empty name.
+ */
+ if (!(*ifrp->ifr_name))
+ break;
+
+ /*
+ * Skip entries that begin with "dummy".
+ * XXX - what are these? Is this Linux-specific?
+ * Are there platforms on which we shouldn't do this?
+ */
+ if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
+ continue;
+
+ /*
* Get the flags for this interface, and skip it if it's
* not up.
*/
@@ -449,6 +474,34 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
dstaddr_size = 0;
}
+#ifdef HAVE_SOLARIS
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, it's a logical interface. Those are just
+ * the way you assign multiple IP addresses to a real
+ * interface, so an entry for a logical interface should
+ * be treated like the entry for the real interface;
+ * we do that by stripping off the ":" and the number.
+ */
+ p = strchr(ifrp->ifr_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+#endif
+
/*
* Add information for this address to the list.
*/
diff --git a/contrib/libpcap/fad-glifc.c b/contrib/libpcap/fad-glifc.c
index d365ae1aa0d1..8ad7a6cb5f4f 100644
--- a/contrib/libpcap/fad-glifc.c
+++ b/contrib/libpcap/fad-glifc.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.2.2.1 2003/11/15 23:26:39 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5 2005/01/29 10:34:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -89,6 +89,9 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
struct lifconf ifc;
char *buf = NULL;
unsigned buf_size;
+#ifdef HAVE_SOLARIS
+ char *p, *q;
+#endif
struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
struct sockaddr *netmask, *broadaddr, *dstaddr;
int ret = 0;
@@ -175,6 +178,36 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
fd = fd4;
/*
+ * Skip entries that begin with "dummy".
+ * XXX - what are these? Is this Linux-specific?
+ * Are there platforms on which we shouldn't do this?
+ */
+ if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
+ continue;
+
+#ifdef HAVE_SOLARIS
+ /*
+ * Skip entries that have a ":" followed by a number
+ * at the end - those are Solaris virtual interfaces
+ * on which you can't capture.
+ */
+ p = strchr(ifrp->lifr_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ while (isdigit((unsigned char)*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ */
+ continue;
+ }
+ }
+#endif
+
+ /*
* Get the flags for this interface, and skip it if it's
* not up.
*/
@@ -284,6 +317,34 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
} else
dstaddr = NULL;
+#ifdef HAVE_SOLARIS
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, it's a logical interface. Those are just
+ * the way you assign multiple IP addresses to a real
+ * interface, so an entry for a logical interface should
+ * be treated like the entry for the real interface;
+ * we do that by stripping off the ":" and the number.
+ */
+ p = strchr(ifrp->ifr_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+#endif
+
/*
* Add information for this address to the list.
*/
diff --git a/contrib/libpcap/fad-null.c b/contrib/libpcap/fad-null.c
index be1a0edcc831..676ff71e44fd 100644
--- a/contrib/libpcap/fad-null.c
+++ b/contrib/libpcap/fad-null.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.1.2.1 2003/11/15 23:26:39 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.2 2003/11/15 23:23:58 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/fad-win32.c b/contrib/libpcap/fad-win32.c
index cc2ce5a9afcc..91b0ef954439 100644
--- a/contrib/libpcap/fad-win32.c
+++ b/contrib/libpcap/fad-win32.c
@@ -32,7 +32,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.7.2.1 2003/11/15 23:26:40 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11 2005/01/29 00:52:22 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -155,8 +155,7 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
/*
* Add an entry for this interface, with no addresses.
*/
- if (add_or_find_if(&curdev, devlist, (char *)name, 0, (char *)desc,
- errbuf) == -1) {
+ if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
/*
* Failure.
*/
@@ -221,14 +220,30 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
pcap_if_t *devlist = NULL;
int ret = 0;
const char *desc;
- char AdaptersName[8192];
- ULONG NameLength = 8192;
+ char *AdaptersName;
+ ULONG NameLength;
char *name;
+ PacketGetAdapterNames(NULL, &NameLength);
+
+ if (NameLength > 0)
+ AdaptersName = (char*) malloc(NameLength);
+ else
+ {
+ *alldevsp = NULL;
+ return 0;
+ }
+ if (AdaptersName == NULL)
+ {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+ return (-1);
+ }
+
if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketGetAdapterNames: %s",
pcap_win32strerror());
+ free(AdaptersName);
return (-1);
}
@@ -261,14 +276,13 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
*/
name = &AdaptersName[0];
while (*name != '\0') {
- /*
- * Add an entry for this interface.
- */
- if (pcap_add_if_win32(&devlist, name, desc,
- errbuf) == -1) {
+ /*
+ * Add an entry for this interface.
+ */
+ if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
/*
- * Failure.
- */
+ * Failure.
+ */
ret = -1;
break;
}
@@ -277,15 +291,16 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
}
if (ret == -1) {
- /*
- * We had an error; free the list we've been constructing.
- */
- if (devlist != NULL) {
+ /*
+ * We had an error; free the list we've been constructing.
+ */
+ if (devlist != NULL) {
pcap_freealldevs(devlist);
devlist = NULL;
}
}
*alldevsp = devlist;
+ free(AdaptersName);
return (ret);
}
diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c
index 33f5a50ff9d1..9fff3cb87a5b 100644
--- a/contrib/libpcap/gencode.c
+++ b/contrib/libpcap/gencode.c
@@ -21,7 +21,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.193.2.8 2004/03/29 20:53:47 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221 2005/03/27 22:10:23 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -33,7 +33,6 @@ static const char rcsid[] _U_ =
#else /* WIN32 */
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/time.h>
#endif /* WIN32 */
/*
@@ -59,6 +58,10 @@ static const char rcsid[] _U_ =
#include <setjmp.h>
#include <stdarg.h>
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
#include "pcap-int.h"
#include "ethertype.h"
@@ -97,14 +100,12 @@ static const char rcsid[] _U_ =
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
-/* Hack for updating VLAN offsets. */
-static u_int orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1;
+/* Hack for updating VLAN, MPLS offsets. */
+static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U;
/* XXX */
#ifdef PCAP_FDDIPAD
-int pcap_fddipad = PCAP_FDDIPAD;
-#else
-int pcap_fddipad;
+static int pcap_fddipad;
#endif
/* VARARGS */
@@ -123,7 +124,7 @@ bpf_error(const char *fmt, ...)
/* NOTREACHED */
}
-static void init_linktype(int);
+static void init_linktype(pcap_t *);
static int alloc_reg(void);
static void free_reg(int);
@@ -133,8 +134,10 @@ 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
+ * not a big deal if all this memory was wasted but if this ever
* goes into a library that would probably not be a good idea.
+ *
+ * XXX - this *is* in a library....
*/
#define NCHUNKS 16
#define CHUNK0SIZE 1024
@@ -165,6 +168,7 @@ static struct block *gen_uncond(int);
static inline struct block *gen_true(void);
static inline struct block *gen_false(void);
static struct block *gen_ether_linktype(int);
+static struct block *gen_linux_sll_linktype(int);
static struct block *gen_linktype(int);
static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int);
static struct block *gen_llc(int);
@@ -340,7 +344,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
}
lex_init(buf ? buf : "");
- init_linktype(pcap_datalink(p));
+ init_linktype(p);
(void)pcap_parse();
if (n_errors)
@@ -577,15 +581,15 @@ gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse)
{
struct slist *s;
struct block *b;
-
+
s = new_stmt(BPF_LD|datasize|BPF_ABS);
s->s.k = offset;
-
+
if (mask != 0xffffffff) {
s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K);
s->next->s.k = mask;
}
-
+
b = new_block(JMP(jtype));
b->stmts = s;
b->s.k = jvalue;
@@ -678,10 +682,13 @@ static u_int off_nl_nosnap;
static int linktype;
static void
-init_linktype(type)
- int type;
+init_linktype(p)
+ pcap_t *p;
{
- linktype = type;
+ linktype = pcap_datalink(p);
+#ifdef PCAP_FDDIPAD
+ pcap_fddipad = p->fddipad;
+#endif
/*
* Assume it's not raw ATM with a pseudo-header, for now.
@@ -698,7 +705,7 @@ init_linktype(type)
orig_nl = -1;
orig_nl_nosnap = -1;
- switch (type) {
+ switch (linktype) {
case DLT_ARCNET:
off_linktype = 2;
@@ -750,6 +757,7 @@ init_linktype(type)
return;
case DLT_PPP:
+ case DLT_PPP_PPPD:
case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
off_linktype = 2;
@@ -922,7 +930,7 @@ init_linktype(type)
off_vpi = SUNATM_VPI_POS;
off_vci = SUNATM_VCI_POS;
off_proto = PROTO_POS;
- off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */
+ off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */
off_payload = SUNATM_PKT_BEGIN_POS;
off_linktype = off_payload;
off_nl = off_payload+8; /* 802.2+SNAP */
@@ -993,6 +1001,21 @@ init_linktype(type)
off_nl_nosnap = -1;
return;
+ case DLT_DOCSIS:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_SYMANTEC_FIREWALL:
+ off_linktype = 6;
+ off_nl = 44; /* Ethernet II */
+ off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */
+ return;
+
case DLT_PFLOG:
off_linktype = 0;
/* XXX read from header? */
@@ -1000,6 +1023,25 @@ init_linktype(type)
off_nl_nosnap = PFLOG_HDRLEN;
return;
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ off_linktype = 4;
+ off_nl = 4;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_JUNIPER_ATM1:
+ off_linktype = 4; /* in reality variable between 4-8 */
+ off_nl = 4;
+ off_nl_nosnap = 14;
+ return;
+
+ case DLT_JUNIPER_ATM2:
+ off_linktype = 8; /* in reality variable between 8-12 */
+ off_nl = 8;
+ off_nl_nosnap = 18;
+ return;
+
#ifdef DLT_PFSYNC
case DLT_PFSYNC:
off_linktype = -1;
@@ -1232,6 +1274,172 @@ gen_ether_linktype(proto)
}
static struct block *
+gen_linux_sll_linktype(proto)
+ register int proto;
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case LLCSAP_IP:
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_IP << 8) | LLCSAP_IP));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_ISONS:
+ /*
+ * OSI protocols always use 802.2 encapsulation.
+ * XXX - should we check both the DSAP and the
+ * SSAP, like this, or should we check just the
+ * DSAP?
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_NETBEUI:
+ /*
+ * NetBEUI always uses 802.2 encapsulation.
+ * XXX - should we check both the DSAP and the
+ * LSAP, like this, or should we check just the
+ * DSAP?
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_IPX:
+ /*
+ * Ethernet_II frames, which are Ethernet
+ * frames with a frame type of ETHERTYPE_IPX;
+ *
+ * Ethernet_802.3 frames, which have a frame
+ * type of LINUX_SLL_P_802_3;
+ *
+ * Ethernet_802.2 frames, which are 802.3
+ * frames with an 802.2 LLC header (i.e, have
+ * a frame type of LINUX_SLL_P_802_2) and
+ * with the IPX LSAP as the DSAP in the LLC
+ * header;
+ *
+ * Ethernet_SNAP frames, which are 802.3
+ * frames with an LLC header and a SNAP
+ * header and with an OUI of 0x000000
+ * (encapsulated Ethernet) and a protocol
+ * ID of ETHERTYPE_IPX in the SNAP header.
+ *
+ * First, do the checks on LINUX_SLL_P_802_2
+ * frames; generate the check for either
+ * Ethernet_802.2 or Ethernet_SNAP frames, and
+ * then put a check for LINUX_SLL_P_802_2 frames
+ * before it.
+ */
+ b0 = gen_cmp(off_linktype + 2, BPF_B,
+ (bpf_int32)LLCSAP_IPX);
+ b1 = gen_snap(0x000000, ETHERTYPE_IPX,
+ off_linktype + 2);
+ gen_or(b0, b1);
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ gen_and(b0, b1);
+
+ /*
+ * Now check for 802.3 frames and OR that with
+ * the previous test.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
+ gen_or(b0, b1);
+
+ /*
+ * Now add the check for Ethernet_II frames, and
+ * do that before checking for the other frame
+ * types.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H,
+ (bpf_int32)ETHERTYPE_IPX);
+ gen_or(b0, b1);
+ return b1;
+
+ case ETHERTYPE_ATALK:
+ case ETHERTYPE_AARP:
+ /*
+ * EtherTalk (AppleTalk protocols on Ethernet link
+ * layer) may use 802.2 encapsulation.
+ */
+
+ /*
+ * Check for 802.2 encapsulation (EtherTalk phase 2?);
+ * we check for the 802.2 protocol type in the
+ * "Ethernet type" field.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+
+ /*
+ * 802.2-encapsulated ETHERTYPE_ATALK packets are
+ * SNAP packets with an organization code of
+ * 0x080007 (Apple, for Appletalk) and a protocol
+ * type of ETHERTYPE_ATALK (Appletalk).
+ *
+ * 802.2-encapsulated ETHERTYPE_AARP packets are
+ * SNAP packets with an organization code of
+ * 0x000000 (encapsulated Ethernet) and a protocol
+ * type of ETHERTYPE_AARP (Appletalk ARP).
+ */
+ if (proto == ETHERTYPE_ATALK)
+ b1 = gen_snap(0x080007, ETHERTYPE_ATALK,
+ off_linktype + 2);
+ else /* proto == ETHERTYPE_AARP */
+ b1 = gen_snap(0x000000, ETHERTYPE_AARP,
+ off_linktype + 2);
+ gen_and(b0, b1);
+
+ /*
+ * Check for Ethernet encapsulation (Ethertalk
+ * phase 1?); we just check for the Ethernet
+ * protocol type.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+
+ gen_or(b0, b1);
+ return b1;
+
+ default:
+ if (proto <= ETHERMTU) {
+ /*
+ * This is an LLC SAP value, so the frames
+ * that match would be 802.2 frames.
+ * Check for the 802.2 protocol type
+ * in the "Ethernet type" field, and
+ * then check the DSAP.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H,
+ LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_B,
+ (bpf_int32)proto);
+ gen_and(b0, b1);
+ return b1;
+ } else {
+ /*
+ * This is an Ethernet type, so compare
+ * the length/type field with it (if
+ * the frame is an 802.2 frame, the length
+ * field will be <= ETHERMTU, and, as
+ * "proto" is > ETHERMTU, this test
+ * will fail and the frame won't match,
+ * which is what we want).
+ */
+ return gen_cmp(off_linktype, BPF_H,
+ (bpf_int32)proto);
+ }
+ }
+}
+
+static struct block *
gen_linktype(proto)
register int proto;
{
@@ -1241,6 +1449,7 @@ gen_linktype(proto)
case DLT_EN10MB:
return gen_ether_linktype(proto);
+ /*NOTREACHED*/
break;
case DLT_C_HDLC:
@@ -1252,6 +1461,7 @@ gen_linktype(proto)
default:
return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED*/
break;
}
break;
@@ -1265,6 +1475,7 @@ gen_linktype(proto)
case DLT_ATM_CLIP:
case DLT_IP_OVER_FC:
return gen_llc(proto);
+ /*NOTREACHED*/
break;
case DLT_SUNATM:
@@ -1302,164 +1513,8 @@ gen_linktype(proto)
}
case DLT_LINUX_SLL:
- switch (proto) {
-
- case LLCSAP_IP:
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_IP << 8) | LLCSAP_IP));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_ISONS:
- /*
- * OSI protocols always use 802.2 encapsulation.
- * XXX - should we check both the DSAP and the
- * LSAP, like this, or should we check just the
- * DSAP?
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_NETBEUI:
- /*
- * NetBEUI always uses 802.2 encapsulation.
- * XXX - should we check both the DSAP and the
- * LSAP, like this, or should we check just the
- * DSAP?
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_IPX:
- /*
- * Ethernet_II frames, which are Ethernet
- * frames with a frame type of ETHERTYPE_IPX;
- *
- * Ethernet_802.3 frames, which have a frame
- * type of LINUX_SLL_P_802_3;
- *
- * Ethernet_802.2 frames, which are 802.3
- * frames with an 802.2 LLC header (i.e, have
- * a frame type of LINUX_SLL_P_802_2) and
- * with the IPX LSAP as the DSAP in the LLC
- * header;
- *
- * Ethernet_SNAP frames, which are 802.3
- * frames with an LLC header and a SNAP
- * header and with an OUI of 0x000000
- * (encapsulated Ethernet) and a protocol
- * ID of ETHERTYPE_IPX in the SNAP header.
- *
- * First, do the checks on LINUX_SLL_P_802_2
- * frames; generate the check for either
- * Ethernet_802.2 or Ethernet_SNAP frames, and
- * then put a check for LINUX_SLL_P_802_2 frames
- * before it.
- */
- b0 = gen_cmp(off_linktype + 2, BPF_B,
- (bpf_int32)LLCSAP_IPX);
- b1 = gen_snap(0x000000, ETHERTYPE_IPX,
- off_linktype + 2);
- gen_or(b0, b1);
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- gen_and(b0, b1);
-
- /*
- * Now check for 802.3 frames and OR that with
- * the previous test.
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
- gen_or(b0, b1);
-
- /*
- * Now add the check for Ethernet_II frames, and
- * do that before checking for the other frame
- * types.
- */
- b0 = gen_cmp(off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
- gen_or(b0, b1);
- return b1;
-
- case ETHERTYPE_ATALK:
- case ETHERTYPE_AARP:
- /*
- * EtherTalk (AppleTalk protocols on Ethernet link
- * layer) may use 802.2 encapsulation.
- */
-
- /*
- * Check for 802.2 encapsulation (EtherTalk phase 2?);
- * we check for the 802.2 protocol type in the
- * "Ethernet type" field.
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
-
- /*
- * 802.2-encapsulated ETHERTYPE_ATALK packets are
- * SNAP packets with an organization code of
- * 0x080007 (Apple, for Appletalk) and a protocol
- * type of ETHERTYPE_ATALK (Appletalk).
- *
- * 802.2-encapsulated ETHERTYPE_AARP packets are
- * SNAP packets with an organization code of
- * 0x000000 (encapsulated Ethernet) and a protocol
- * type of ETHERTYPE_AARP (Appletalk ARP).
- */
- if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK,
- off_linktype + 2);
- else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP,
- off_linktype + 2);
- gen_and(b0, b1);
-
- /*
- * Check for Ethernet encapsulation (Ethertalk
- * phase 1?); we just check for the Ethernet
- * protocol type.
- */
- b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
-
- gen_or(b0, b1);
- return b1;
-
- default:
- if (proto <= ETHERMTU) {
- /*
- * This is an LLC SAP value, so the frames
- * that match would be 802.2 frames.
- * Check for the 802.2 protocol type
- * in the "Ethernet type" field, and
- * then check the DSAP.
- */
- b0 = gen_cmp(off_linktype, BPF_H,
- LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_B,
- (bpf_int32)proto);
- gen_and(b0, b1);
- return b1;
- } else {
- /*
- * This is an Ethernet type, so compare
- * the length/type field with it (if
- * the frame is an 802.2 frame, the length
- * field will be <= ETHERMTU, and, as
- * "proto" is > ETHERMTU, this test
- * will fail and the frame won't match,
- * which is what we want).
- */
- return gen_cmp(off_linktype, BPF_H,
- (bpf_int32)proto);
- }
- }
+ return gen_linux_sll_linktype(proto);
+ /*NOTREACHED*/
break;
case DLT_SLIP:
@@ -1483,9 +1538,11 @@ gen_linktype(proto)
default:
return gen_false(); /* always false */
}
+ /*NOTREACHED*/
break;
case DLT_PPP:
+ case DLT_PPP_PPPD:
case DLT_PPP_SERIAL:
case DLT_PPP_ETHER:
/*
@@ -1669,6 +1726,7 @@ gen_linktype(proto)
#endif /* INET6 */
else
return gen_false();
+ /*NOTREACHED*/
break;
case DLT_ARCNET:
@@ -1689,7 +1747,7 @@ gen_linktype(proto)
#endif /* INET6 */
case ETHERTYPE_IP:
- b0 = gen_cmp(off_linktype, BPF_B,
+ b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP);
b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP_OLD);
@@ -1699,7 +1757,7 @@ gen_linktype(proto)
case ETHERTYPE_ARP:
b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP);
- b1 = gen_cmp(off_linktype, BPF_B,
+ b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP_OLD);
gen_or(b0, b1);
return (b1);
@@ -1712,6 +1770,7 @@ gen_linktype(proto)
return (gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ATALK));
}
+ /*NOTREACHED*/
break;
case DLT_LTALK:
@@ -1721,6 +1780,7 @@ gen_linktype(proto)
default:
return gen_false();
}
+ /*NOTREACHED*/
break;
case DLT_FRELAY:
@@ -1766,10 +1826,27 @@ gen_linktype(proto)
default:
return gen_false();
}
+ /*NOTREACHED*/
break;
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ /* just lets verify the magic number for now -
+ * on ATM we may have up to 6 different encapsulations on the wire
+ * and need a lot of heuristics to figure out that the payload
+ * might be;
+ *
+ * FIXME encapsulation specific BPF_ filters
+ */
+ return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+
case DLT_LINUX_IRDA:
- bpf_error("IrDA link-layer type filtering not implemented");
+ bpf_error("IrDA link-layer type filtering not implemented");
+
+ case DLT_DOCSIS:
+ bpf_error("DOCSIS link-layer type filtering not implemented");
}
/*
@@ -2504,7 +2581,7 @@ gen_dnhostop(addr, dir, base_off)
return b1;
case Q_ISO:
- bpf_error("ISO host filtering not implemented");
+ bpf_error("ISO host filtering not implemented");
default:
abort();
@@ -2978,91 +3055,91 @@ gen_proto_abbrev(proto)
break;
case Q_ISO:
- b1 = gen_linktype(LLCSAP_ISONS);
+ b1 = gen_linktype(LLCSAP_ISONS);
break;
case Q_ESIS:
- b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS:
- b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
- b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
- case Q_ISIS_LSP:
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ case Q_ISIS_LSP:
+ b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_SNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_CSNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_PSNP:
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_CLNP:
- b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
break;
case Q_STP:
- b1 = gen_linktype(LLCSAP_8021D);
+ b1 = gen_linktype(LLCSAP_8021D);
break;
case Q_IPX:
- b1 = gen_linktype(LLCSAP_IPX);
+ b1 = gen_linktype(LLCSAP_IPX);
break;
case Q_NETBEUI:
- b1 = gen_linktype(LLCSAP_NETBEUI);
+ b1 = gen_linktype(LLCSAP_NETBEUI);
break;
default:
@@ -3303,8 +3380,11 @@ lookup_proto(name, proto)
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);
+ if (v == PROTO_UNDEF) {
+ v = pcap_nametollc(name);
+ if (v == PROTO_UNDEF)
+ bpf_error("unknown ether proto '%s'", name);
+ }
break;
case Q_ISO:
@@ -3696,6 +3776,7 @@ gen_proto(v, proto, dir)
* XXX - what about SNAP-encapsulated frames?
*/
return gen_cmp(2, BPF_H, (0x03<<8) | v);
+ /*NOTREACHED*/
break;
case DLT_C_HDLC:
@@ -4136,6 +4217,7 @@ gen_mcode(s1, s2, masklen, q)
bpf_error("Mask syntax for networks only");
/* NOTREACHED */
}
+ /* NOTREACHED */
}
struct block *
@@ -4770,6 +4852,7 @@ gen_broadcast(proto)
return b2;
}
bpf_error("only link-layer/IP broadcast filters supported");
+ /* NOTREACHED */
}
/*
@@ -4986,6 +5069,7 @@ gen_multicast(proto)
#endif /* INET6 */
}
bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+ /* NOTREACHED */
}
/*
@@ -5036,6 +5120,31 @@ gen_inbound(dir)
(bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
break;
+ case DLT_PPP_PPPD:
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_cmp(0, BPF_B, PPP_PPPD_OUT);
+ } else {
+ /* match incoming packets */
+ b0 = gen_cmp(0, BPF_B, PPP_PPPD_IN);
+ }
+ break;
+
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ /* juniper flags (including direction) are stored
+ * the byte after the 3-byte magic number */
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_mcmp(3, BPF_B, 0, 0x01);
+ } else {
+ /* match incoming packets */
+ b0 = gen_mcmp(3, BPF_B, 1, 0x01);
+ }
+ break;
+
default:
bpf_error("inbound/outbound not supported on linktype %d",
linktype);
@@ -5064,7 +5173,7 @@ gen_pf_ifname(const char *ifname)
len-1);
/* NOTREACHED */
}
- b0 = gen_bcmp(off, strlen(ifname), ifname);
+ b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname);
return (b0);
}
@@ -5084,7 +5193,7 @@ gen_pf_ruleset(char *ruleset)
/* NOTREACHED */
}
b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset),
- strlen(ruleset), ruleset);
+ strlen(ruleset), (const u_char *)ruleset);
return (b0);
}
@@ -5240,7 +5349,80 @@ gen_vlan(vlan_num)
if (vlan_num >= 0) {
struct block *b1;
- b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num);
+ b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ return (b0);
+}
+
+/*
+ * support for MPLS
+ */
+struct block *
+gen_mpls(label_num)
+ int label_num;
+{
+ struct block *b0;
+
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the MPLS packet. This is somewhat of a kludge.
+ */
+ if (orig_nl == (u_int)-1) {
+ orig_linktype = off_linktype; /* save original values */
+ orig_nl = off_nl;
+ orig_nl_nosnap = off_nl_nosnap;
+
+ switch (linktype) {
+
+ case DLT_EN10MB:
+ off_linktype = 16;
+ off_nl_nosnap = 18;
+ off_nl = 18;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
+ break;
+
+ case DLT_PPP:
+ off_linktype = 6;
+ off_nl_nosnap = 8;
+ off_nl = 8;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST);
+ break;
+
+ case DLT_C_HDLC:
+ off_linktype = 6;
+ off_nl_nosnap = 8;
+ off_nl = 8;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
+ break;
+
+ /* FIXME add other DLT_s ...
+ * for Frame-Relay/and ATM this may get messy due to SNAP headers
+ * leave it for now */
+
+ default:
+ bpf_error("no MPLS support for data link type %d",
+ linktype);
+ b0 = NULL;
+ /*NOTREACHED*/
+ }
+ } else {
+ bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'");
+ b0 = NULL;
+ /*NOTREACHED*/
+ }
+
+ /* If a specific MPLS label is requested, check it */
+ if (label_num >= 0) {
+ struct block *b1;
+
+ label_num = label_num << 12; /* label is shifted 12 bits on the wire */
+ b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */
gen_and(b0, b1);
b0 = b1;
}
@@ -5425,15 +5607,15 @@ gen_msg_abbrev(type)
break;
case A_CALLPROCEED:
- b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
break;
case A_CONNECT:
b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
- break;
+ break;
case A_CONNECTACK:
- b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
break;
case A_RELEASE:
@@ -5441,7 +5623,7 @@ gen_msg_abbrev(type)
break;
case A_RELEASE_DONE:
- b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
break;
default:
@@ -5468,9 +5650,9 @@ gen_atmmulti_abbrev(type)
if (!is_atm)
bpf_error("'oamf4' supported only on raw ATM");
/* OAM F4 type */
- b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+ b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
- gen_or(b0, b1);
+ gen_or(b0, b1);
b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
gen_and(b0, b1);
break;
diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h
index 205b29d98a9c..83de011220c4 100644
--- a/contrib/libpcap/gencode.h
+++ b/contrib/libpcap/gencode.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.58.2.1 2004/03/28 21:45:31 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60 2004/06/16 08:20:30 hannes Exp $ (LBL)
*/
/*
@@ -273,6 +273,7 @@ struct block *gen_multicast(int);
struct block *gen_inbound(int);
struct block *gen_vlan(int);
+struct block *gen_mpls(int);
struct block *gen_atmfield_code(int atmfield, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse);
struct block *gen_atmtype_abbrev(int type);
diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y
index dc63e322a9f2..481718170038 100644
--- a/contrib/libpcap/grammar.y
+++ b/contrib/libpcap/grammar.y
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.79.2.3 2004/03/28 21:45:32 fenner Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86 2004/12/18 08:49:23 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -33,7 +33,6 @@ static const char rcsid[] _U_ =
#include <pcap-stdinc.h>
#else /* WIN32 */
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/socket.h>
#endif /* WIN32 */
@@ -49,7 +48,6 @@ struct rtentry;
#endif /* WIN32 */
#include <stdio.h>
-#include <strings.h>
#include "pcap-int.h"
@@ -128,7 +126,7 @@ pcap_parse()
%token LSH RSH
%token LEN
%token IPV6 ICMPV6 AH ESP
-%token VLAN
+%token VLAN MPLS
%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
%token STP
%token IPX
@@ -324,6 +322,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
| OUTBOUND { $$ = gen_inbound(1); }
| VLAN pnum { $$ = gen_vlan($2); }
| VLAN { $$ = gen_vlan(-1); }
+ | MPLS pnum { $$ = gen_mpls($2); }
+ | MPLS { $$ = gen_mpls(-1); }
| pfvar { $$ = $1; }
;
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c
index 43eafe7fb6fd..561781ab927b 100644
--- a/contrib/libpcap/inet.c
+++ b/contrib/libpcap/inet.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.1 2003/11/15 23:26:41 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66 2005/02/10 19:38:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -46,13 +46,14 @@ static const char rcsid[] _U_ =
#else /* WIN32 */
#include <sys/param.h>
+#ifndef MSDOS
#include <sys/file.h>
+#endif
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
-#include <sys/time.h> /* concession to AIX */
struct mbuf; /* Squelch compiler warnings on some platforms for */
struct rtentry; /* declarations in <net/if.h> */
@@ -66,17 +67,14 @@ struct rtentry; /* declarations in <net/if.h> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__BORLANDC__)
#include <unistd.h>
-#endif /* WIN32 */
+#endif /* !WIN32 && !__BORLANDC__ */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#else
#define INT_MAX 2147483647
#endif
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
#include "pcap-int.h"
@@ -132,10 +130,33 @@ int
add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
u_int flags, const char *description, char *errbuf)
{
+ pcap_t *p;
pcap_if_t *curdev, *prevdev, *nextdev;
int this_instance;
/*
+ * Can we open this interface for live capture?
+ *
+ * We do this check so that interfaces that ae supplied
+ * by the interface enumeration mechanism we're using
+ * but that don't support packet capture aren't included
+ * in the list. An example of this is loopback interfaces
+ * on Solaris; we don't just omit loopback interfaces
+ * becaue you *can* capture on loopback interfaces on some
+ * OSes.
+ */
+ p = pcap_open_live(name, 68, 0, 0, errbuf);
+ if (p == NULL) {
+ /*
+ * No. Don't bother including it.
+ * Don't treat this as an error, though.
+ */
+ *curdev_ret = NULL;
+ return (0);
+ }
+ pcap_close(p);
+
+ /*
* Is there already an entry in the list for this interface?
*/
for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
@@ -282,7 +303,7 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
}
int
-add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
struct sockaddr *addr, size_t addr_size,
struct sockaddr *netmask, size_t netmask_size,
struct sockaddr *broadaddr, size_t broadaddr_size,
@@ -394,7 +415,7 @@ add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
}
int
-pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
+pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
const char *description, char *errbuf)
{
pcap_if_t *curdev;
@@ -450,7 +471,7 @@ pcap_freealldevs(pcap_if_t *alldevs)
}
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
/*
* Return the name of a network interface attached to the system, or NULL
@@ -574,7 +595,7 @@ pcap_lookupnet(device, netp, maskp, errbuf)
return (0);
}
-#else /* WIN32 */
+#elif defined(WIN32)
/*
* Return the name of a network interface attached to the system, or NULL
@@ -597,9 +618,10 @@ pcap_lookupdev(errbuf)
ULONG NameLength = 8192;
static char AdaptersName[8192];
- PacketGetAdapterNames(AdaptersName,&NameLength);
-
- return (AdaptersName);
+ if (PacketGetAdapterNames(AdaptersName,&NameLength) )
+ return (AdaptersName);
+ else
+ return NULL;
} else {
/*
* Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
@@ -617,7 +639,15 @@ pcap_lookupdev(errbuf)
return NULL;
}
- PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength);
+ if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
+ {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "PacketGetAdapterNames: %s",
+ pcap_win32strerror());
+ free(TAdaptersName);
+ return NULL;
+ }
+
tAstr = (char*)TAdaptersName;
tUstr = (WCHAR*)AdaptersName;
@@ -646,6 +676,7 @@ pcap_lookupdev(errbuf)
tAstr += strlen(tAstr) + 1;
}
+ free(TAdaptersName);
return (char *)(AdaptersName);
}
}
@@ -653,7 +684,7 @@ pcap_lookupdev(errbuf)
int
pcap_lookupnet(device, netp, maskp, errbuf)
- const register char *device;
+ register const char *device;
register bpf_u_int32 *netp, *maskp;
register char *errbuf;
{
@@ -690,4 +721,4 @@ pcap_lookupnet(device, netp, maskp, errbuf)
return (0);
}
-#endif /* WIN32 */
+#endif /* !WIN32 && !MSDOS */
diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c
index f9d6a4f5075b..ac5653930c6e 100644
--- a/contrib/libpcap/nametoaddr.c
+++ b/contrib/libpcap/nametoaddr.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.68.2.3 2003/11/19 18:13:48 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77 2005/03/27 22:26:25 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -53,12 +53,19 @@ static const char rcsid[] _U_ =
#ifndef WIN32
#ifdef HAVE_ETHER_HOSTTON
+/*
+ * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
+ * ether_hostton()?
+ */
#ifdef HAVE_NETINET_IF_ETHER_H
struct mbuf; /* Squelch compiler warnings on some platforms for */
struct rtentry; /* declarations in <net/if.h> */
#include <net/if.h> /* for "struct ifnet" in "struct arpcom" on Solaris */
#include <netinet/if_ether.h>
#endif /* HAVE_NETINET_IF_ETHER_H */
+#ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+#include <netinet/ether.h>
+#endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
#endif /* HAVE_ETHER_HOSTTON */
#include <arpa/inet.h>
#include <netdb.h>
@@ -124,6 +131,7 @@ pcap_nametoaddrinfo(const char *name)
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; /*not really*/
+ hints.ai_protocol = IPPROTO_TCP; /*not really*/
error = getaddrinfo(name, NULL, &hints, &res);
if (error)
return NULL;
@@ -267,6 +275,30 @@ pcap_nametoeproto(const char *s)
return PROTO_UNDEF;
}
+#include "llc.h"
+
+/* Static data base of LLC values. */
+static struct eproto llc_db[] = {
+ { "iso", LLCSAP_ISONS },
+ { "stp", LLCSAP_8021D },
+ { "ipx", LLCSAP_IPX },
+ { "netbeui", LLCSAP_NETBEUI },
+ { (char *)0, 0 }
+};
+
+int
+pcap_nametollc(const char *s)
+{
+ struct eproto *p = llc_db;
+
+ while (p->s != 0) {
+ if (strcmp(p->s, s) == 0)
+ return p->p;
+ p += 1;
+ }
+ return PROTO_UNDEF;
+}
+
/* Hex digit to integer. */
static inline int
xdtoi(c)
@@ -380,18 +412,8 @@ pcap_ether_hostton(const char *name)
}
#else
-/*
- * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files,
- * for those OS versions that don't declare it, rather than being declared
- * here? That way, for example, we could declare it on FreeBSD 2.x (which
- * doesn't declare it), but not on FreeBSD 3.x (which declares it like
- * this) or FreeBSD 4.x (which declares it with its first argument as
- * "const char *", so no matter how we declare it here, it'll fail to
- * compile on one of 3.x or 4.x).
- */
-#if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__) && \
- !defined(_UNICOSMP)
-extern int ether_hostton(char *, struct ether_addr *);
+#if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON
+extern int ether_hostton(const char *, struct ether_addr *);
#endif
/* Use the os supplied routines */
diff --git a/contrib/libpcap/optimize.c b/contrib/libpcap/optimize.c
index ea9f50d2f099..173bc55406c1 100644
--- a/contrib/libpcap/optimize.c
+++ b/contrib/libpcap/optimize.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.76.2.3 2003/12/22 00:26:36 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.85 2005/04/04 08:42:18 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -32,6 +32,7 @@ static const char rcsid[] _U_ =
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
+#include <string.h>
#include <errno.h>
@@ -47,12 +48,26 @@ static const char rcsid[] _U_ =
extern int dflag;
#endif
-#define A_ATOM BPF_MEMWORDS
-#define X_ATOM (BPF_MEMWORDS+1)
+#if defined(MSDOS) && !defined(__DJGPP__)
+extern int _w32_ffs (int mask);
+#define ffs _w32_ffs
+#endif
+/*
+ * Represents a deleted instruction.
+ */
#define NOP -1
/*
+ * Register numbers for use-def values.
+ * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory
+ * location. A_ATOM is the accumulator and X_ATOM is the index
+ * register.
+ */
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+/*
* This define is used to represent *both* the accumulator and
* x register in use-def computations.
* Currently, the use-def code assumes only one definition per instruction.
@@ -419,6 +434,17 @@ atomdef(s)
return -1;
}
+/*
+ * Compute the sets of registers used, defined, and killed by 'b'.
+ *
+ * "Used" means that a statement in 'b' uses the register before any
+ * statement in 'b' defines it, i.e. it uses the value left in
+ * that register by a predecessor block of this block.
+ * "Defined" means that a statement in 'b' defines it.
+ * "Killed" means that a statement in 'b' defines it before any
+ * statement in 'b' uses it, i.e. it kills the value left in that
+ * register by a predecessor block of this block.
+ */
static void
compute_local_ud(b)
struct block *b;
@@ -452,8 +478,26 @@ compute_local_ud(b)
def |= ATOMMASK(atom);
}
}
- if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP)
- use |= ATOMMASK(A_ATOM);
+ if (BPF_CLASS(b->s.code) == BPF_JMP) {
+ /*
+ * XXX - what about RET?
+ */
+ atom = atomuse(&b->s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ if (!ATOMELEM(def, X_ATOM))
+ use |= ATOMMASK(X_ATOM);
+ if (!ATOMELEM(def, A_ATOM))
+ use |= ATOMMASK(A_ATOM);
+ }
+ else if (atom < N_ATOMS) {
+ if (!ATOMELEM(def, atom))
+ use |= ATOMMASK(atom);
+ }
+ else
+ abort();
+ }
+ }
b->def = def;
b->kill = kill;
@@ -664,13 +708,21 @@ opt_peep(b)
return;
last = s;
- while (1) {
+ for (/*empty*/; /*empty*/; s = next) {
+ /*
+ * Skip over nops.
+ */
s = this_op(s);
if (s == 0)
- break;
+ break; /* nothing left in the block */
+
+ /*
+ * Find the next real instruction after that one
+ * (skipping nops).
+ */
next = this_op(s->next);
if (next == 0)
- break;
+ break; /* no next instruction */
last = next;
/*
@@ -707,29 +759,38 @@ opt_peep(b)
* any local dependencies.
*/
if (ATOMELEM(b->out_use, X_ATOM))
- break;
+ continue;
+ /*
+ * Check that the instruction following the ldi
+ * is an addx, or it's an ldxms with an addx
+ * following it (with 0 or more nops between the
+ * ldxms and addx).
+ */
if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
add = next;
else
add = this_op(next->next);
if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
- break;
+ continue;
+ /*
+ * Check that a tax follows that (with 0 or more
+ * nops between them).
+ */
tax = this_op(add->next);
if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
- break;
+ continue;
+ /*
+ * Check that an ild follows that (with 0 or more
+ * nops between them).
+ */
ild = this_op(tax->next);
if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
BPF_MODE(ild->s.code) != BPF_IND)
- break;
+ continue;
/*
- * 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}
@@ -746,6 +807,16 @@ opt_peep(b)
* (007) nop
* (008) ild [x+2]
*
+ * XXX We need to check that X is not
+ * subsequently used, because we want to change
+ * what'll be in it after this sequence.
+ *
+ * We know we can eliminate the accumulator
+ * modifications earlier in the sequence since
+ * it is defined by the last stmt of this sequence
+ * (i.e., the last statement of the sequence loads
+ * a value into the accumulator, so we can eliminate
+ * earlier operations on the accumulator).
*/
ild->s.k += s->s.k;
s->s.code = NOP;
@@ -753,19 +824,29 @@ opt_peep(b)
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 the comparison at the end of a block is an equality
+ * comparison against a constant, and nobody uses the value
+ * we leave in the A register at the end of a block, and
+ * the operation preceding the comparison is an arithmetic
+ * operation, we can sometime optimize it away.
*/
- if (BPF_OP(b->s.code) == BPF_JEQ) {
- if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
- !ATOMELEM(b->out_use, A_ATOM)) {
+ if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
+ !ATOMELEM(b->out_use, A_ATOM)) {
+ /*
+ * We can optimize away certain subtractions of the
+ * X register.
+ */
+ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
val = b->val[X_ATOM];
if (vmap[val].is_const) {
/*
+ * If we have a subtract to do a comparison,
+ * and the X register is a known constant,
+ * we can merge this value into the
+ * comparison:
+ *
* sub x -> nop
* jeq #y jeq #(x+y)
*/
@@ -774,37 +855,45 @@ opt_peep(b)
done = 0;
} else if (b->s.k == 0) {
/*
- * sub #x -> nop
- * jeq #0 jeq #x
+ * If the X register isn't a constant,
+ * and the comparison in the test is
+ * against 0, we can compare with the
+ * X register, instead:
+ *
+ * sub x -> nop
+ * jeq #0 jeq x
*/
last->s.code = NOP;
- b->s.code = BPF_CLASS(b->s.code) |
- BPF_OP(b->s.code) | BPF_X;
+ b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
done = 0;
}
}
/*
- * Likewise, a constant subtract can be simplified.
+ * Likewise, a constant subtract can be simplified:
+ *
+ * sub #x -> nop
+ * jeq #y -> jeq #(x+y)
*/
- else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
- !ATOMELEM(b->out_use, A_ATOM)) {
-
+ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
last->s.code = NOP;
b->s.k += last->s.k;
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);
+ /*
+ * And, similarly, a constant AND can be simplified
+ * if we're testing against 0, i.e.:
+ *
+ * and #k nop
+ * jeq #0 -> jset #k
+ */
+ else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+ b->s.k == 0) {
+ b->s.k = last->s.k;
+ b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+ last->s.code = NOP;
+ done = 0;
+ opt_not(b);
+ }
}
/*
* jset #0 -> never
@@ -1102,7 +1191,7 @@ opt_blk(b, do_stmts)
struct slist *s;
struct edge *p;
int i;
- bpf_int32 aval;
+ bpf_int32 aval, xval;
#if 0
for (s = b->stmts; s && s->next; s = s->next)
@@ -1114,16 +1203,30 @@ opt_blk(b, do_stmts)
/*
* 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)
+ if (p == 0) {
+ /*
+ * We have no predecessors, so everything is undefined
+ * upon entry to this block.
+ */
memset((char *)b->val, 0, sizeof(b->val));
- else {
+ } else {
+ /*
+ * Inherit values from our predecessors.
+ *
+ * First, get the values from the predecessor along the
+ * first edge leading to this node.
+ */
memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
+ /*
+ * Now look at all the other nodes leading to this node.
+ * If, for the predecessor along that edge, a register
+ * has a different value from the one we have (i.e.,
+ * control paths are merging, and the merging paths
+ * assign different values to that register), give the
+ * register the undefined value of 0.
+ */
while ((p = p->next) != NULL) {
for (i = 0; i < N_ATOMS; ++i)
if (b->val[i] != p->pred->val[i])
@@ -1131,17 +1234,36 @@ opt_blk(b, do_stmts)
}
}
aval = b->val[A_ATOM];
+ xval = b->val[X_ATOM];
for (s = b->stmts; s; s = s->next)
opt_stmt(&s->s, b->val, do_stmts);
/*
* This is a special case: if we don't use anything from this
- * block, and we load the accumulator with value that is
- * already there, or if this block is a return,
+ * block, and we load the accumulator or index register with a
+ * value that is already there, or if this block is a return,
* eliminate all the statements.
+ *
+ * XXX - what if it does a store?
+ *
+ * XXX - why does it matter whether we use anything from this
+ * block? If the accumulator or index register doesn't change
+ * its value, isn't that OK even if we use that value?
+ *
+ * XXX - if we load the accumulator with a different value,
+ * and the block ends with a conditional branch, we obviously
+ * can't eliminate it, as the branch depends on that value.
+ * For the index register, the conditional branch only depends
+ * on the index register value if the test is against the index
+ * register value rather than a constant; if nothing uses the
+ * value we put into the index register, and we're not testing
+ * against the index register's value, and there aren't any
+ * other problems that would keep us from eliminating this
+ * block, can we eliminate it?
*/
if (do_stmts &&
- ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) ||
+ ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval &&
+ xval != 0 && b->val[X_ATOM] == xval) ||
BPF_CLASS(b->s.code) == BPF_RET)) {
if (b->stmts != 0) {
b->stmts = 0;
@@ -1212,9 +1334,9 @@ fold_edge(child, ep)
if (oval0 == oval1)
/*
- * The operands are identical, so the
- * result is true if a true branch was
- * taken to get here, otherwise false.
+ * The operands of the branch instructions are
+ * identical, so the result is true if a true
+ * branch was taken to get here, otherwise false.
*/
return sense ? JT(child) : JF(child);
@@ -1222,8 +1344,16 @@ fold_edge(child, ep)
/*
* 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.
+ * comparison with a constant.
+ *
+ * I.e., if we came down the true branch, and the branch
+ * was an equality comparison with a constant, we know the
+ * accumulator contains that constant. If we came down
+ * the false branch, or the comparison wasn't with a
+ * constant, we don't know what was in the accumulator.
+ *
+ * We rely on the fact that distinct constants have distinct
+ * value numbers.
*/
return JF(child);
diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c
index 5b0eab6528c3..085f181dd96e 100644
--- a/contrib/libpcap/pcap-bpf.c
+++ b/contrib/libpcap/pcap-bpf.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.67.2.4 2003/11/22 00:06:28 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86 2005/02/26 21:58:05 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -142,7 +142,11 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
int cc;
int n = 0;
register u_char *bp, *ep;
+ u_char *datap;
struct bpf_insn *fcode;
+#ifdef PCAP_FDDIPAD
+ register int pad;
+#endif
fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns;
again:
@@ -224,6 +228,9 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
*/
#define bhp ((struct bpf_hdr *)bp)
ep = bp + cc;
+#ifdef PCAP_FDDIPAD
+ pad = p->fddipad;
+#endif
while (bp < ep) {
register int caplen, hdrlen;
@@ -249,31 +256,48 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
+ datap = bp + hdrlen;
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now.
+ *
+#ifdef PCAP_FDDIPAD
+ * Note: the filter code was generated assuming
+ * that p->fddipad was the amount of padding
+ * before the header, as that's what's required
+ * in the kernel, so we run the filter before
+ * skipping that padding.
+#endif
*/
if (fcode == NULL ||
- bpf_filter(fcode, bp + hdrlen, bhp->bh_datalen, caplen)) {
+ bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) {
+ struct pcap_pkthdr pkthdr;
+
+ pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
#ifdef _AIX
/*
* AIX's BPF returns seconds/nanoseconds time
* stamps, not seconds/microseconds time stamps.
- *
- * XXX - I'm guessing here that it's a "struct
- * timestamp"; if not, this code won't compile,
- * but, if not, you want to send us a bug report
- * and fall back on using DLPI. It's not as if
- * BPF used to work right on AIX before this
- * change; this change attempts to fix the fact
- * that it didn't....
*/
- bhp->bh_tstamp.tv_usec = bhp->bh_tstamp.tv_usec/1000;
+ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000;
+#else
+ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
#endif
- /*
- * XXX A bpf_hdr matches a pcap_pkthdr.
- */
- (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+#ifdef PCAP_FDDIPAD
+ if (caplen > pad)
+ pkthdr.caplen = caplen - pad;
+ else
+ pkthdr.caplen = 0;
+ if (bhp->bh_datalen > pad)
+ pkthdr.len = bhp->bh_datalen - pad;
+ else
+ pkthdr.len = 0;
+ datap += pad;
+#else
+ pkthdr.caplen = caplen;
+ pkthdr.len = bhp->bh_datalen;
+#endif
+ (*callback)(user, &pkthdr, datap);
bp += BPF_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && cnt > 0) {
p->bp = bp;
@@ -292,6 +316,55 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
+static int
+pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ ret = write(p->fd, buf, size);
+#ifdef __APPLE__
+ if (ret == -1 && errno == EAFNOSUPPORT) {
+ /*
+ * In Mac OS X, there's a bug wherein setting the
+ * BIOCSHDRCMPLT flag causes writes to fail; see,
+ * for example:
+ *
+ * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
+ *
+ * So, if, on OS X, we get EAFNOSUPPORT from the write, we
+ * assume it's due to that bug, and turn off that flag
+ * and try again. If we succeed, it either means that
+ * somebody applied the fix from that URL, or other patches
+ * for that bug from
+ *
+ * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/
+ *
+ * and are running a Darwin kernel with those fixes, or
+ * that Apple fixed the problem in some OS X release.
+ */
+ u_int spoof_eth_src = 0;
+
+ if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+ (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "send: can't turn off BIOCSHDRCMPLT: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+
+ /*
+ * Now try the write again.
+ */
+ ret = write(p->fd, buf, size);
+ }
+#endif /* __APPLE__ */
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
#ifdef _AIX
static int
bpf_odminit(char *errbuf)
@@ -467,7 +540,23 @@ bpf_open(pcap_t *p, char *errbuf)
*/
do {
(void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
- fd = open(device, O_RDONLY);
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ fd = open(device, O_RDWR);
+ if (fd == -1 && errno == EACCES)
+ fd = open(device, O_RDONLY);
} while (fd < 0 && errno == EBUSY);
/*
@@ -480,25 +569,14 @@ bpf_open(pcap_t *p, char *errbuf)
return (fd);
}
-static void
-pcap_close_bpf(pcap_t *p)
-{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
-}
-
/*
- * XXX - on AIX, IBM's tcpdump (and perhaps the incompatible-with-everybody-
- * else's libpcap in AIX 5.1) appears to forcibly load the BPF driver
- * if it's not already loaded, and to create the BPF devices if they
- * don't exist.
- *
- * It'd be nice if we could do the same, although the code to do so
- * might be version-dependent, alas (the way to do it isn't necessarily
- * documented).
+ * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
*/
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS 143
+#endif
+
pcap_t *
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
char *ebuf)
@@ -509,8 +587,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifdef BIOCGDLTLIST
struct bpf_dltlist bdl;
#endif
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+ u_int spoof_eth_src = 1;
+#endif
u_int v;
pcap_t *p;
+ struct bpf_insn total_insn;
+ struct bpf_program total_prog;
struct utsname osinfo;
#ifdef HAVE_DAG_API
@@ -644,6 +727,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
break;
}
#endif
+#ifdef PCAP_FDDIPAD
+ if (v == DLT_FDDI)
+ p->fddipad = PCAP_FDDIPAD:
+ else
+ p->fddipad = 0;
+#endif
p->linktype = v;
#ifdef BIOCGDLTLIST
@@ -653,7 +742,10 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* not fatal; we just don't get to use the feature later.
*/
if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
- bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * bdl.bfl_len);
+ u_int i;
+ int is_ethernet;
+
+ bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * bdl.bfl_len + 1);
if (bdl.bfl_list == NULL) {
(void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
@@ -663,9 +755,44 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
+ free(bdl.bfl_list);
goto bad;
}
+ /*
+ * OK, for real Ethernet devices, add DLT_DOCSIS to the
+ * list, so that an application can let you choose it,
+ * in case you're capturing DOCSIS traffic that a Cisco
+ * Cable Modem Termination System is putting out onto
+ * an Ethernet (it doesn't put an Ethernet header onto
+ * the wire, it puts raw DOCSIS frames out on the wire
+ * inside the low-level Ethernet framing).
+ *
+ * A "real Ethernet device" is defined here as a device
+ * that has a link-layer type of DLT_EN10MB and that has
+ * no alternate link-layer types; that's done to exclude
+ * 802.11 interfaces (which might or might not be the
+ * right thing to do, but I suspect it is - Ethernet <->
+ * 802.11 bridges would probably badly mishandle frames
+ * that don't have Ethernet headers).
+ */
+ if (p->linktype == DLT_EN10MB) {
+ is_ethernet = 1;
+ for (i = 0; i < bdl.bfl_len; i++) {
+ if (bdl.bfl_list[i] != DLT_EN10MB) {
+ is_ethernet = 0;
+ break;
+ }
+ }
+ if (is_ethernet) {
+ /*
+ * We reserved one more slot at the end of
+ * the list.
+ */
+ bdl.bfl_list[bdl.bfl_len] = DLT_DOCSIS;
+ bdl.bfl_len++;
+ }
+ }
p->dlt_count = bdl.bfl_len;
p->dlt_list = bdl.bfl_list;
} else {
@@ -677,6 +804,42 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
#endif
+ /*
+ * If this is an Ethernet device, and we don't have a DLT_ list,
+ * give it a list with DLT_EN10MB and DLT_DOCSIS. (That'd give
+ * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to
+ * do, but there's not much we can do about that without finding
+ * some other way of determining whether it's an Ethernet or 802.11
+ * device.)
+ */
+ if (p->linktype == DLT_EN10MB && p->dlt_count == 0) {
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ }
+
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+ /*
+ * Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so
+ * the link-layer source address isn't forcibly overwritten.
+ * (Should we ignore errors? Should we do this only if
+ * we're open for writing?)
+ *
+ * XXX - I seem to remember some packet-sending bug in some
+ * BSDs - check CVS log for "bpf.c"?
+ */
+ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "BIOCSHDRCMPLT: %s", pcap_strerror(errno));
+ goto bad;
+ }
+#endif
/* set timeout */
if (to_ms != 0) {
/*
@@ -778,6 +941,28 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif
/*
+ * If there's no filter program installed, there's
+ * no indication to the kernel of what the snapshot
+ * length should be, so no snapshotting is done.
+ *
+ * Therefore, when we open the device, we install
+ * an "accept everything" filter with the specified
+ * snapshot length.
+ */
+ total_insn.code = (u_short)(BPF_RET | BPF_K);
+ total_insn.jt = 0;
+ total_insn.jf = 0;
+ total_insn.k = snaplen;
+
+ total_prog.bf_len = 1;
+ total_prog.bf_insns = &total_insn;
+ if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ pcap_strerror(errno));
+ goto bad;
+ }
+
+ /*
* On most BPF platforms, either you can do a "select()" or
* "poll()" on a BPF file descriptor and it works correctly,
* or you can do it and it will return "readable" if the
@@ -818,8 +1003,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* We can check what OS this is.
*/
if (strcmp(osinfo.sysname, "FreeBSD") == 0 &&
- (strcmp(osinfo.release, "4.3") == 0 ||
- strcmp(osinfo.release, "4.4") == 0))
+ (strncmp(osinfo.release, "4.3-", 4) == 0 ||
+ strncmp(osinfo.release, "4.4-", 4) == 0))
p->selectable_fd = -1;
else
p->selectable_fd = p->fd;
@@ -832,20 +1017,19 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
p->read_op = pcap_read_bpf;
+ p->inject_op = pcap_inject_bpf;
p->setfilter_op = pcap_setfilter_bpf;
p->set_datalink_op = pcap_set_datalink_bpf;
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_bpf;
- p->close_op = pcap_close_bpf;
+ p->close_op = pcap_close_common;
return (p);
bad:
(void)close(fd);
-#ifdef BIOCGDLTLIST
- if (bdl.bfl_list != NULL)
- free(bdl.bfl_list);
-#endif
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
return (NULL);
}
@@ -893,6 +1077,14 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
return (-1);
}
p->md.use_bpf = 1; /* filtering in the kernel */
+
+ /*
+ * Discard any previously-received packets, as they might have
+ * passed whatever filter was formerly in effect, but might
+ * not pass this filter (BIOCSETF discards packets buffered
+ * in the kernel, so you can lose packets in any case).
+ */
+ p->cc = 0;
return (0);
}
diff --git a/contrib/libpcap/pcap-bpf.h b/contrib/libpcap/pcap-bpf.h
index 80d589df1345..deb15ac61b5b 100644
--- a/contrib/libpcap/pcap-bpf.h
+++ b/contrib/libpcap/pcap-bpf.h
@@ -37,7 +37,7 @@
*
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.9.2.9 2004/03/28 21:45:32 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34 2005/02/08 20:03:15 guy Exp $ (LBL)
*/
/*
@@ -60,8 +60,13 @@ extern "C" {
/* BSD style release date */
#define BPF_RELEASE 199606
+#ifdef MSDOS /* must be 32-bit */
+typedef long bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
typedef int bpf_int32;
typedef u_int bpf_u_int32;
+#endif
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
@@ -121,7 +126,7 @@ struct bpf_version {
* These are the types that are the same on all platforms, and that
* have been defined by <net/bpf.h> for ages.
*/
-#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
#define DLT_AX25 3 /* Amateur Radio AX.25 */
@@ -175,6 +180,12 @@ struct bpf_version {
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
* These values are defined by NetBSD; other platforms should refrain from
* using them for other purposes, so that NetBSD savefiles with link
* types of 50 or 51 can be read as this type on all platforms.
@@ -350,10 +361,11 @@ struct bpf_version {
#define DLT_AURORA 126 /* Xilinx Aurora link layer */
/*
- * BSD header for 802.11 plus a number of bits of link-layer information
- * including radio information.
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
*/
-#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus BSD radio header */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
/*
* Reserved for the TZSP encapsulation, as per request from
@@ -415,7 +427,7 @@ struct bpf_version {
*/
/*
- * Reserved for DOCSIS MAC frames.
+ * DOCSIS MAC frames.
*/
#define DLT_DOCSIS 143
@@ -491,8 +503,8 @@ struct bpf_version {
*
* http://www.shaftnet.org/~pizza/software/capturefrm.txt
*
- * but could and arguably should also be used by non-AVS Linux
- * 802.11 drivers; that may happen in the future.
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
*/
#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
@@ -505,6 +517,70 @@ struct bpf_version {
#define DLT_JUNIPER_MONITOR 164
/*
+ * Reserved for BACnet MS/TP.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
* The instruction encodings.
*/
/* instruction classes */
diff --git a/contrib/libpcap/pcap-dag.c b/contrib/libpcap/pcap-dag.c
index 67ffaa7a3559..a30f970564d0 100644
--- a/contrib/libpcap/pcap-dag.c
+++ b/contrib/libpcap/pcap-dag.c
@@ -9,27 +9,13 @@
* is not defined then nothing is altered - the dag_ functions will be
* called as required from their pcap-linux/bpf equivalents.
*
- * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
- *
- * Modifications:
- * 2003 May - Jesper Peterson <support@endace.com>
- * Code shuffled around to suit fad-xxx.c structure
- * Added atexit() handler to stop DAG if application is too lazy
- * 2003 September - Koryn Grant <koryn@endace.com>
- * Added support for nonblocking operation.
- * Added support for processing more than a single packet in pcap_dispatch().
- * Fixed bug in loss counter code.
- * Improved portability of loss counter code (e.g. use UINT_MAX instead of 0xffff).
- * Removed unused local variables.
- * Added required headers (ctype.h, limits.h, unistd.h, netinet/in.h).
- * 2003 October - Koryn Grant <koryn@endace.com.>
- * Changed semantics to match those of standard pcap on linux.
- * - packets rejected by the filter are not counted.
+ * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
+ * Modifications: Jesper Peterson, Koryn Grant <support@endace.com>
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.10.2.4 2003/11/21 10:20:45 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21 2005/04/03 23:56:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -55,17 +41,25 @@ struct mbuf; /* Squelch compiler warnings on some platforms for */
struct rtentry; /* declarations in <net/if.h> */
#include <net/if.h>
-#include <dagnew.h>
-#include <dagapi.h>
+#include "dagnew.h"
+#include "dagapi.h"
#define MIN_DAG_SNAPLEN 12
#define MAX_DAG_SNAPLEN 2040
-#define ATM_SNAPLEN 48
+#define ATM_CELL_SIZE 52
+#define ATM_HDR_SIZE 4
+
+/* SunATM pseudo header */
+struct sunatm_hdr {
+ unsigned char flags; /* destination and traffic type */
+ unsigned char vpi; /* VPI */
+ unsigned short vci; /* VCI */
+};
typedef struct pcap_dag_node {
- struct pcap_dag_node *next;
- pcap_t *p;
- pid_t pid;
+ struct pcap_dag_node *next;
+ pcap_t *p;
+ pid_t pid;
} pcap_dag_node_t;
static pcap_dag_node_t *pcap_dags = NULL;
@@ -103,22 +97,22 @@ static int dag_set_datalink(pcap_t *p, int dlt);
static int dag_get_datalink(pcap_t *p);
static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
-static void delete_pcap_dag(pcap_t *p) {
- pcap_dag_node_t *curr = NULL, *prev = NULL;
-
- for (prev = NULL, curr = pcap_dags;
- curr != NULL && curr->p != p;
- prev = curr, curr = curr->next) {
- /* empty */
- }
-
- if (curr != NULL && curr->p == p) {
- if (prev != NULL) {
- prev->next = curr->next;
- } else {
- pcap_dags = curr->next;
- }
- }
+static void
+delete_pcap_dag(pcap_t *p)
+{
+ pcap_dag_node_t *curr = NULL, *prev = NULL;
+
+ for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
+ /* empty */
+ }
+
+ if (curr != NULL && curr->p == p) {
+ if (prev != NULL) {
+ prev->next = curr->next;
+ } else {
+ pcap_dags = curr->next;
+ }
+ }
}
/*
@@ -126,58 +120,64 @@ static void delete_pcap_dag(pcap_t *p) {
* in the pcap_t structure, and closes the file descriptor for the DAG card.
*/
-static void dag_platform_close(pcap_t *p) {
+static void
+dag_platform_close(pcap_t *p)
+{
#ifdef linux
- if (p != NULL && p->md.device != NULL) {
- if(dag_stop(p->fd) < 0)
- fprintf(stderr,"dag_stop %s: %s\n", p->md.device, strerror(errno));
- if(dag_close(p->fd) < 0)
- fprintf(stderr,"dag_close %s: %s\n", p->md.device, strerror(errno));
-
- free(p->md.device);
- }
+ if (p != NULL && p->md.device != NULL) {
+ if(dag_stop(p->fd) < 0)
+ fprintf(stderr,"dag_stop %s: %s\n", p->md.device, strerror(errno));
+ if(dag_close(p->fd) < 0)
+ fprintf(stderr,"dag_close %s: %s\n", p->md.device, strerror(errno));
+
+ free(p->md.device);
+ }
#else
- if (p != NULL) {
- if(dag_stop(p->fd) < 0)
- fprintf(stderr,"dag_stop: %s\n", strerror(errno));
- if(dag_close(p->fd) < 0)
- fprintf(stderr,"dag_close: %s\n", strerror(errno));
- }
+ if (p != NULL) {
+ if(dag_stop(p->fd) < 0)
+ fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+ if(dag_close(p->fd) < 0)
+ fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ }
#endif
- delete_pcap_dag(p);
- /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
+ delete_pcap_dag(p);
+ /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
}
-static void atexit_handler(void) {
- while (pcap_dags != NULL) {
- if (pcap_dags->pid == getpid()) {
- dag_platform_close(pcap_dags->p);
- } else {
- delete_pcap_dag(pcap_dags->p);
- }
- }
+static void
+atexit_handler(void)
+{
+ while (pcap_dags != NULL) {
+ if (pcap_dags->pid == getpid()) {
+ dag_platform_close(pcap_dags->p);
+ } else {
+ delete_pcap_dag(pcap_dags->p);
+ }
+ }
}
-static int new_pcap_dag(pcap_t *p) {
- pcap_dag_node_t *node = NULL;
+static int
+new_pcap_dag(pcap_t *p)
+{
+ pcap_dag_node_t *node = NULL;
- if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
- return -1;
- }
+ if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
+ return -1;
+ }
- if (!atexit_handler_installed) {
- atexit(atexit_handler);
- atexit_handler_installed = 1;
- }
+ if (!atexit_handler_installed) {
+ atexit(atexit_handler);
+ atexit_handler_installed = 1;
+ }
- node->next = pcap_dags;
- node->p = p;
- node->pid = getpid();
+ node->next = pcap_dags;
+ node->p = p;
+ node->pid = getpid();
- pcap_dags = node;
+ pcap_dags = node;
- return 0;
+ return 0;
}
/*
@@ -185,7 +185,9 @@ static int new_pcap_dag(pcap_t *p) {
* for each of them. Returns the number of packets handled, -1 if an
* error occured, or -2 if we were told to break out of the loop.
*/
-static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
+static int
+dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
unsigned int processed = 0;
int flags = p->md.dag_offset_flags;
unsigned int nonblocking = flags & DAGF_NONBLOCK;
@@ -209,13 +211,13 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
}
p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
- if ((p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) && nonblocking)
+ if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
{
/* Pcap is configured to process only available packets, and there aren't any. */
return 0;
}
}
-
+
/* Process the packets. */
while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
@@ -240,54 +242,59 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
return -2;
}
- if (IS_BIGENDIAN())
- {
- rlen = header->rlen;
- }
- else
- {
rlen = ntohs(header->rlen);
+ if (rlen < dag_record_size)
+ {
+ strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
+ return -1;
}
p->md.dag_mem_bottom += rlen;
switch(header->type) {
+ case TYPE_AAL5:
case TYPE_ATM:
- packet_len = ATM_SNAPLEN;
- caplen = ATM_SNAPLEN;
- dp += 4;
+ if (header->type == TYPE_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ } else {
+ caplen = packet_len = ATM_CELL_SIZE;
+ }
+ if (p->linktype == DLT_SUNATM) {
+ struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
+ unsigned long rawatm;
+
+ rawatm = ntohl(*((unsigned long *)dp));
+ sunatm->vci = htons((rawatm >> 4) & 0xffff);
+ sunatm->vpi = (rawatm >> 20) & 0x00ff;
+ sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
+ ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
+ ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
+ ((dp[ATM_HDR_SIZE] == 0xaa &&
+ dp[ATM_HDR_SIZE+1] == 0xaa &&
+ dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
+
+ } else {
+ packet_len -= ATM_HDR_SIZE;
+ caplen -= ATM_HDR_SIZE;
+ dp += ATM_HDR_SIZE;
+ }
break;
case TYPE_ETH:
- if (IS_BIGENDIAN())
- {
- packet_len = header->wlen;
- }
- else
- {
packet_len = ntohs(header->wlen);
- }
packet_len -= (p->md.dag_fcs_bits >> 3);
caplen = rlen - dag_record_size - 2;
- if (caplen > packet_len)
- {
+ if (caplen > packet_len) {
caplen = packet_len;
}
dp += 2;
break;
case TYPE_HDLC_POS:
- if (IS_BIGENDIAN())
- {
- packet_len = header->wlen;
- }
- else
- {
packet_len = ntohs(header->wlen);
- }
packet_len -= (p->md.dag_fcs_bits >> 3);
caplen = rlen - dag_record_size;
- if (caplen > packet_len)
- {
+ if (caplen > packet_len) {
caplen = packet_len;
}
break;
@@ -298,10 +305,10 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
/* Count lost packets. */
if (header->lctr) {
- if (p->md.stat.ps_drop > (UINT_MAX - header->lctr)) {
+ if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
p->md.stat.ps_drop = UINT_MAX;
} else {
- p->md.stat.ps_drop += header->lctr;
+ p->md.stat.ps_drop += ntohs(header->lctr);
}
}
@@ -311,16 +318,13 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
/* convert between timestamp formats */
register unsigned long long ts;
- if (IS_BIGENDIAN())
- {
+ if (IS_BIGENDIAN()) {
ts = SWAP_TS(header->ts);
- }
- else
- {
+ } else {
ts = header->ts;
}
- pcap_header.ts.tv_sec = ts >> 32;
+ pcap_header.ts.tv_sec = ts >> 32;
ts = (ts & 0xffffffffULL) * 1000000;
ts += 0x80000000; /* rounding */
pcap_header.ts.tv_usec = ts >> 32;
@@ -332,13 +336,13 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
/* Fill in our own header data */
pcap_header.caplen = caplen;
pcap_header.len = packet_len;
-
+
/* Count the packet. */
p->md.stat.ps_recv++;
-
+
/* Call the user supplied callback function */
callback(user, &pcap_header, dp);
-
+
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
processed++;
if (processed == cnt)
@@ -354,10 +358,18 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
return processed;
}
}
-
+
return processed;
}
+static int
+dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+ strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
/*
* Get a handle for a live capture from the given DAG device. Passing a NULL
* device will result in a failure. The promisc flag is ignored because DAG
@@ -366,152 +378,171 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
*
* See also pcap(3).
*/
-pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) {
- char conf[30]; /* dag configure string */
- pcap_t *handle;
- char *s;
- int n;
-
- if (device == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
- return NULL;
- }
- /* Allocate a handle for this session. */
-
- handle = malloc(sizeof(*handle));
- if (handle == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno));
- return NULL;
- }
-
- /* Initialize some components of the pcap structure. */
-
- memset(handle, 0, sizeof(*handle));
-
- if (strstr(device, "/dev") == NULL) {
- char * newDev = (char *)malloc(strlen(device) + 6);
- newDev[0] = '\0';
- strcat(newDev, "/dev/");
- strcat(newDev,device);
- device = newDev;
- } else {
- device = strdup(device);
- }
-
- if (device == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno));
- goto fail;
- }
-
- /* setup device parameters */
- if((handle->fd = dag_open((char *)device)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
- goto fail;
- }
-
- /* set the card snap length to the specified snaplen parameter */
- if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
- snaplen = MAX_DAG_SNAPLEN;
- } else if (snaplen < MIN_DAG_SNAPLEN) {
- snaplen = MIN_DAG_SNAPLEN;
- }
- /* snap len has to be a multiple of 4 */
- snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
-
- fprintf(stderr, "Configuring DAG with '%s'.\n", conf);
- if(dag_configure(handle->fd, conf) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
- goto fail;
- }
-
- if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
- goto fail;
- }
-
- if(dag_start(handle->fd) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
- goto fail;
- }
-
- /*
- * Important! You have to ensure bottom is properly
- * initialized to zero on startup, it won't give you
- * a compiler warning if you make this mistake!
- */
- handle->md.dag_mem_bottom = 0;
- handle->md.dag_mem_top = 0;
-
- /* TODO: query the card */
- handle->md.dag_fcs_bits = 32;
- if ((s = getenv("ERF_FCS_BITS")) != NULL) {
- if ((n = atoi(s)) == 0 || n == 16|| n == 32) {
- handle->md.dag_fcs_bits = n;
- } else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
- goto fail;
- }
- }
-
- handle->snapshot = snaplen;
- /*handle->md.timeout = to_ms; */
-
- if ((handle->linktype = dag_get_datalink(handle)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_linktype %s: unknown linktype\n", device);
- goto fail;
- }
-
- handle->bufsize = 0;
-
- if (new_pcap_dag(handle) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
- goto fail;
- }
-
- /*
- * "select()" and "poll()" don't (yet) work on DAG device descriptors.
- */
- handle->selectable_fd = -1;
+pcap_t *
+dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+ char conf[30]; /* dag configure string */
+ pcap_t *handle;
+ char *s;
+ int n;
+ daginf_t* daginf;
+
+ if (device == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+ return NULL;
+ }
+ /* Allocate a handle for this session. */
+
+ handle = malloc(sizeof(*handle));
+ if (handle == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno));
+ return NULL;
+ }
+
+ /* Initialize some components of the pcap structure. */
+
+ memset(handle, 0, sizeof(*handle));
+
+ if (strstr(device, "/dev") == NULL) {
+ char * newDev = (char *)malloc(strlen(device) + 6);
+ newDev[0] = '\0';
+ strcat(newDev, "/dev/");
+ strcat(newDev,device);
+ device = newDev;
+ } else {
+ device = strdup(device);
+ }
+
+ if (device == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno));
+ goto fail;
+ }
+
+ /* setup device parameters */
+ if((handle->fd = dag_open((char *)device)) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+ /* set the card snap length to the specified snaplen parameter */
+ if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
+ snaplen = MAX_DAG_SNAPLEN;
+ } else if (snaplen < MIN_DAG_SNAPLEN) {
+ snaplen = MIN_DAG_SNAPLEN;
+ }
+ /* snap len has to be a multiple of 4 */
+ snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
+
+ if(dag_configure(handle->fd, conf) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+ if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+ if(dag_start(handle->fd) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * Important! You have to ensure bottom is properly
+ * initialized to zero on startup, it won't give you
+ * a compiler warning if you make this mistake!
+ */
+ handle->md.dag_mem_bottom = 0;
+ handle->md.dag_mem_top = 0;
+ handle->md.dag_fcs_bits = 32;
+
+ /* Query the card first for special cases. */
+ daginf = dag_info(handle->fd);
+ if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code))
+ {
+ /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */
+ handle->md.dag_fcs_bits = 0;
+ }
+
+ /* Then allow an environment variable to override. */
+ if ((s = getenv("ERF_FCS_BITS")) != NULL) {
+ if ((n = atoi(s)) == 0 || n == 16|| n == 32) {
+ handle->md.dag_fcs_bits = n;
+ } else {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
+ goto fail;
+ }
+ }
+
+ handle->snapshot = snaplen;
+ /*handle->md.timeout = to_ms; */
+
+ handle->linktype = -1;
+ if (dag_get_datalink(handle) < 0) {
+ strcpy(ebuf, handle->errbuf);
+ goto fail;
+ }
+
+ handle->bufsize = 0;
+
+ if (new_pcap_dag(handle) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * "select()" and "poll()" don't (yet) work on DAG device descriptors.
+ */
+ handle->selectable_fd = -1;
#ifdef linux
- handle->md.device = (char *)device;
+ handle->md.device = (char *)device;
#else
- free((char *)device);
- device = NULL;
+ free((char *)device);
+ device = NULL;
#endif
- handle->read_op = dag_read;
- handle->setfilter_op = dag_setfilter;
- handle->set_datalink_op = dag_set_datalink;
- handle->getnonblock_op = pcap_getnonblock_fd;
- handle->setnonblock_op = dag_setnonblock;
- handle->stats_op = dag_stats;
- handle->close_op = dag_platform_close;
+ handle->read_op = dag_read;
+ handle->inject_op = dag_inject;
+ handle->setfilter_op = dag_setfilter;
+ handle->set_datalink_op = dag_set_datalink;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = dag_setnonblock;
+ handle->stats_op = dag_stats;
+ handle->close_op = dag_platform_close;
- return handle;
+ return handle;
fail:
- if (device != NULL) {
- free((char *)device);
- }
- if (handle != NULL) {
- free(handle);
- }
+ if (device != NULL) {
+ free((char *)device);
+ }
+ if (handle != NULL) {
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (handle->dlt_list != NULL) {
+ free(handle->dlt_list);
+ }
+ free(handle);
+ }
- return NULL;
+ return NULL;
}
-static int dag_stats(pcap_t *p, struct pcap_stat *ps) {
- /* This needs to be filled out correctly. Hopefully a dagapi call will
- provide all necessary information.
- */
- /*p->md.stat.ps_recv = 0;*/
- /*p->md.stat.ps_drop = 0;*/
-
- *ps = p->md.stat;
+static int
+dag_stats(pcap_t *p, struct pcap_stat *ps) {
+ /* This needs to be filled out correctly. Hopefully a dagapi call will
+ provide all necessary information.
+ */
+ /*p->md.stat.ps_recv = 0;*/
+ /*p->md.stat.ps_drop = 0;*/
+
+ *ps = p->md.stat;
- return 0;
+ return 0;
}
/*
@@ -527,87 +558,86 @@ static int dag_stats(pcap_t *p, struct pcap_stat *ps) {
int
dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
{
- FILE *proc_dag_f;
- char linebuf[512];
- int linenum;
- unsigned char *p;
- char name[512]; /* XXX - pick a size */
- char *q;
- int ret = 0;
-
- /* Quick exit if /proc/dag not readable */
- proc_dag_f = fopen("/proc/dag", "r");
- if (proc_dag_f == NULL)
- {
- int i;
- char dev[16] = "dagx";
-
- for (i = '0'; ret == 0 && i <= '9'; i++) {
- dev[3] = i;
- if (pcap_add_if(devlistp, dev, 0, NULL, errbuf) == -1) {
- /*
- * Failure.
- */
- ret = -1;
- }
- }
-
- return (ret);
- }
-
- for (linenum = 1;
- fgets(linebuf, sizeof linebuf, proc_dag_f) != NULL; linenum++) {
-
- /*
- * Skip the first two lines - they're headers.
- */
- if (linenum <= 2)
- continue;
-
- p = &linebuf[0];
-
- if (*p == '\0' || *p == '\n' || *p != 'D')
- continue; /* not a Dag line */
-
- /*
- * Get the interface name.
- */
- q = &name[0];
- while (*p != '\0' && *p != ':') {
- if (*p != ' ')
- *q++ = tolower(*p++);
- else
- p++;
- }
- *q = '\0';
-
- /*
- * Add an entry for this interface, with no addresses.
- */
- p[strlen(p) - 1] = '\0'; /* get rid of \n */
- if (pcap_add_if(devlistp, name, 0, strdup(p + 2), errbuf) == -1) {
- /*
- * Failure.
- */
- ret = -1;
- break;
- }
- }
- if (ret != -1) {
- /*
- * Well, we didn't fail for any other reason; did we
- * fail due to an error reading the file?
- */
- if (ferror(proc_dag_f)) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Error reading /proc/dag: %s",
- pcap_strerror(errno));
- ret = -1;
- }
- }
-
- (void)fclose(proc_dag_f);
- return (ret);
+ FILE *proc_dag_f;
+ char linebuf[512];
+ int linenum;
+ unsigned char *p;
+ char name[512]; /* XXX - pick a size */
+ char *q;
+ int ret = 0;
+
+ /* Quick exit if /proc/dag not readable */
+ proc_dag_f = fopen("/proc/dag", "r");
+ if (proc_dag_f == NULL)
+ {
+ int i;
+ char dev[16] = "dagx";
+
+ for (i = '0'; ret == 0 && i <= '9'; i++) {
+ dev[3] = i;
+ if (pcap_add_if(devlistp, dev, 0, NULL, errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ }
+ }
+
+ return (ret);
+ }
+
+ for (linenum = 1; fgets(linebuf, sizeof linebuf, proc_dag_f) != NULL; linenum++) {
+
+ /*
+ * Skip the first two lines - they're headers.
+ */
+ if (linenum <= 2)
+ continue;
+
+ p = &linebuf[0];
+
+ if (*p == '\0' || *p == '\n' || *p != 'D')
+ continue; /* not a Dag line */
+
+ /*
+ * Get the interface name.
+ */
+ q = &name[0];
+ while (*p != '\0' && *p != ':') {
+ if (*p != ' ')
+ *q++ = tolower(*p++);
+ else
+ p++;
+ }
+ *q = '\0';
+
+ /*
+ * Add an entry for this interface, with no addresses.
+ */
+ p[strlen(p) - 1] = '\0'; /* get rid of \n */
+ if (pcap_add_if(devlistp, name, 0, strdup(p + 2), errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ break;
+ }
+ }
+ if (ret != -1) {
+ /*
+ * Well, we didn't fail for any other reason; did we
+ * fail due to an error reading the file?
+ */
+ if (ferror(proc_dag_f)) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Error reading /proc/dag: %s",
+ pcap_strerror(errno));
+ ret = -1;
+ }
+ }
+
+ (void)fclose(proc_dag_f);
+ return (ret);
}
/*
@@ -615,31 +645,32 @@ dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
* no attempt to store the filter in kernel memory as that is not supported
* with DAG cards.
*/
-static int dag_setfilter(pcap_t *p, struct bpf_program *fp) {
- if (!p)
- return -1;
- if (!fp) {
- strncpy(p->errbuf, "setfilter: No filter specified",
- sizeof(p->errbuf));
- return -1;
- }
-
- /* Make our private copy of the filter */
-
- if (install_bpf_program(p, fp) < 0) {
- snprintf(p->errbuf, sizeof(p->errbuf),
- "malloc: %s", pcap_strerror(errno));
- return -1;
- }
-
- p->md.use_bpf = 0;
-
- return (0);
+static int
+dag_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+ if (!p)
+ return -1;
+ if (!fp) {
+ strncpy(p->errbuf, "setfilter: No filter specified",
+ sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Make our private copy of the filter */
+
+ if (install_bpf_program(p, fp) < 0)
+ return -1;
+
+ p->md.use_bpf = 0;
+
+ return (0);
}
static int
dag_set_datalink(pcap_t *p, int dlt)
{
+ p->linktype = dlt;
+
return (0);
}
@@ -666,45 +697,66 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
static int
dag_get_datalink(pcap_t *p)
{
- int linktype = -1;
-
- /* Check the type through a dagapi call.
- */
- switch(dag_linktype(p->fd)) {
- case TYPE_HDLC_POS: {
- dag_record_t *record;
-
- /* peek at the first available record to see if it is PPP */
- while ((p->md.dag_mem_top - p->md.dag_mem_bottom) < (dag_record_size + 4)) {
- p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), 0);
- }
- record = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
-
- if ((ntohl(record->rec.pos.hdlc) & 0xffff0000) == 0xff030000) {
- linktype = DLT_PPP_SERIAL;
- fprintf(stderr, "Set DAG linktype to %d (DLT_PPP_SERIAL)\n", linktype);
- } else {
- linktype = DLT_CHDLC;
- fprintf(stderr, "Set DAG linktype to %d (DLT_CHDLC)\n", linktype);
- }
- break;
- }
- case TYPE_ETH:
- linktype = DLT_EN10MB;
- fprintf(stderr, "Set DAG linktype to %d (DLT_EN10MB)\n", linktype);
- break;
- case TYPE_ATM:
- linktype = DLT_ATM_RFC1483;
- fprintf(stderr, "Set DAG linktype to %d (DLT_ATM_RFC1483)\n", linktype);
- break;
- case TYPE_LEGACY:
- linktype = DLT_NULL;
- fprintf(stderr, "Set DAG linktype to %d (DLT_NULL)\n", linktype);
- break;
- default:
- fprintf(stderr, "Unknown DAG linktype %d\n", dag_linktype(p->fd));
- break;
- }
-
- return linktype;
+ int daglinktype;
+
+ if (p->dlt_list == NULL && (p->dlt_list = malloc(2*sizeof(*(p->dlt_list)))) == NULL) {
+ (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ /* Check the type through a dagapi call. */
+ daglinktype = dag_linktype(p->fd);
+
+ switch(daglinktype) {
+
+ case TYPE_HDLC_POS:
+ if (p->dlt_list != NULL) {
+ p->dlt_count = 2;
+ p->dlt_list[0] = DLT_CHDLC;
+ p->dlt_list[1] = DLT_PPP_SERIAL;
+ }
+ p->linktype = DLT_CHDLC;
+ break;
+
+ case TYPE_ETH:
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_count = 2;
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ }
+ p->linktype = DLT_EN10MB;
+ break;
+
+ case TYPE_AAL5:
+ case TYPE_ATM:
+ if (p->dlt_list != NULL) {
+ p->dlt_count = 2;
+ p->dlt_list[0] = DLT_ATM_RFC1483;
+ p->dlt_list[1] = DLT_SUNATM;
+ }
+ p->linktype = DLT_ATM_RFC1483;
+ break;
+
+
+ case TYPE_LEGACY:
+ p->linktype = DLT_NULL;
+ break;
+
+ default:
+ snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d\n", daglinktype);
+ return (-1);
+
+ }
+
+ return p->linktype;
}
diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c
index f8a917a7ebdf..c92762958552 100644
--- a/contrib/libpcap/pcap-dlpi.c
+++ b/contrib/libpcap/pcap-dlpi.c
@@ -19,7 +19,9 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
- * University College London.
+ * University College London, and subsequently modified by
+ * Guy Harris (guy@alum.mit.edu) and Mark Pizzolato
+ * <List-tcpdump-workers@subscriptions.pizzolato.net>.
*/
/*
@@ -27,18 +29,40 @@
*
* Notes:
*
- * - Apparently the DLIOCRAW ioctl() is specific to SunOS.
+ * - The DLIOCRAW ioctl() is specific to SunOS.
*
* - There is a bug in bufmod(7) such that setting the snapshot
* length results in data being left of the front of the packet.
*
* - It might be desirable to use pfmod(7) to filter packets in the
* kernel when possible.
+ *
+ * - The HP-UX 10.20 DLPI Programmer's Guide used to be available
+ * at
+ *
+ * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
+ *
+ * but is no longer available; it can still be found at
+ *
+ * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf
+ *
+ * in PDF form.
+ *
+ * - The HP-UX 11.00 DLPI Programmer's Guide is available at
+ *
+ * http://docs.hp.com/hpux/onlinedocs/B2355-90139/B2355-90139.html
+ *
+ * and in PDF form at
+ *
+ * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90139.pdf
+ *
+ * - Both of the HP documents describe raw-mode services, which are
+ * what we use if DL_HP_RAWDLS is defined.
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.91.2.3 2003/11/21 10:20:46 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108 2004/10/19 07:06:12 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -57,7 +81,7 @@ static const char rcsid[] _U_ =
#ifdef HAVE_HPUX9
#include <sys/socket.h>
#endif
-#ifdef DL_HP_PPA_ACK_OBS
+#ifdef DL_HP_PPA_REQ
#include <sys/stat.h>
#endif
#include <sys/stream.h>
@@ -82,6 +106,12 @@ static const char rcsid[] _U_ =
#include <stropts.h>
#include <unistd.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
#include "pcap-int.h"
#ifdef HAVE_OS_PROTO_H
@@ -127,16 +157,20 @@ static const char rcsid[] _U_ =
/* Forwards */
static char *split_dname(char *, int *, char *);
+static int dl_doattach(int, int, char *);
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 dlbindack(int, char *, char *);
+static int dlpromisconreq(int, bpf_u_int32, char *);
static int dlokack(int, const char *, char *, char *);
+static int dlinforeq(int, char *);
+static int dlinfoack(int, char *, char *);
+#ifdef DL_HP_RAWDLS
+static int dlrawdatareq(int, const u_char *, int);
+#endif
static int recv_ack(int, int, const char *, char *, char *);
static char *dlstrerror(bpf_u_int32);
static char *dlprim(bpf_u_int32);
-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
@@ -158,21 +192,32 @@ pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
/*
* "ps_recv" counts packets handed to the filter, not packets
* that passed the filter. As filtering is done in userland,
- * this does not include packets dropped because we ran out
- * of buffer space.
+ * this would not include packets dropped because we ran out
+ * of buffer space; in order to make this more like other
+ * platforms (Linux 2.4 and later, BSDs with BPF), where the
+ * "packets received" count includes packets received but dropped
+ * due to running out of buffer space, and to keep from confusing
+ * applications that, for example, compute packet drop percentages,
+ * we also make it count packets dropped by "bufmod" (otherwise we
+ * might run the risk of the packet drop count being bigger than
+ * the received-packet count).
*
- * "ps_drop" counts packets dropped inside the DLPI service
- * provider device device because of flow control requirements
- * or resource exhaustion; it doesn't count packets dropped by
- * the interface driver, or packets dropped upstream. As
- * filtering is done in userland, it counts packets regardless
- * of whether they would've passed the filter.
+ * "ps_drop" counts packets dropped by "bufmod" because of
+ * flow control requirements or resource exhaustion; it doesn't
+ * count packets dropped by the interface driver, or packets
+ * dropped upstream. As filtering is done in userland, it counts
+ * packets regardless of whether they would've passed the filter.
*
* These statistics don't include packets not yet read from
* the kernel by libpcap, but they may include packets not
* yet read from libpcap by the application.
*/
*ps = p->md.stat;
+
+ /*
+ * Add in the drop count, as per the above comment.
+ */
+ ps->ps_recv += ps->ps_drop;
return (0);
}
@@ -220,11 +265,21 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
p->break_loop = 0;
return (-2);
}
+ /*
+ * XXX - check for the DLPI primitive, which
+ * would be DL_HP_RAWDATA_IND on HP-UX
+ * if we're in raw mode?
+ */
if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
/* Don't choke when we get ptraced */
- if (errno == EINTR) {
+ switch (errno) {
+
+ case EINTR:
cc = 0;
continue;
+
+ case EAGAIN:
+ return (0);
}
strlcpy(p->errbuf, pcap_strerror(errno),
sizeof(p->errbuf));
@@ -306,6 +361,58 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
+static int
+pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+#if defined(DLIOCRAW)
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+#elif defined(DL_HP_RAWDLS)
+ if (p->send_fd < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "send: Output FD couldn't be opened");
+ return (-1);
+ }
+ ret = dlrawdatareq(p->send_fd, buf, size);
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+#else /* no raw mode */
+ /*
+ * XXX - this is a pain, because you might have to extract
+ * the address from the packet and use it in a DL_UNITDATA_REQ
+ * request. That would be dependent on the link-layer type.
+ *
+ * I also don't know what SAP you'd have to bind the descriptor
+ * to, or whether you'd need separate "receive" and "send" FDs,
+ * nor do I know whether you'd need different bindings for
+ * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus
+ * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.
+ *
+ * So, for now, we just return a "you can't send" indication,
+ * and leave it up to somebody with a DLPI-based system lacking
+ * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement
+ * packet transmission on that system. If they do, they should
+ * send it to us - but should not send us code that assumes
+ * Ethernet; if the code doesn't work on non-Ethernet interfaces,
+ * it should check "p->linktype" and reject the send request if
+ * it's anything other than DLT_EN10MB.
+ */
+ strlcpy(p->errbuf, "send: Not supported on this version of this OS",
+ PCAP_ERRBUF_SIZE);
+ ret = -1;
+#endif /* raw mode */
+ return (ret);
+}
+
#ifndef DL_IPATM
#define DL_IPATM 0x12 /* ATM Classical IP interface */
#endif
@@ -325,10 +432,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
static void
pcap_close_dlpi(pcap_t *p)
{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
+ pcap_close_common(p);
+ if (p->send_fd >= 0)
+ close(p->send_fd);
}
pcap_t *
@@ -362,6 +468,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
memset(p, 0, sizeof(*p));
p->fd = -1; /* indicate that it hasn't been opened yet */
+ p->send_fd = -1;
#ifdef HAVE_DEV_DLPI
/*
@@ -400,6 +507,22 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad;
}
+#ifdef DL_HP_RAWDLS
+ /*
+ * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
+ * receiving packets on the same descriptor - you have to bind the
+ * descriptor on which you receive to a SAP of 22 and bind the
+ * descriptor on which you send to a SAP of 24.
+ *
+ * If the open fails, we just leave -1 in "p->send_fd" and reject
+ * attempts to send packets, just as if, in pcap-bpf.c, we fail
+ * to open the BPF device for reading and writing, we just try
+ * to open it for reading only and, if that succeeds, just let
+ * the send attempts fail.
+ */
+ p->send_fd = open(cp, O_RDWR);
+#endif
+
/*
* Get a table of all PPAs for that device, and search that
* table for the specified device type name and unit number.
@@ -445,8 +568,28 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/* Try again with unit number */
if ((p->fd = open(dname2, O_RDWR)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2,
- pcap_strerror(errno));
+ if (errno == ENOENT) {
+ /*
+ * We just report "No DLPI device found"
+ * with the device name, so people don't
+ * get confused and think, for example,
+ * that if they can't capture on "lo0"
+ * on Solaris the fix is to change libpcap
+ * (or the application that uses it) to
+ * look for something other than "/dev/lo0",
+ * as the fix is to look for an operating
+ * system other than Solaris - you just
+ * *can't* capture on a loopback interface
+ * on Solaris, the lack of a DLPI device
+ * for the loopback interface is just a
+ * symptom of that inability.
+ */
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "%s: No DLPI device found", device);
+ } else {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ dname2, pcap_strerror(errno));
+ }
goto bad;
}
/* XXX Assume unit zero */
@@ -467,10 +610,17 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
if (infop->dl_mac_type == DL_IPATM)
isatm = 1;
#endif
- if (infop->dl_provider_style == DL_STYLE2 &&
- (dlattachreq(p->fd, ppa, ebuf) < 0 ||
- dlokack(p->fd, "attach", (char *)buf, ebuf) < 0))
- goto bad;
+ if (infop->dl_provider_style == DL_STYLE2) {
+ if (dl_doattach(p->fd, ppa, ebuf) < 0)
+ goto bad;
+#ifdef DL_HP_RAWDLS
+ if (p->send_fd >= 0) {
+ if (dl_doattach(p->send_fd, ppa, ebuf) < 0)
+ goto bad;
+ }
+#endif
+ }
+
/*
** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if
** using SINIX)
@@ -495,12 +645,34 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
if ((dlbindreq(p->fd, 1537, ebuf) < 0 &&
dlbindreq(p->fd, 2, ebuf) < 0) ||
-#else
+ dlbindack(p->fd, (char *)buf, ebuf) < 0)
+ goto bad;
+#elif defined(DL_HP_RAWDLS)
+ /*
+ ** This is the descriptor on which we receive packets; we
+ ** bind it to 22, as that's INSAP, as per the HP-UX DLPI
+ ** Programmer's Guide.
+ */
+ if (dlbindreq(p->fd, 22, ebuf) < 0 ||
+ dlbindack(p->fd, (char *)buf, ebuf) < 0)
+ goto bad;
+
+ if (p->send_fd >= 0) {
+ /*
+ ** This is the descriptor on which we send packets; we
+ ** bind it to 24, as that's OUTSAP, as per the HP-UX
+ ** DLPI Programmer's Guide.
+ */
+ if (dlbindreq(p->send_fd, 24, ebuf) < 0 ||
+ dlbindack(p->send_fd, (char *)buf, ebuf) < 0)
+ goto bad;
+ }
+#else /* neither AIX nor HP-UX */
if (dlbindreq(p->fd, 0, ebuf) < 0 ||
-#endif
dlbindack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
-#endif
+#endif /* SAP to bind to */
+#endif /* HP-UX 9 or 10.20 or SINIX */
#ifdef HAVE_SOLARIS
if (isatm) {
@@ -519,7 +691,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif
if (promisc) {
/*
- ** Enable promiscuous
+ ** Enable promiscuous (not necessary on send FD)
*/
if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||
dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0)
@@ -528,7 +700,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
** Try to enable multicast (you would have thought
** promiscuous would be sufficient). (Skip if using
- ** HP-UX or SINIX)
+ ** HP-UX or SINIX) (Not necessary on send FD)
*/
#if !defined(__hpux) && !defined(sinix)
if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||
@@ -540,7 +712,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
** Try to enable sap (when not in promiscuous mode when using
** using HP-UX, when not doing SunATM on Solaris, and never
- ** under SINIX)
+ ** under SINIX) (Not necessary on send FD)
*/
#ifndef sinix
if (
@@ -573,6 +745,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
** Determine link type
+ ** XXX - get SAP length and address length as well, for use
+ ** when sending packets.
*/
if (dlinforeq(p->fd, ebuf) < 0 ||
dlinfoack(p->fd, (char *)buf, ebuf) < 0)
@@ -585,6 +759,25 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
case DL_ETHER:
p->linktype = DLT_EN10MB;
p->offset = 2;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
break;
case DL_FDDI:
@@ -593,6 +786,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
break;
case DL_TPR:
+ /*
+ * XXX - what about DL_TPB? Is that Token Bus?
+ */
p->linktype = DLT_IEEE802;
p->offset = 2;
break;
@@ -711,6 +907,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->selectable_fd = p->fd;
p->read_op = pcap_read_dlpi;
+ p->inject_op = pcap_inject_dlpi;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
@@ -722,6 +919,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
bad:
if (p->fd >= 0)
close(p->fd);
+ if (p->send_fd >= 0)
+ close(p->send_fd);
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
return (NULL);
}
@@ -739,7 +943,7 @@ split_dname(char *device, int *unitp, char *ebuf)
{
char *cp;
char *eos;
- int unit;
+ long unit;
/*
* Look for a number at the end of the device name string.
@@ -755,15 +959,37 @@ split_dname(char *device, int *unitp, char *ebuf)
while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
cp--;
+ errno = 0;
unit = strtol(cp, &eos, 10);
if (*eos != '\0') {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
return (NULL);
}
- *unitp = unit;
+ if (errno == ERANGE || unit > INT_MAX) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+ device);
+ return (NULL);
+ }
+ if (unit < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+ device);
+ return (NULL);
+ }
+ *unitp = (int)unit;
return (cp);
}
+static int
+dl_doattach(int fd, int ppa, char *ebuf)
+{
+ bpf_u_int32 buf[MAXDLBUF];
+
+ if (dlattachreq(fd, ppa, ebuf) < 0 ||
+ dlokack(fd, "attach", (char *)buf, ebuf) < 0)
+ return (-1);
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
@@ -1170,6 +1396,42 @@ dlinfoack(int fd, char *bufp, char *ebuf)
return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
}
+#ifdef DL_HP_RAWDLS
+/*
+ * There's an ack *if* there's an error.
+ */
+static int
+dlrawdatareq(int fd, const u_char *datap, int datalen)
+{
+ struct strbuf ctl, data;
+ long buf[MAXDLBUF]; /* XXX - char? */
+ union DL_primitives *dlp;
+ int dlen;
+
+ dlp = (union DL_primitives*) buf;
+
+ dlp->dl_primitive = DL_HP_RAWDATA_REQ;
+ dlen = DL_HP_RAWDATA_REQ_SIZE;
+
+ /*
+ * HP's documentation doesn't appear to show us supplying any
+ * address pointed to by the control part of the message.
+ * I think that's what raw mode means - you just send the raw
+ * packet, you don't specify where to send it to, as that's
+ * implied by the destination address.
+ */
+ ctl.maxlen = 0;
+ ctl.len = dlen;
+ ctl.buf = (void *)buf;
+
+ data.maxlen = 0;
+ data.len = datalen;
+ data.buf = (void *)datap;
+
+ return (putmsg(fd, &ctl, &data, 0));
+}
+#endif /* DL_HP_RAWDLS */
+
#ifdef HAVE_SYS_BUFMOD_H
static int
strioctl(int fd, int cmd, int len, char *dp)
@@ -1216,7 +1478,7 @@ get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
}
#endif
-#ifdef DL_HP_PPA_ACK_OBS
+#ifdef DL_HP_PPA_REQ
/*
* Under HP-UX 10 and HP-UX 11, we can ask for the ppa
*/
diff --git a/contrib/libpcap/pcap-dos.c b/contrib/libpcap/pcap-dos.c
new file mode 100644
index 000000000000..21fd11338923
--- /dev/null
+++ b/contrib/libpcap/pcap-dos.c
@@ -0,0 +1,1473 @@
+/*
+ * This file is part of DOS-libpcap
+ * Ported to DOS/DOSX by G. Vanem <giva@bgnett.no>
+ *
+ * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
+ * network drivers.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004/12/18 08:52:10 guy Exp $ (LBL)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <float.h>
+#include <fcntl.h>
+#include <io.h>
+
+#if defined(USE_32BIT_DRIVERS)
+ #include "msdos/pm_drvr/pmdrvr.h"
+ #include "msdos/pm_drvr/pci.h"
+ #include "msdos/pm_drvr/bios32.h"
+ #include "msdos/pm_drvr/module.h"
+ #include "msdos/pm_drvr/3c501.h"
+ #include "msdos/pm_drvr/3c503.h"
+ #include "msdos/pm_drvr/3c509.h"
+ #include "msdos/pm_drvr/3c59x.h"
+ #include "msdos/pm_drvr/3c515.h"
+ #include "msdos/pm_drvr/3c90x.h"
+ #include "msdos/pm_drvr/3c575_cb.h"
+ #include "msdos/pm_drvr/ne.h"
+ #include "msdos/pm_drvr/wd.h"
+ #include "msdos/pm_drvr/accton.h"
+ #include "msdos/pm_drvr/cs89x0.h"
+ #include "msdos/pm_drvr/rtl8139.h"
+ #include "msdos/pm_drvr/ne2k-pci.h"
+#endif
+
+#include "pcap.h"
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#ifdef USE_NDIS2
+#include "msdos/ndis2.h"
+#endif
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_ether.h>
+#include <net/if_packe.h>
+#include <tcp.h>
+
+#if defined(USE_32BIT_DRIVERS)
+ #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0)
+ #define NDIS_NEXT_DEV &rtl8139_dev
+
+ static char *rx_pool = NULL;
+ static void init_32bit (void);
+
+ static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool);
+ static int pktq_check (struct rx_ringbuf *q);
+ static int pktq_inc_out (struct rx_ringbuf *q);
+ static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
+ static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC;
+
+ static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC;
+ static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
+
+#else
+ #define FLUSHK() ((void)0)
+ #define NDIS_NEXT_DEV NULL
+#endif
+
+/*
+ * Internal variables/functions in Watt-32
+ */
+extern WORD _pktdevclass;
+extern BOOL _eth_is_init;
+extern int _w32_dynamic_host;
+extern int _watt_do_exit;
+extern int _watt_is_init;
+extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
+extern void (*_w32_usr_post_init) (void);
+extern void (*_w32_print_hook)();
+
+extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */
+extern int pkt_get_mtu (void);
+
+static int ref_count = 0;
+
+static u_long mac_count = 0;
+static u_long filter_count = 0;
+
+static volatile BOOL exc_occured = 0;
+
+static struct device *handle_to_device [20];
+
+static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
+ u_char *data);
+static void pcap_close_dos (pcap_t *p);
+static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
+static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
+static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
+
+static int ndis_probe (struct device *dev);
+static int pkt_probe (struct device *dev);
+
+static void close_driver (void);
+static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
+static int first_init (const char *name, char *ebuf, int promisc);
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+ const u_char *buf);
+
+/*
+ * These are the device we always support
+ */
+static struct device ndis_dev = {
+ "ndis",
+ "NDIS2 LanManager",
+ 0,
+ 0,0,0,0,0,0,
+ NDIS_NEXT_DEV, /* NULL or a 32-bit device */
+ ndis_probe
+ };
+
+static struct device pkt_dev = {
+ "pkt",
+ "Packet-Driver",
+ 0,
+ 0,0,0,0,0,0,
+ &ndis_dev,
+ pkt_probe
+ };
+
+static struct device *get_device (int fd)
+{
+ if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
+ return (NULL);
+ return handle_to_device [fd-1];
+}
+
+/*
+ * Open MAC-driver with name 'device_name' for live capture of
+ * network packets.
+ */
+pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
+ int timeout_ms, char *errbuf)
+{
+ struct pcap *pcap;
+
+ if (snaplen < ETH_MIN)
+ snaplen = ETH_MIN;
+
+ if (snaplen > ETH_MAX) /* silently accept and truncate large MTUs */
+ snaplen = ETH_MAX;
+
+ pcap = calloc (sizeof(*pcap), 1);
+ if (!pcap)
+ {
+ strcpy (errbuf, "Not enough memory (pcap)");
+ return (NULL);
+ }
+
+ pcap->snapshot = max (ETH_MIN+8, snaplen);
+ pcap->linktype = DLT_EN10MB; /* !! */
+ pcap->inter_packet_wait = timeout_ms;
+ pcap->close_op = pcap_close_dos;
+ pcap->read_op = pcap_read_dos;
+ pcap->stats_op = pcap_stats_dos;
+ pcap->inject_op = pcap_sendpacket_dos;
+ pcap->setfilter_op = pcap_setfilter_dos;
+ pcap->fd = ++ref_count;
+
+ if (pcap->fd == 1) /* first time we're called */
+ {
+ if (!init_watt32(pcap, device_name, errbuf) ||
+ !first_init(device_name, errbuf, promisc))
+ {
+ free (pcap);
+ return (NULL);
+ }
+ atexit (close_driver);
+ }
+ else if (stricmp(active_dev->name,device_name))
+ {
+ snprintf (errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot use different devices simultaneously "
+ "(`%s' vs. `%s')", active_dev->name, device_name);
+ free (pcap);
+ pcap = NULL;
+ }
+ handle_to_device [pcap->fd-1] = active_dev;
+ return (pcap);
+}
+
+/*
+ * Poll the receiver queue and call the pcap callback-handler
+ * with the packet.
+ */
+static int
+pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
+{
+ struct pcap_pkthdr pcap;
+ struct bpf_insn *fcode = p->fcode.bf_insns;
+ struct timeval now, expiry;
+ BYTE *rx_buf;
+ int rx_len = 0;
+
+ if (p->inter_packet_wait > 0)
+ {
+ gettimeofday2 (&now, NULL);
+ expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait;
+ expiry.tv_sec = now.tv_sec;
+ while (expiry.tv_usec >= 1000000L)
+ {
+ expiry.tv_usec -= 1000000L;
+ expiry.tv_sec++;
+ }
+ }
+
+ while (!exc_occured)
+ {
+ volatile struct device *dev; /* might be reset by sig_handler */
+
+ dev = get_device (p->fd);
+ if (!dev)
+ break;
+
+ PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
+ FLUSHK();
+
+ /* If driver has a zero-copy receive facility, peek at the queue,
+ * filter it, do the callback and release the buffer.
+ */
+ if (dev->peek_rx_buf)
+ {
+ PCAP_ASSERT (dev->release_rx_buf);
+ rx_len = (*dev->peek_rx_buf) (&rx_buf);
+ }
+ else
+ {
+ BYTE buf [ETH_MAX+100]; /* add some margin */
+ rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
+ rx_buf = buf;
+ }
+
+ if (rx_len > 0) /* got a packet */
+ {
+ mac_count++;
+
+ FLUSHK();
+
+ pcap.caplen = min (rx_len, p->snapshot);
+ pcap.len = rx_len;
+
+ if (callback &&
+ (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen)))
+ {
+ filter_count++;
+
+ /* Fix-me!! Should be time of arrival. Not time of
+ * capture.
+ */
+ gettimeofday2 (&pcap.ts, NULL);
+ (*callback) (data, &pcap, rx_buf);
+ }
+
+ if (dev->release_rx_buf)
+ (*dev->release_rx_buf) (rx_buf);
+
+ if (pcap_pkt_debug > 0)
+ {
+ if (callback == watt32_recv_hook)
+ dbug_write ("pcap_recv_hook\n");
+ else dbug_write ("pcap_read_op\n");
+ }
+ FLUSHK();
+ return (1);
+ }
+
+ /* If not to wait for a packet or pcap_close() called from
+ * e.g. SIGINT handler, exit loop now.
+ */
+ if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0)
+ break;
+
+ gettimeofday2 (&now, NULL);
+
+ if (timercmp(&now, &expiry, >))
+ break;
+
+#ifndef DJGPP
+ kbhit(); /* a real CPU hog */
+#endif
+
+ if (p->wait_proc)
+ (*p->wait_proc)(); /* call yield func */
+ }
+
+ if (rx_len < 0) /* receive error */
+ {
+ p->md.stat.ps_drop++;
+#ifdef USE_32BIT_DRIVERS
+ if (pcap_pkt_debug > 1)
+ printk ("pkt-err %s\n", pktInfo.error);
+#endif
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
+{
+ int rc, num = 0;
+
+ while (num <= cnt || (cnt < 0))
+ {
+ if (p->fd <= 0)
+ return (-1);
+ rc = pcap_read_one (p, callback, data);
+ if (rc > 0)
+ num++;
+ if (rc < 0)
+ break;
+ _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */
+ }
+ return (num);
+}
+
+/*
+ * Return network statistics
+ */
+static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
+{
+ struct net_device_stats *stats;
+ struct device *dev = p ? get_device(p->fd) : NULL;
+
+ if (!dev)
+ {
+ strcpy (p->errbuf, "illegal pcap handle");
+ return (-1);
+ }
+
+ if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
+ {
+ strcpy (p->errbuf, "device statistics not available");
+ return (-1);
+ }
+
+ FLUSHK();
+
+ p->md.stat.ps_recv = stats->rx_packets;
+ p->md.stat.ps_drop += stats->rx_missed_errors;
+ p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */
+ stats->rx_errors; /* HW errors */
+ if (ps)
+ *ps = p->md.stat;
+
+ return (0);
+}
+
+/*
+ * Return detailed network/device statistics.
+ * May be called after 'dev->close' is called.
+ */
+int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
+{
+ struct device *dev = p ? get_device (p->fd) : NULL;
+
+ if (!dev || !dev->get_stats)
+ {
+ strlcpy (p->errbuf, "detailed device statistics not available",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+
+ if (!strnicmp(dev->name,"pkt",3))
+ {
+ strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+ memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
+ return (0);
+}
+
+/*
+ * Simply store the filter-code for the pcap_read_dos() callback
+ * Some day the filter-code could be handed down to the active
+ * device (pkt_rx1.s or 32-bit device interrupt handler).
+ */
+static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
+{
+ if (!p)
+ return (-1);
+ p->fcode = *fp;
+ return (0);
+}
+
+/*
+ * Return # of packets received in pcap_read_dos()
+ */
+u_long pcap_mac_packets (void)
+{
+ return (mac_count);
+}
+
+/*
+ * Return # of packets passed through filter in pcap_read_dos()
+ */
+u_long pcap_filter_packets (void)
+{
+ return (filter_count);
+}
+
+/*
+ * Close pcap device. Not called for offline captures.
+ */
+static void pcap_close_dos (pcap_t *p)
+{
+ if (p && !exc_occured)
+ {
+ if (pcap_stats(p,NULL) < 0)
+ p->md.stat.ps_drop = 0;
+ if (!get_device(p->fd))
+ return;
+
+ handle_to_device [p->fd-1] = NULL;
+ p->fd = 0;
+ if (ref_count > 0)
+ ref_count--;
+ if (ref_count > 0)
+ return;
+ }
+ close_driver();
+}
+
+/*
+ * Return the name of the 1st network interface,
+ * or NULL if none can be found.
+ */
+char *pcap_lookupdev (char *ebuf)
+{
+ struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+ init_32bit();
+#endif
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if ((*dev->probe)(dev))
+ {
+ FLUSHK();
+ probed_dev = (struct device*) dev; /* remember last probed device */
+ return (char*) dev->name;
+ }
+ }
+
+ if (ebuf)
+ strcpy (ebuf, "No driver found");
+ return (NULL);
+}
+
+/*
+ * Gets localnet & netmask from Watt-32.
+ */
+int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
+ bpf_u_int32 *netmask, char *errbuf)
+{
+ if (!_watt_is_init)
+ {
+ strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be "
+ "called first");
+ return (-1);
+ }
+
+ *netmask = _w32_sin_mask;
+ *localnet = my_ip_addr & *netmask;
+ if (*localnet == 0)
+ {
+ if (IN_CLASSA(*netmask))
+ *localnet = IN_CLASSA_NET;
+ else if (IN_CLASSB(*netmask))
+ *localnet = IN_CLASSB_NET;
+ else if (IN_CLASSC(*netmask))
+ *localnet = IN_CLASSC_NET;
+ else
+ {
+ sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
+ return (-1);
+ }
+ }
+ ARGSUSED (device);
+ return (0);
+}
+
+/*
+ * Get a list of all interfaces that are present and that we probe okay.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ */
+int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+{
+ struct device *dev;
+ struct sockaddr_ll sa_ll_1, sa_ll_2;
+ struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
+ pcap_if_t *devlist = NULL;
+ int ret = 0;
+ size_t addr_size = sizeof(struct sockaddr_ll);
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if (!(*dev->probe)(dev))
+ continue;
+
+ PCAP_ASSERT (dev->close); /* set by probe routine */
+ FLUSHK();
+ (*dev->close) (dev);
+
+ memset (&sa_ll_1, 0, sizeof(sa_ll_1));
+ memset (&sa_ll_2, 0, sizeof(sa_ll_2));
+ sa_ll_1.sll_family = AF_PACKET;
+ sa_ll_2.sll_family = AF_PACKET;
+
+ addr = (struct sockaddr*) &sa_ll_1;
+ netmask = (struct sockaddr*) &sa_ll_1;
+ dstaddr = (struct sockaddr*) &sa_ll_1;
+ broadaddr = (struct sockaddr*) &sa_ll_2;
+ memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
+
+ if (pcap_add_if(&devlist, dev->name, dev->flags,
+ dev->long_name, errbuf) < 0)
+ {
+ ret = -1;
+ break;
+ }
+ if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
+ netmask, addr_size, broadaddr, addr_size,
+ dstaddr, addr_size, errbuf) < 0)
+ {
+ ret = -1;
+ break;
+ }
+ }
+
+ if (devlist && ret < 0)
+ {
+ pcap_freealldevs (devlist);
+ devlist = NULL;
+ }
+ else
+ if (!devlist)
+ strcpy (errbuf, "No drivers found");
+
+ *alldevsp = devlist;
+ return (ret);
+}
+
+/*
+ * pcap_assert() is mainly used for debugging
+ */
+void pcap_assert (const char *what, const char *file, unsigned line)
+{
+ FLUSHK();
+ fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
+ file, line, what);
+ close_driver();
+ _exit (-1);
+}
+
+/*
+ * For pcap_offline_read(): wait and yield between printing packets
+ * to simulate the pace packets where actually recorded.
+ */
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
+{
+ if (p)
+ {
+ p->wait_proc = yield;
+ p->inter_packet_wait = wait;
+ }
+}
+
+/*
+ * Initialise a named network device.
+ */
+static struct device *
+open_driver (const char *dev_name, char *ebuf, int promisc)
+{
+ struct device *dev;
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->name);
+
+ if (strcmp (dev_name,dev->name))
+ continue;
+
+ if (!probed_dev) /* user didn't call pcap_lookupdev() first */
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if (!(*dev->probe)(dev)) /* call the xx_probe() function */
+ {
+ sprintf (ebuf, "failed to detect device `%s'", dev_name);
+ return (NULL);
+ }
+ probed_dev = dev; /* device is probed okay and may be used */
+ }
+ else if (dev != probed_dev)
+ {
+ goto not_probed;
+ }
+
+ FLUSHK();
+
+ /* Select what traffic to receive
+ */
+ if (promisc)
+ dev->flags |= (IFF_ALLMULTI | IFF_PROMISC);
+ else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
+
+ PCAP_ASSERT (dev->open);
+
+ if (!(*dev->open)(dev))
+ {
+ sprintf (ebuf, "failed to activate device `%s'", dev_name);
+ if (pktInfo.error && !strncmp(dev->name,"pkt",3))
+ {
+ strcat (ebuf, ": ");
+ strcat (ebuf, pktInfo.error);
+ }
+ return (NULL);
+ }
+
+ /* Some devices need this to operate in promiscous mode
+ */
+ if (promisc && dev->set_multicast_list)
+ (*dev->set_multicast_list) (dev);
+
+ active_dev = dev; /* remember our active device */
+ break;
+ }
+
+ /* 'dev_name' not matched in 'dev_base' list.
+ */
+ if (!dev)
+ {
+ sprintf (ebuf, "device `%s' not supported", dev_name);
+ return (NULL);
+ }
+
+not_probed:
+ if (!probed_dev)
+ {
+ sprintf (ebuf, "device `%s' not probed", dev_name);
+ return (NULL);
+ }
+ return (dev);
+}
+
+/*
+ * Deinitialise MAC driver.
+ * Set receive mode back to default mode.
+ */
+static void close_driver (void)
+{
+ /* !!todo: loop over all 'handle_to_device[]' ? */
+ struct device *dev = active_dev;
+
+ if (dev && dev->close)
+ {
+ (*dev->close) (dev);
+ FLUSHK();
+ }
+
+ active_dev = NULL;
+
+#ifdef USE_32BIT_DRIVERS
+ if (rx_pool)
+ {
+ k_free (rx_pool);
+ rx_pool = NULL;
+ }
+ if (dev)
+ pcibios_exit();
+#endif
+}
+
+
+#ifdef __DJGPP__
+static void setup_signals (void (*handler)(int))
+{
+ signal (SIGSEGV,handler);
+ signal (SIGILL, handler);
+ signal (SIGFPE, handler);
+}
+
+static void exc_handler (int sig)
+{
+#ifdef USE_32BIT_DRIVERS
+ if (active_dev->irq > 0) /* excludes IRQ 0 */
+ {
+ disable_irq (active_dev->irq);
+ irq_eoi_cmd (active_dev->irq);
+ _printk_safe = 1;
+ }
+#endif
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ fputs ("Catching SIGSEGV.\n", stderr);
+ break;
+ case SIGILL:
+ fputs ("Catching SIGILL.\n", stderr);
+ break;
+ case SIGFPE:
+ _fpreset();
+ fputs ("Catching SIGFPE.\n", stderr);
+ break;
+ default:
+ fprintf (stderr, "Catching signal %d.\n", sig);
+ }
+ exc_occured = 1;
+ pcap_close_dos (NULL);
+}
+#endif /* __DJGPP__ */
+
+
+/*
+ * Open the pcap device for the first client calling pcap_open_live()
+ */
+static int first_init (const char *name, char *ebuf, int promisc)
+{
+ struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+ rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
+ if (!rx_pool)
+ {
+ strcpy (ebuf, "Not enough memory (Rx pool)");
+ return (0);
+ }
+#endif
+
+#ifdef __DJGPP__
+ setup_signals (exc_handler);
+#endif
+
+#ifdef USE_32BIT_DRIVERS
+ init_32bit();
+#endif
+
+ dev = open_driver (name, ebuf, promisc);
+ if (!dev)
+ {
+#ifdef USE_32BIT_DRIVERS
+ k_free (rx_pool);
+ rx_pool = NULL;
+#endif
+
+#ifdef __DJGPP__
+ setup_signals (SIG_DFL);
+#endif
+ return (0);
+ }
+
+#ifdef USE_32BIT_DRIVERS
+ /*
+ * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
+ * set in it's probe handler), initialise near-memory ring-buffer for
+ * the 32-bit device.
+ */
+ if (dev->copy_rx_buf == NULL)
+ {
+ dev->get_rx_buf = get_rxbuf;
+ dev->peek_rx_buf = peek_rxbuf;
+ dev->release_rx_buf = release_rxbuf;
+ pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
+ }
+#endif
+ return (1);
+}
+
+#ifdef USE_32BIT_DRIVERS
+static void init_32bit (void)
+{
+ static int init_pci = 0;
+
+ if (!_printk_file)
+ _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
+
+ if (!init_pci)
+ (void)pci_init(); /* init BIOS32+PCI interface */
+ init_pci = 1;
+}
+#endif
+
+
+/*
+ * Hook functions for using Watt-32 together with pcap
+ */
+static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
+static WORD etype;
+static pcap_t pcap_save;
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+ const u_char *buf)
+{
+ /* Fix me: assumes Ethernet II only */
+ struct ether_header *ep = (struct ether_header*) buf;
+
+ memcpy (rxbuf, buf, pcap->caplen);
+ etype = ep->ether_type;
+ ARGSUSED (dummy);
+}
+
+#if (WATTCP_VER >= 0x0224)
+/*
+ * This function is used by Watt-32 to poll for a packet.
+ * i.e. it's set to bypass _eth_arrived()
+ */
+static void *pcap_recv_hook (WORD *type)
+{
+ int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
+
+ if (len < 0)
+ return (NULL);
+
+ *type = etype;
+ return (void*) &rxbuf;
+}
+
+/*
+ * This function is called by Watt-32 (via _eth_xmit_hook).
+ * If dbug_init() was called, we should trace packets sent.
+ */
+static int pcap_xmit_hook (const void *buf, unsigned len)
+{
+ int rc = 0;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write ("pcap_xmit_hook: ");
+
+ if (active_dev && active_dev->xmit)
+ if ((*active_dev->xmit) (active_dev, buf, len) > 0)
+ rc = len;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write (rc ? "ok\n" : "fail\n");
+ return (rc);
+}
+#endif
+
+static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
+{
+ struct device *dev = p ? get_device(p->fd) : NULL;
+
+ if (!dev || !dev->xmit)
+ return (-1);
+ return (*dev->xmit) (dev, buf, len);
+}
+
+/*
+ * This function is called by Watt-32 in tcp_post_init().
+ * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
+ */
+static void (*prev_post_hook) (void);
+
+static void pcap_init_hook (void)
+{
+ _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
+ _w32__do_mask_req = 0;
+ _w32_dynamic_host = 0;
+ if (prev_post_hook)
+ (*prev_post_hook)();
+}
+
+/*
+ * Supress PRINT message from Watt-32's sock_init()
+ */
+static void null_print (void) {}
+
+/*
+ * To use features of Watt-32 (netdb functions and socket etc.)
+ * we must call sock_init(). But we set various hooks to prevent
+ * using normal PKTDRVR functions in pcpkt.c. This should hopefully
+ * make Watt-32 and pcap co-operate.
+ */
+static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
+{
+ char *env;
+ int rc, MTU, has_ip_addr;
+ int using_pktdrv = 1;
+
+ /* If user called sock_init() first, we need to reinit in
+ * order to open debug/trace-file properly
+ */
+ if (_watt_is_init)
+ sock_exit();
+
+ env = getenv ("PCAP_DEBUG");
+ if (env && atoi(env) > 0 &&
+ pcap_pkt_debug < 0) /* if not already set */
+ {
+ dbug_init();
+ pcap_pkt_debug = atoi (env);
+ }
+
+ _watt_do_exit = 0; /* prevent sock_init() calling exit() */
+ prev_post_hook = _w32_usr_post_init;
+ _w32_usr_post_init = pcap_init_hook;
+ _w32_print_hook = null_print;
+
+ if (dev_name && strncmp(dev_name,"pkt",3))
+ using_pktdrv = FALSE;
+
+ rc = sock_init();
+ has_ip_addr = (rc != 8); /* IP-address assignment failed */
+
+ /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
+ * just pretend Watt-32 is initialised okay.
+ *
+ * !! fix-me: The Watt-32 config isn't done if no pktdrvr
+ * was found. In that case my_ip_addr + sin_mask
+ * have default values. Should be taken from another
+ * ini-file/environment in any case (ref. tcpdump.ini)
+ */
+ _watt_is_init = 1;
+
+ if (!using_pktdrv || !has_ip_addr) /* for now .... */
+ {
+ static const char myip[] = "192.168.0.1";
+ static const char mask[] = "255.255.255.0";
+
+ printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
+ my_ip_addr = aton (myip);
+ _w32_sin_mask = aton (mask);
+ }
+ else if (rc && using_pktdrv)
+ {
+ sprintf (err_buf, "sock_init() failed, code %d", rc);
+ return (0);
+ }
+
+ /* Set recv-hook for peeking in _eth_arrived().
+ */
+#if (WATTCP_VER >= 0x0224)
+ _eth_recv_hook = pcap_recv_hook;
+ _eth_xmit_hook = pcap_xmit_hook;
+#endif
+
+ /* Free the pkt-drvr handle allocated in pkt_init().
+ * The above hooks should thus use the handle reopened in open_driver()
+ */
+ if (using_pktdrv)
+ {
+ _eth_release();
+/* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */
+ }
+
+ memcpy (&pcap_save, pcap, sizeof(pcap_save));
+ MTU = pkt_get_mtu();
+ pcap_save.fcode.bf_insns = NULL;
+ pcap_save.linktype = _eth_get_hwtype (NULL, NULL);
+ pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
+
+#if 1
+ /* prevent use of resolve() and resolve_ip()
+ */
+ last_nameserver = 0;
+#endif
+ return (1);
+}
+
+int EISA_bus = 0; /* Where is natural place for this? */
+
+/*
+ * Application config hooks to set various driver parameters.
+ */
+
+static struct config_table debug_tab[] = {
+ { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
+ { "PKT.VECTOR", ARG_ATOX_W, NULL },
+ { "NDIS.DEBUG", ARG_ATOI, NULL },
+#ifdef USE_32BIT_DRIVERS
+ { "3C503.DEBUG", ARG_ATOI, &ei_debug },
+ { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr },
+ { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start },
+ { "3C503.IRQ", ARG_ATOI, &el2_dev.irq },
+ { "3C505.DEBUG", ARG_ATOI, NULL },
+ { "3C505.BASE", ARG_ATOX_W, NULL },
+ { "3C507.DEBUG", ARG_ATOI, NULL },
+ { "3C509.DEBUG", ARG_ATOI, &el3_debug },
+ { "3C509.ILOOP", ARG_ATOI, &el3_max_loop },
+ { "3C529.DEBUG", ARG_ATOI, NULL },
+ { "3C575.DEBUG", ARG_ATOI, &debug_3c575 },
+ { "3C59X.DEBUG", ARG_ATOI, &vortex_debug },
+ { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] },
+ { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] },
+ { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] },
+ { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] },
+ { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug },
+ { "ACCT.DEBUG", ARG_ATOI, &ethpk_debug },
+ { "CS89.DEBUG", ARG_ATOI, &cs89_debug },
+ { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug },
+ /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */
+ { "SMC.DEBUG", ARG_ATOI, &ei_debug },
+ /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */
+ { "PCI.DEBUG", ARG_ATOI, &pci_debug },
+ { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug },
+ { "IRQ.DEBUG", ARG_ATOI, &irq_debug },
+ { "TIMER.IRQ", ARG_ATOI, &timer_irq },
+#endif
+ { NULL }
+ };
+
+/*
+ * pcap_config_hook() is an extension to application's config
+ * handling. Uses Watt-32's config-table function.
+ */
+int pcap_config_hook (const char *name, const char *value)
+{
+ return parse_config_table (debug_tab, NULL, name, value);
+}
+
+/*
+ * Linked list of supported devices
+ */
+struct device *active_dev = NULL; /* the device we have opened */
+struct device *probed_dev = NULL; /* the device we have probed */
+const struct device *dev_base = &pkt_dev; /* list of network devices */
+
+/*
+ * PKTDRVR device functions
+ */
+int pcap_pkt_debug = -1;
+
+static void pkt_close (struct device *dev)
+{
+ BOOL okay = PktExitDriver();
+
+ if (pcap_pkt_debug > 1)
+ fprintf (stderr, "pkt_close(): %d\n", okay);
+
+ if (dev->priv)
+ free (dev->priv);
+ dev->priv = NULL;
+}
+
+static int pkt_open (struct device *dev)
+{
+ PKT_RX_MODE mode;
+
+ if (dev->flags & IFF_PROMISC)
+ mode = PDRX_ALL_PACKETS;
+ else mode = PDRX_BROADCAST;
+
+ if (!PktInitDriver(mode))
+ return (0);
+
+ PktResetStatistics (pktInfo.handle);
+ PktQueueBusy (FALSE);
+ return (1);
+}
+
+static int pkt_xmit (struct device *dev, const void *buf, int len)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write ("pcap_xmit\n");
+
+ if (!PktTransmit(buf,len))
+ {
+ stats->tx_errors++;
+ return (0);
+ }
+ return (len);
+}
+
+static void *pkt_stats (struct device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ if (!stats || !PktSessStatistics(pktInfo.handle))
+ return (NULL);
+
+ stats->rx_packets = pktStat.inPackets;
+ stats->rx_errors = pktStat.lost;
+ stats->rx_missed_errors = PktRxDropped();
+ return (stats);
+}
+
+static int pkt_probe (struct device *dev)
+{
+ if (!PktSearchDriver())
+ return (0);
+
+ dev->open = pkt_open;
+ dev->xmit = pkt_xmit;
+ dev->close = pkt_close;
+ dev->get_stats = pkt_stats;
+ dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */
+ dev->get_rx_buf = NULL;
+ dev->peek_rx_buf = NULL;
+ dev->release_rx_buf = NULL;
+ dev->priv = calloc (sizeof(struct net_device_stats), 1);
+ if (!dev->priv)
+ return (0);
+ return (1);
+}
+
+/*
+ * NDIS device functions
+ */
+static void ndis_close (struct device *dev)
+{
+#ifdef USE_NDIS2
+ NdisShutdown();
+#endif
+ ARGSUSED (dev);
+}
+
+static int ndis_open (struct device *dev)
+{
+ int promis = (dev->flags & IFF_PROMISC);
+
+#ifdef USE_NDIS2
+ if (!NdisInit(promis))
+ return (0);
+ return (1);
+#else
+ ARGSUSED (promis);
+ return (0);
+#endif
+}
+
+static void *ndis_stats (struct device *dev)
+{
+ static struct net_device_stats stats;
+
+ /* to-do */
+ ARGSUSED (dev);
+ return (&stats);
+}
+
+static int ndis_probe (struct device *dev)
+{
+#ifdef USE_NDIS2
+ if (!NdisOpen())
+ return (0);
+#endif
+
+ dev->open = ndis_open;
+ dev->xmit = NULL;
+ dev->close = ndis_close;
+ dev->get_stats = ndis_stats;
+ dev->copy_rx_buf = NULL; /* to-do */
+ dev->get_rx_buf = NULL; /* upcall is from rmode driver */
+ dev->peek_rx_buf = NULL;
+ dev->release_rx_buf = NULL;
+ return (0);
+}
+
+/*
+ * Search & probe for supported 32-bit (pmode) pcap devices
+ */
+#if defined(USE_32BIT_DRIVERS)
+
+struct device el2_dev LOCKED_VAR = {
+ "3c503",
+ "EtherLink II",
+ 0,
+ 0,0,0,0,0,0,
+ NULL,
+ el2_probe
+ };
+
+struct device el3_dev LOCKED_VAR = {
+ "3c509",
+ "EtherLink III",
+ 0,
+ 0,0,0,0,0,0,
+ &el2_dev,
+ el3_probe
+ };
+
+struct device tc515_dev LOCKED_VAR = {
+ "3c515",
+ "EtherLink PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &el3_dev,
+ tc515_probe
+ };
+
+struct device tc59_dev LOCKED_VAR = {
+ "3c59x",
+ "EtherLink PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &tc515_dev,
+ tc59x_probe
+ };
+
+struct device tc90xbc_dev LOCKED_VAR = {
+ "3c90x",
+ "EtherLink 90X",
+ 0,
+ 0,0,0,0,0,0,
+ &tc59_dev,
+ tc90xbc_probe
+ };
+
+struct device wd_dev LOCKED_VAR = {
+ "wd",
+ "Westen Digital",
+ 0,
+ 0,0,0,0,0,0,
+ &tc90xbc_dev,
+ wd_probe
+ };
+
+struct device ne_dev LOCKED_VAR = {
+ "ne",
+ "NEx000",
+ 0,
+ 0,0,0,0,0,0,
+ &wd_dev,
+ ne_probe
+ };
+
+struct device acct_dev LOCKED_VAR = {
+ "acct",
+ "Accton EtherPocket",
+ 0,
+ 0,0,0,0,0,0,
+ &ne_dev,
+ ethpk_probe
+ };
+
+struct device cs89_dev LOCKED_VAR = {
+ "cs89",
+ "Crystal Semiconductor",
+ 0,
+ 0,0,0,0,0,0,
+ &acct_dev,
+ cs89x0_probe
+ };
+
+struct device rtl8139_dev LOCKED_VAR = {
+ "rtl8139",
+ "RealTek PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &cs89_dev,
+ rtl8139_probe /* dev->probe routine */
+ };
+
+/*
+ * Dequeue routine is called by polling.
+ * NOTE: the queue-element is not copied, only a pointer is
+ * returned at '*buf'
+ */
+int peek_rxbuf (BYTE **buf)
+{
+ struct rx_elem *tail, *head;
+
+ PCAP_ASSERT (pktq_check (&active_dev->queue));
+
+ DISABLE();
+ tail = pktq_out_elem (&active_dev->queue);
+ head = pktq_in_elem (&active_dev->queue);
+ ENABLE();
+
+ if (head != tail)
+ {
+ PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
+
+ *buf = &tail->data[0];
+ return (tail->size);
+ }
+ *buf = NULL;
+ return (0);
+}
+
+/*
+ * Release buffer we peeked at above.
+ */
+int release_rxbuf (BYTE *buf)
+{
+#ifndef NDEBUG
+ struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
+
+ PCAP_ASSERT (&tail->data[0] == buf);
+#else
+ ARGSUSED (buf);
+#endif
+ pktq_inc_out (&active_dev->queue);
+ return (1);
+}
+
+/*
+ * get_rxbuf() routine (in locked code) is called from IRQ handler
+ * to request a buffer. Interrupts are disabled and we have a 32kB stack.
+ */
+BYTE *get_rxbuf (int len)
+{
+ int idx;
+
+ if (len < ETH_MIN || len > ETH_MAX)
+ return (NULL);
+
+ idx = pktq_in_index (&active_dev->queue);
+
+#ifdef DEBUG
+ {
+ static int fan_idx LOCKED_VAR = 0;
+ writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */
+ 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */
+ fan_idx &= 3;
+ }
+/* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
+#endif
+
+ if (idx != active_dev->queue.out_index)
+ {
+ struct rx_elem *head = pktq_in_elem (&active_dev->queue);
+
+ head->size = len;
+ active_dev->queue.in_index = idx;
+ return (&head->data[0]);
+ }
+
+ /* !!to-do: drop 25% of the oldest element
+ */
+ pktq_clear (&active_dev->queue);
+ return (NULL);
+}
+
+/*
+ * Simple ring-buffer queue handler for reception of packets
+ * from network driver.
+ */
+#define PKTQ_MARKER 0xDEADBEEF
+
+static int pktq_check (struct rx_ringbuf *q)
+{
+#ifndef NDEBUG
+ int i;
+ char *buf;
+#endif
+
+ if (!q || !q->num_elem || !q->buf_start)
+ return (0);
+
+#ifndef NDEBUG
+ buf = q->buf_start;
+
+ for (i = 0; i < q->num_elem; i++)
+ {
+ buf += q->elem_size;
+ if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
+ return (0);
+ }
+#endif
+ return (1);
+}
+
+static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
+{
+ int i;
+
+ q->elem_size = size;
+ q->num_elem = num;
+ q->buf_start = pool;
+ q->in_index = 0;
+ q->out_index = 0;
+
+ PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
+ PCAP_ASSERT (num);
+ PCAP_ASSERT (pool);
+
+ for (i = 0; i < num; i++)
+ {
+#if 0
+ struct rx_elem *elem = (struct rx_elem*) pool;
+
+ /* assert dword aligned elements
+ */
+ PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
+#endif
+ pool += size;
+ *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
+ }
+ return (1);
+}
+
+/*
+ * Increment the queue 'out_index' (tail).
+ * Check for wraps.
+ */
+static int pktq_inc_out (struct rx_ringbuf *q)
+{
+ q->out_index++;
+ if (q->out_index >= q->num_elem)
+ q->out_index = 0;
+ return (q->out_index);
+}
+
+/*
+ * Return the queue's next 'in_index' (head).
+ * Check for wraps.
+ */
+static int pktq_in_index (struct rx_ringbuf *q)
+{
+ volatile int index = q->in_index + 1;
+
+ if (index >= q->num_elem)
+ index = 0;
+ return (index);
+}
+
+/*
+ * Return the queue's head-buffer.
+ */
+static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
+{
+ return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
+}
+
+/*
+ * Return the queue's tail-buffer.
+ */
+static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
+{
+ return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
+}
+
+/*
+ * Clear the queue ring-buffer by setting head=tail.
+ */
+static void pktq_clear (struct rx_ringbuf *q)
+{
+ q->in_index = q->out_index;
+}
+
+/*
+ * Symbols that must be linkable for "gcc -O0"
+ */
+#undef __IOPORT_H
+#undef __DMA_H
+
+#define extern
+#define __inline__
+
+#include "msdos/pm_drvr/ioport.h"
+#include "msdos/pm_drvr/dma.h"
+
+#endif /* USE_32BIT_DRIVERS */
+
diff --git a/contrib/libpcap/pcap-dos.h b/contrib/libpcap/pcap-dos.h
new file mode 100644
index 000000000000..c9737baec3eb
--- /dev/null
+++ b/contrib/libpcap/pcap-dos.h
@@ -0,0 +1,227 @@
+/*
+ * Internal details for libpcap on DOS.
+ * 32-bit targets: djgpp, Pharlap or DOS4GW.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.h,v 1.1 2004/12/18 08:52:10 guy Exp $ (LBL)
+ */
+
+#ifndef __PCAP_DOS_H
+#define __PCAP_DOS_H
+
+#ifdef __DJGPP__
+#include <pc.h> /* simple non-conio kbhit */
+#else
+#include <conio.h>
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef BYTE ETHER[6];
+
+#define ETH_ALEN sizeof(ETHER) /* Ether address length */
+#define ETH_HLEN (2*ETH_ALEN+2) /* Ether header length */
+#define ETH_MTU 1500
+#define ETH_MIN 60
+#define ETH_MAX (ETH_MTU+ETH_HLEN)
+
+#ifndef TRUE
+ #define TRUE 1
+ #define FALSE 0
+#endif
+
+#define PHARLAP 1
+#define DJGPP 2
+#define DOS4GW 4
+
+#ifdef __DJGPP__
+ #undef DOSX
+ #define DOSX DJGPP
+#endif
+
+#ifdef __WATCOMC__
+ #undef DOSX
+ #define DOSX DOS4GW
+#endif
+
+#ifdef __HIGHC__
+ #include <pharlap.h>
+ #undef DOSX
+ #define DOSX PHARLAP
+ #define inline
+#else
+ typedef unsigned int UINT;
+#endif
+
+
+#if defined(__GNUC__) || defined(__HIGHC__)
+ typedef unsigned long long uint64;
+ typedef unsigned long long QWORD;
+#endif
+
+#if defined(__WATCOMC__)
+ typedef unsigned __int64 uint64;
+ typedef unsigned __int64 QWORD;
+#endif
+
+#define ARGSUSED(x) (void) x
+
+#if defined (__SMALL__) || defined(__LARGE__)
+ #define DOSX 0
+
+#elif !defined(DOSX)
+ #error DOSX not defined; 1 = PharLap, 2 = djgpp, 4 = DOS4GW
+#endif
+
+#ifdef __HIGHC__
+#define min(a,b) _min(a,b)
+#define max(a,b) _max(a,b)
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+#if !defined(_U_) && defined(__GNUC__)
+#define _U_ __attribute__((unused))
+#endif
+
+#ifndef _U_
+#define _U_
+#endif
+
+#if defined(USE_32BIT_DRIVERS)
+ #include "msdos/pm_drvr/lock.h"
+
+ #ifndef RECEIVE_QUEUE_SIZE
+ #define RECEIVE_QUEUE_SIZE 60
+ #endif
+
+ #ifndef RECEIVE_BUF_SIZE
+ #define RECEIVE_BUF_SIZE (ETH_MAX+20)
+ #endif
+
+ extern struct device el2_dev LOCKED_VAR; /* 3Com EtherLink II */
+ extern struct device el3_dev LOCKED_VAR; /* EtherLink III */
+ extern struct device tc59_dev LOCKED_VAR; /* 3Com Vortex Card (?) */
+ extern struct device tc515_dev LOCKED_VAR;
+ extern struct device tc90x_dev LOCKED_VAR;
+ extern struct device tc90bcx_dev LOCKED_VAR;
+ extern struct device wd_dev LOCKED_VAR;
+ extern struct device ne_dev LOCKED_VAR;
+ extern struct device acct_dev LOCKED_VAR;
+ extern struct device cs89_dev LOCKED_VAR;
+ extern struct device rtl8139_dev LOCKED_VAR;
+
+ struct rx_ringbuf {
+ volatile int in_index; /* queue index head */
+ int out_index; /* queue index tail */
+ int elem_size; /* size of each element */
+ int num_elem; /* number of elements */
+ char *buf_start; /* start of buffer pool */
+ };
+
+ struct rx_elem {
+ DWORD size; /* size copied to this element */
+ BYTE data[ETH_MAX+10]; /* add some margin. data[0] should be */
+ }; /* dword aligned */
+
+ extern BYTE *get_rxbuf (int len) LOCKED_FUNC;
+ extern int peek_rxbuf (BYTE **buf);
+ extern int release_rxbuf (BYTE *buf);
+
+#else
+ #define LOCKED_VAR
+ #define LOCKED_FUNC
+
+ struct device {
+ const char *name;
+ const char *long_name;
+ DWORD base_addr; /* device I/O address */
+ int irq; /* device IRQ number */
+ int dma; /* DMA channel */
+ DWORD mem_start; /* shared mem start */
+ DWORD mem_end; /* shared mem end */
+ DWORD rmem_start; /* shmem "recv" start */
+ DWORD rmem_end; /* shared "recv" end */
+
+ struct device *next; /* next device in list */
+
+ /* interface service routines */
+ int (*probe)(struct device *dev);
+ int (*open) (struct device *dev);
+ void (*close)(struct device *dev);
+ int (*xmit) (struct device *dev, const void *buf, int len);
+ void *(*get_stats)(struct device *dev);
+ void (*set_multicast_list)(struct device *dev);
+
+ /* driver-to-pcap receive buffer routines */
+ int (*copy_rx_buf) (BYTE *buf, int max); /* rx-copy (pktdrvr only) */
+ BYTE *(*get_rx_buf) (int len); /* rx-buf fetch/enqueue */
+ int (*peek_rx_buf) (BYTE **buf); /* rx-non-copy at queue */
+ int (*release_rx_buf) (BYTE *buf); /* release after peek */
+
+ WORD flags; /* Low-level status flags. */
+ void *priv; /* private data */
+ };
+
+ /*
+ * Network device statistics
+ */
+ typedef struct net_device_stats {
+ DWORD rx_packets; /* total packets received */
+ DWORD tx_packets; /* total packets transmitted */
+ DWORD rx_bytes; /* total bytes received */
+ DWORD tx_bytes; /* total bytes transmitted */
+ DWORD rx_errors; /* bad packets received */
+ DWORD tx_errors; /* packet transmit problems */
+ DWORD rx_dropped; /* no space in Rx buffers */
+ DWORD tx_dropped; /* no space available for Tx */
+ DWORD multicast; /* multicast packets received */
+
+ /* detailed rx_errors: */
+ DWORD rx_length_errors;
+ DWORD rx_over_errors; /* recv'r overrun error */
+ DWORD rx_osize_errors; /* recv'r over-size error */
+ DWORD rx_crc_errors; /* recv'd pkt with crc error */
+ DWORD rx_frame_errors; /* recv'd frame alignment error */
+ DWORD rx_fifo_errors; /* recv'r fifo overrun */
+ DWORD rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ DWORD tx_aborted_errors;
+ DWORD tx_carrier_errors;
+ DWORD tx_fifo_errors;
+ DWORD tx_heartbeat_errors;
+ DWORD tx_window_errors;
+ DWORD tx_collisions;
+ DWORD tx_jabbers;
+ } NET_STATS;
+#endif
+
+extern struct device *active_dev LOCKED_VAR;
+extern const struct device *dev_base LOCKED_VAR;
+extern struct device *probed_dev;
+
+extern int pcap_pkt_debug;
+
+extern void _w32_os_yield (void); /* Watt-32's misc.c */
+
+#ifdef NDEBUG
+ #define PCAP_ASSERT(x) ((void)0)
+
+#else
+ void pcap_assert (const char *what, const char *file, unsigned line);
+
+ #define PCAP_ASSERT(x) do { \
+ if (!(x)) \
+ pcap_assert (#x, __FILE__, __LINE__); \
+ } while (0)
+#endif
+
+#endif /* __PCAP_DOS_H */
diff --git a/contrib/libpcap/pcap-enet.c b/contrib/libpcap/pcap-enet.c
index bbfe3e555714..a48420718d08 100644
--- a/contrib/libpcap/pcap-enet.c
+++ b/contrib/libpcap/pcap-enet.c
@@ -8,7 +8,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.7.2.1 2003/11/15 23:26:44 guy Exp $";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.8 2003/11/15 23:24:02 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h
index c56553c3f692..a64fc3cb16e8 100644
--- a/contrib/libpcap/pcap-int.h
+++ b/contrib/libpcap/pcap-int.h
@@ -30,7 +30,7 @@
* 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.55.2.4 2003/12/15 01:42:24 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68 2004/12/18 08:52:10 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
@@ -46,6 +46,11 @@ extern "C" {
#include <packet32.h>
#endif /* WIN32 */
+#ifdef MSDOS
+#include <fcntl.h>
+#include <io.h>
+#endif
+
/*
* Savefile
*/
@@ -74,13 +79,14 @@ struct pcap_md {
u_long TotDrops; /* count of dropped packets */
long TotMissed; /* missed by i/f during this run */
long OrigMissed; /* missed by i/f before this run */
+ char *device; /* device name */
#ifdef linux
int sock_packet; /* using Linux 2.0 compatible interface */
int timeout; /* timeout specified to pcap_open_live */
int clear_promisc; /* must clear promiscuous mode when we close */
int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
+ int ifindex; /* interface index of device we're bound to */
int lo_ifindex; /* interface index of the loopback device */
- char *device; /* device name */
struct pcap *next; /* list of open promiscuous sock_packet pcaps */
#endif
@@ -89,7 +95,7 @@ struct pcap_md {
u_int dag_mem_bottom; /* DAG card current memory bottom pointer */
u_int dag_mem_top; /* DAG card current memory top pointer */
int dag_fcs_bits; /* Number of checksum bits from link layer */
- int dag_offset_flags; /* Flags to pass to dag_offset(). */
+ int dag_offset_flags; /* Flags to pass to dag_offset(). */
#endif
};
@@ -102,6 +108,7 @@ struct pcap {
#else
int fd;
int selectable_fd;
+ int send_fd;
#endif /* WIN32 */
int snapshot;
int linktype;
@@ -110,6 +117,15 @@ struct pcap {
int break_loop; /* flag set to force break from packet-reading loop */
+#ifdef PCAP_FDDIPAD
+ int fddipad;
+#endif
+
+#ifdef MSDOS
+ int inter_packet_wait; /* offline: wait between packets */
+ void (*wait_proc)(void); /* call proc while waiting */
+#endif
+
struct pcap_sf sf;
struct pcap_md md;
@@ -130,6 +146,7 @@ struct pcap {
* Methods.
*/
int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
+ int (*inject_op)(pcap_t *, const void *, size_t);
int (*setfilter_op)(pcap_t *, struct bpf_program *);
int (*set_datalink_op)(pcap_t *, int);
int (*getnonblock_op)(pcap_t *, char *);
@@ -144,7 +161,7 @@ struct pcap {
char errbuf[PCAP_ERRBUF_SIZE + 1];
int dlt_count;
- int *dlt_list;
+ u_int *dlt_list;
struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
};
@@ -252,11 +269,13 @@ extern int vsnprintf (char *, size_t, const char *, va_list ap);
/*
* Routines that most pcap implementations can use for non-blocking mode.
*/
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
int pcap_getnonblock_fd(pcap_t *, char *);
int pcap_setnonblock_fd(pcap_t *p, int, char *);
#endif
+void pcap_close_common(pcap_t *);
+
/*
* Internal interfaces for "pcap_findalldevs()".
*
@@ -267,10 +286,10 @@ int pcap_setnonblock_fd(pcap_t *p, int, char *);
* "pcap_add_if()" adds an interface to the list of interfaces.
*/
int pcap_platform_finddevs(pcap_if_t **, char *);
-int add_addr_to_iflist(pcap_if_t **, char *, u_int, struct sockaddr *,
+int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *,
size_t, struct sockaddr *, size_t, struct sockaddr *, size_t,
struct sockaddr *, size_t, char *);
-int pcap_add_if(pcap_if_t **, char *, u_int, const char *, char *);
+int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *);
struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
const char *, char *);
@@ -279,9 +298,6 @@ int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
char *pcap_win32strerror(void);
#endif
-/* XXX */
-extern int pcap_fddipad;
-
int install_bpf_program(pcap_t *, struct bpf_program *);
int pcap_strcasecmp(const char *, const char *);
diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c
index df1b64686aeb..89ad5c48eec8 100644
--- a/contrib/libpcap/pcap-linux.c
+++ b/contrib/libpcap/pcap-linux.c
@@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.98.2.4 2003/11/21 10:20:46 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110 2004/10/19 07:06:12 guy Exp $ (LBL)";
#endif
/*
@@ -188,6 +188,7 @@ static int live_open_old(pcap_t *, const char *, int, int, char *);
static int live_open_new(pcap_t *, const char *, int, int, char *);
static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
+static int pcap_inject_linux(pcap_t *, const void *, size_t);
static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
static void pcap_close_linux(pcap_t *);
@@ -404,6 +405,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
handle->selectable_fd = handle->fd;
handle->read_op = pcap_read_linux;
+ handle->inject_op = pcap_inject_linux;
handle->setfilter_op = pcap_setfilter_linux;
handle->set_datalink_op = NULL; /* can't change data link type */
handle->getnonblock_op = pcap_getnonblock_fd;
@@ -672,6 +674,49 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
return 1;
}
+static int
+pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+ int ret;
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+ if (!handle->md.sock_packet) {
+ /* PF_PACKET socket */
+ if (handle->md.ifindex == -1) {
+ /*
+ * We don't support sending on the "any" device.
+ */
+ strlcpy(handle->errbuf,
+ "Sending packets isn't supported on the \"any\" device",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+
+ if (handle->md.cooked) {
+ /*
+ * We don't support sending on the "any" device.
+ *
+ * XXX - how do you send on a bound cooked-mode
+ * socket?
+ * Is a "sendto()" required there?
+ */
+ strlcpy(handle->errbuf,
+ "Sending packets isn't supported in cooked mode",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+ }
+#endif
+
+ ret = send(handle->fd, buf, size, 0);
+ if (ret == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
/*
* Get the statistics for the given packet capture handle.
* Reports the number of dropped packets iff the kernel supports
@@ -717,9 +762,13 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* platforms, but the best approximation is to return
* "tp_packets" as the count of packets and "tp_drops"
* as the count of drops.
+ *
+ * Keep a running total because each call to
+ * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
+ * resets the counters to zero.
*/
- handle->md.stat.ps_recv = kstats.tp_packets;
- handle->md.stat.ps_drop = kstats.tp_drops;
+ handle->md.stat.ps_recv += kstats.tp_packets;
+ handle->md.stat.ps_drop += kstats.tp_drops;
}
else
{
@@ -948,6 +997,34 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
switch (arptype) {
case ARPHRD_ETHER:
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ *
+ * XXX - are there any sorts of "fake Ethernet" that have
+ * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
+ * a Cisco CMTS won't put traffic onto it or get traffic
+ * bridged onto it? ISDN is handled in "live_open_new()",
+ * as we fall back on cooked mode there; are there any
+ * others?
+ */
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_EN10MB;
+ handle->dlt_list[1] = DLT_DOCSIS;
+ handle->dlt_count = 2;
+ }
+ /* FALLTHROUGH */
+
case ARPHRD_METRICOM:
case ARPHRD_LOOPBACK:
handle->linktype = DLT_EN10MB;
@@ -1163,6 +1240,9 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
handle->linktype = DLT_IP_OVER_FC;
break;
+#ifndef ARPHRD_IRDA
+#define ARPHRD_IRDA 783
+#endif
case ARPHRD_IRDA:
/* Don't expect IP packet out of this interfaces... */
handle->linktype = DLT_LINUX_IRDA;
@@ -1189,7 +1269,7 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
int to_ms, char *ebuf)
{
#ifdef HAVE_PF_PACKET_SOCKETS
- int sock_fd = -1, device_id, arptype;
+ int sock_fd = -1, arptype;
int err;
int fatal_err = 0;
struct packet_mreq mr;
@@ -1278,6 +1358,17 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
}
handle->md.cooked = 1;
+ /*
+ * Get rid of any link-layer type list
+ * we allocated - this only supports cooked
+ * capture.
+ */
+ if (handle->dlt_list != NULL) {
+ free(handle->dlt_list);
+ handle->dlt_list = NULL;
+ handle->dlt_count = 0;
+ }
+
if (handle->linktype == -1) {
/*
* Warn that we're falling back on
@@ -1294,15 +1385,16 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
}
/* IrDA capture is not a real "cooked" capture,
* it's IrLAP frames, not IP packets. */
- if(handle->linktype != DLT_LINUX_IRDA)
+ if (handle->linktype != DLT_LINUX_IRDA)
handle->linktype = DLT_LINUX_SLL;
}
- device_id = iface_get_id(sock_fd, device, ebuf);
- if (device_id == -1)
+ handle->md.ifindex = iface_get_id(sock_fd, device, ebuf);
+ if (handle->md.ifindex == -1)
break;
- if ((err = iface_bind(sock_fd, device_id, ebuf)) < 0) {
+ if ((err = iface_bind(sock_fd, handle->md.ifindex,
+ ebuf)) < 0) {
if (err == -2)
fatal_err = 1;
break;
@@ -1315,14 +1407,15 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
handle->linktype = DLT_LINUX_SLL;
/*
- * XXX - squelch GCC complaints about
- * uninitialized variables; if we can't
- * select promiscuous mode on all interfaces,
- * we should move the code below into the
- * "if (device)" branch of the "if" and
- * get rid of the next statement.
+ * We're not bound to a device.
+ * XXX - true? Or true only if we're using
+ * the "any" device?
+ * For now, we're using this as an indication
+ * that we can't transmit; stop doing that only
+ * if we figure out how to transmit in cooked
+ * mode.
*/
- device_id = -1;
+ handle->md.ifindex = -1;
}
/*
@@ -1346,7 +1439,7 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
if (device && promisc) {
memset(&mr, 0, sizeof(mr));
- mr.mr_ifindex = device_id;
+ mr.mr_ifindex = handle->md.ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock_fd, SOL_PACKET,
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
@@ -1368,9 +1461,14 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
if (sock_fd != -1)
close(sock_fd);
- if (fatal_err)
+ if (fatal_err) {
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (handle->dlt_list != NULL)
+ free(handle->dlt_list);
return -2;
- else
+ } else
return 0;
#else
strncpy(ebuf,
@@ -1546,10 +1644,7 @@ static void pcap_close_linux( pcap_t *handle )
if (handle->md.device != NULL)
free(handle->md.device);
handle->md.device = NULL;
- if (handle->buffer != NULL)
- free(handle->buffer);
- if (handle->fd >= 0)
- close(handle->fd);
+ pcap_close_common(handle);
}
/*
diff --git a/contrib/libpcap/pcap-namedb.h b/contrib/libpcap/pcap-namedb.h
index 4833c4da00c5..29b217dde89b 100644
--- a/contrib/libpcap/pcap-namedb.h
+++ b/contrib/libpcap/pcap-namedb.h
@@ -30,11 +30,11 @@
* 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.8 2000/07/29 07:36:43 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10 2005/03/17 07:02:32 guy Exp $ (LBL)
*/
-#ifndef lib_pcap_ethers_h
-#define lib_pcap_ethers_h
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
#ifdef __cplusplus
extern "C" {
@@ -67,6 +67,7 @@ bpf_u_int32 pcap_nametonetaddr(const char *);
int pcap_nametoport(const char *, int *, int *);
int pcap_nametoproto(const char *);
int pcap_nametoeproto(const char *);
+int pcap_nametollc(const char *);
/*
* If a protocol is unknown, PROTO_UNDEF is returned.
* Also, pcap_nametoport() returns the protocol along with the port number.
diff --git a/contrib/libpcap/pcap-nit.c b/contrib/libpcap/pcap-nit.c
index 86aad0ffe845..097c3be482e1 100644
--- a/contrib/libpcap/pcap-nit.c
+++ b/contrib/libpcap/pcap-nit.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.50.2.4 2004/03/21 08:33:23 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57 2004/10/19 07:06:13 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -193,6 +193,23 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
static int
+pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
+{
+ struct sockaddr sa;
+ int ret;
+
+ memset(&sa, 0, sizeof(sa));
+ strncpy(sa.sa_data, device, sizeof(sa.sa_data));
+ ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
struct nit_ioc nioc;
@@ -224,10 +241,9 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
static void
pcap_close_nit(pcap_t *p)
{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
+ pcap_close_common(p);
+ if (p->device != NULL)
+ free(p->device);
}
pcap_t *
@@ -281,11 +297,42 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
/*
+ * We need the device name in order to send packets.
+ */
+ p->device = strdup(device);
+ if (p->device == NULL) {
+ strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+ free(p->buffer);
+ goto bad;
+ }
+
+ /*
* "p->fd" is a socket, so "select()" should work on it.
*/
p->selectable_fd = p->fd;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+
p->read_op = pcap_read_nit;
+ p->inject_op = pcap_inject_nit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
diff --git a/contrib/libpcap/pcap-null.c b/contrib/libpcap/pcap-null.c
index a4dd72f3f276..06e3ab3ac4ed 100644
--- a/contrib/libpcap/pcap-null.c
+++ b/contrib/libpcap/pcap-null.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.20.2.1 2003/11/15 23:26:45 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21 2003/11/15 23:24:03 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c
index e84d1c7db1b7..1c3158aeba39 100644
--- a/contrib/libpcap/pcap-pf.c
+++ b/contrib/libpcap/pcap-pf.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.79.2.5 2003/11/22 00:32:55 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91 2005/02/26 21:58:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -129,10 +129,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
*/
n = 0;
#ifdef PCAP_FDDIPAD
- if (pc->linktype == DLT_FDDI)
- pad = pcap_fddipad;
- else
- pad = 0;
+ pad = p->fddipad;
#endif
while (cc > 0) {
/*
@@ -182,10 +179,6 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
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;
@@ -195,6 +188,14 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now.
+ *
+#ifdef PCAP_FDDIPAD
+ * Note: the filter code was generated assuming
+ * that p->fddipad was the amount of padding
+ * before the header, as that's what's required
+ * in the kernel, so we run the filter before
+ * skipping that padding.
+#endif
*/
if (fcode == NULL ||
bpf_filter(fcode, p, sp->ens_count, buflen)) {
@@ -206,6 +207,10 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
#else
h.len = sp->ens_count;
#endif
+#ifdef PCAP_FDDIPAD
+ p += pad;
+ buflen -= pad;
+#endif
h.caplen = buflen;
(*callback)(user, &h, p);
if (++n >= cnt && cnt > 0) {
@@ -220,6 +225,20 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
}
static int
+pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
{
@@ -265,14 +284,13 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
return (0);
}
-static void
-pcap_close_pf(pcap_t *p)
-{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
-}
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS 143
+#endif
pcap_t *
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
@@ -291,14 +309,28 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
return (0);
}
memset(p, 0, sizeof(*p));
-
/*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ *
* XXX - we assume here that "pfopen()" does not, in fact, modify
* its argument, even though it takes a "char *" rather than a
* "const char *" as its first argument. That appears to be
* the case, at least on Digital UNIX 4.0.
*/
- p->fd = pfopen(device, O_RDONLY);
+ p->fd = pfopen(device, O_RDWR);
+ if (p->fd == -1 && errno == EACCES)
+ p->fd = pfopen(device, O_RDONLY);
if (p->fd < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
your system may not be properly configured; see the packetfilter(4) man page\n",
@@ -340,6 +372,25 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
case ENDT_10MB:
p->linktype = DLT_EN10MB;
p->offset = 2;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
break;
case ENDT_FDDI:
@@ -396,9 +447,13 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
}
/* set truncation */
#ifdef PCAP_FDDIPAD
- if (p->linktype == DLT_FDDI)
+ if (p->linktype == DLT_FDDI) {
+ p->fddipad = PCAP_FDDIPAD:
+
/* packetfilter includes the padding in the snapshot */
- snaplen += pcap_fddipad;
+ snaplen += PCAP_FDDIPAD;
+ } else
+ p->fddipad = 0;
#endif
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
@@ -440,17 +495,23 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->selectable_fd = p->fd;
p->read_op = pcap_read_pf;
+ p->inject_op = pcap_inject_pf;
p->setfilter_op = pcap_setfilter_pf;
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_pf;
- p->close_op = pcap_close_pf;
+ p->close_op = pcap_close_common;
return (p);
bad:
if (p->fd >= 0)
close(p->fd);
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
return (NULL);
}
@@ -506,6 +567,16 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
*/
fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
p->md.use_bpf = 1;
+
+ /*
+ * Discard any previously-received packets,
+ * as they might have passed whatever filter
+ * was formerly in effect, but might not pass
+ * this filter (BIOCSETF discards packets buffered
+ * in the kernel, so you can lose packets in any
+ * case).
+ */
+ p->cc = 0;
return (0);
}
diff --git a/contrib/libpcap/pcap-snit.c b/contrib/libpcap/pcap-snit.c
index d022dd3e79b2..47bf443ab7a4 100644
--- a/contrib/libpcap/pcap-snit.c
+++ b/contrib/libpcap/pcap-snit.c
@@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.66.2.3 2003/11/21 10:20:48 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72 2004/10/19 07:06:13 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -205,6 +205,29 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
static int
+pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
+{
+ struct strbuf ctl, data;
+
+ /*
+ * XXX - can we just do
+ *
+ ret = write(pd->f, buf, size);
+ */
+ ctl.len = sizeof(*sa); /* XXX - what was this? */
+ ctl.buf = (char *)sa;
+ data.buf = buf;
+ data.len = size;
+ ret = putmsg(p->fd, &ctl, &data);
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
bpf_u_int32 flags;
@@ -238,15 +261,6 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
return (0);
}
-static void
-pcap_close_snit(pcap_t *p)
-{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
-}
-
pcap_t *
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
char *ebuf)
@@ -271,7 +285,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
snaplen = 96;
memset(p, 0, sizeof(*p));
- p->fd = fd = open(dev, O_RDONLY);
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ p->fd = fd = open(dev, O_RDWR);
+ if (fd < 0 && errno == EACCES)
+ p->fd = fd = open(dev, O_RDONLY);
if (fd < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
pcap_strerror(errno));
@@ -344,13 +374,34 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
p->selectable_fd = p->fd;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+
p->read_op = pcap_read_snit;
+ p->inject_op = pcap_inject_snit;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_snit;
- p->close_op = pcap_close_snit;
+ p->close_op = pcap_close_common;
return (p);
bad:
diff --git a/contrib/libpcap/pcap-snoop.c b/contrib/libpcap/pcap-snoop.c
index 1260bd74194f..acbe548f6edc 100644
--- a/contrib/libpcap/pcap-snoop.c
+++ b/contrib/libpcap/pcap-snoop.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.45.2.5 2004/03/21 08:33:24 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54 2004/10/19 07:06:14 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -63,8 +63,8 @@ pcap_read_snoop(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_int datalen;
+ register u_int caplen;
register u_char *cp;
again:
@@ -97,6 +97,16 @@ again:
}
sh = (struct snoopheader *)p->buffer;
datalen = sh->snoop_packetlen;
+
+ /*
+ * XXX - Sigh, snoop_packetlen is a 16 bit quantity. If we
+ * got a short length, but read a full sized snoop pakcet,
+ * assume we overflowed and add back the 64K...
+ */
+ if (cc == (p->snapshot + sizeof(struct snoopheader)) &&
+ (datalen < p->snapshot))
+ datalen += (64 * 1024);
+
caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
cp = (u_char *)(sh + 1) + p->offset; /* XXX */
@@ -126,6 +136,24 @@ again:
}
static int
+pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ /*
+ * XXX - libnet overwrites the source address with what I
+ * presume is the interface's address; is that required?
+ */
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
{
register struct rawstats *rs;
@@ -165,15 +193,6 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
return (0);
}
-static void
-pcap_close_snoop(pcap_t *p)
-{
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->fd >= 0)
- close(p->fd);
-}
-
/* XXX can't disable promiscuous */
pcap_t *
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
@@ -237,6 +256,35 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->linktype = DLT_EN10MB;
p->offset = RAW_HDRPAD(sizeof(struct ether_header));
ll_hdrlen = sizeof(struct ether_header);
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ *
+ * XXX - are there any sorts of "fake Ethernet" that have
+ * Ethernet link-layer headers but that *shouldn't offer
+ * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it
+ * or get traffic bridged onto it? "el" is for ATM LANE
+ * Ethernet devices, so that might be the case for them;
+ * the same applies for "qaa" classical IP devices. If
+ * "fa" devices are for FORE SPANS, that'd apply to them
+ * as well; what are "cip" devices - some other ATM
+ * Classical IP devices?
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
} else if (strncmp("ipg", device, 3) == 0 ||
strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */
strncmp("xpi", device, 3) == 0) {
@@ -329,16 +377,22 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->selectable_fd = p->fd;
p->read_op = pcap_read_snoop;
+ p->inject_op = pcap_inject_snoop;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_snoop;
- p->close_op = pcap_close_snoop;
+ p->close_op = pcap_close_common;
return (p);
bad:
(void)close(fd);
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
return (NULL);
}
diff --git a/contrib/libpcap/pcap-win32.c b/contrib/libpcap/pcap-win32.c
index ef1b0f35697d..cb6c6966e19b 100644
--- a/contrib/libpcap/pcap-win32.c
+++ b/contrib/libpcap/pcap-win32.c
@@ -32,24 +32,32 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.15.2.3 2003/11/30 02:32:02 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25 2005/02/26 21:58:06 guy Exp $ (LBL)";
#endif
#include <pcap-int.h>
#include <packet32.h>
#include <Ntddndis.h>
+#ifdef HAVE_DAG_API
+#include <dagnew.h>
+#include <dagapi.h>
+#endif /* HAVE_DAG_API */
#ifdef __MINGW32__
int* _errno();
#define errno (*_errno())
#endif /* __MINGW32__ */
-static int pcap_setfilter_win32(pcap_t *, struct bpf_program *);
+static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
+static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
static int pcap_getnonblock_win32(pcap_t *, char *);
static int pcap_setnonblock_win32(pcap_t *, int, char *);
#define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
#define SIZE_BUF 1000000
+/* Equivalent to ntohs(), but a lot faster under Windows */
+#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
+
/*
* Header that the WinPcap driver associates to the packets.
* Once was in bpf.h
@@ -92,7 +100,7 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
}
static int
-pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int cc;
int n = 0;
@@ -175,16 +183,209 @@ pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (n);
}
+#ifdef HAVE_DAG_API
+static int
+pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ u_char *dp = NULL;
+ int packet_len = 0, caplen = 0;
+ struct pcap_pkthdr pcap_header;
+ u_char *endofbuf;
+ int n = 0;
+ dag_record_t *header;
+ unsigned erf_record_len;
+ ULONGLONG ts;
+ int cc;
+ unsigned swt;
+ unsigned dfp = p->adapter->DagFastProcess;
+
+ cc = p->cc;
+ if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
+ {
+ /* Get new packets from the network */
+ if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+ return (-1);
+ }
+
+ cc = p->Packet->ulBytesReceived;
+ if(cc == 0)
+ /* The timeout has expired but we no packets arrived */
+ return 0;
+ header = (dag_record_t*)p->adapter->DagBuffer;
+ }
+ else
+ header = (dag_record_t*)p->bp;
+
+ endofbuf = (char*)header + cc;
+
+ /*
+ * Cycle through the packets
+ */
+ do
+ {
+ erf_record_len = SWAPS(header->rlen);
+ if((char*)header + erf_record_len > endofbuf)
+ break;
+
+ /* Increase the number of captured packets */
+ p->md.stat.ps_recv++;
+
+ /* Find the beginning of the packet */
+ dp = ((u_char *)header) + dag_record_size;
+
+ /* Determine actual packet len */
+ switch(header->type)
+ {
+ case TYPE_ATM:
+ packet_len = ATM_SNAPLEN;
+ caplen = ATM_SNAPLEN;
+ dp += 4;
+
+ break;
+
+ case TYPE_ETH:
+ swt = SWAPS(header->wlen);
+ packet_len = swt - (p->md.dag_fcs_bits);
+ caplen = erf_record_len - dag_record_size - 2;
+ if (caplen > packet_len)
+ {
+ caplen = packet_len;
+ }
+ dp += 2;
+
+ break;
+
+ case TYPE_HDLC_POS:
+ swt = SWAPS(header->wlen);
+ packet_len = swt - (p->md.dag_fcs_bits);
+ caplen = erf_record_len - dag_record_size;
+ if (caplen > packet_len)
+ {
+ caplen = packet_len;
+ }
+
+ break;
+ }
+
+ if(caplen > p->snapshot)
+ caplen = p->snapshot;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop)
+ {
+ if (n == 0)
+ {
+ p->break_loop = 0;
+ return (-2);
+ }
+ else
+ {
+ p->bp = (char*)header;
+ p->cc = endofbuf - (char*)header;
+ return (n);
+ }
+ }
+
+ if(!dfp)
+ {
+ /* convert between timestamp formats */
+ ts = header->ts;
+ pcap_header.ts.tv_sec = (int)(ts >> 32);
+ ts = (ts & 0xffffffffi64) * 1000000;
+ ts += 0x80000000; /* rounding */
+ pcap_header.ts.tv_usec = (int)(ts >> 32);
+ if (pcap_header.ts.tv_usec >= 1000000) {
+ pcap_header.ts.tv_usec -= 1000000;
+ pcap_header.ts.tv_sec++;
+ }
+ }
+
+ /* No underlaying filtering system. We need to filter on our own */
+ if (p->fcode.bf_insns)
+ {
+ if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
+ {
+ /* Move to next packet */
+ header = (dag_record_t*)((char*)header + erf_record_len);
+ continue;
+ }
+ }
+
+ /* Fill the header for the user suppplied callback function */
+ pcap_header.caplen = caplen;
+ pcap_header.len = packet_len;
+
+ /* Call the callback function */
+ (*callback)(user, &pcap_header, dp);
+
+ /* Move to next packet */
+ header = (dag_record_t*)((char*)header + erf_record_len);
+
+ /* Stop if the number of packets requested by user has been reached*/
+ if (++n >= cnt && cnt > 0)
+ {
+ p->bp = (char*)header;
+ p->cc = endofbuf - (char*)header;
+ return (n);
+ }
+ }
+ while((u_char*)header < endofbuf);
+
+ return 1;
+}
+#endif /* HAVE_DAG_API */
+
+/* Send a packet to the network */
+static int
+pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
+ LPPACKET PacketToSend;
+
+ PacketToSend=PacketAllocatePacket();
+
+ if (PacketToSend == NULL)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
+ return -1;
+ }
+
+ PacketInitPacket(PacketToSend,(PVOID)buf,size);
+ if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+ PacketFreePacket(PacketToSend);
+ return -1;
+ }
+
+ PacketFreePacket(PacketToSend);
+
+ /*
+ * We assume it all got sent if "PacketSendPacket()" succeeded.
+ * "pcap_inject()" is expected to return the number of bytes
+ * sent.
+ */
+ return size;
+}
static void
pcap_close_win32(pcap_t *p)
{
- if (p->buffer != NULL)
- free(p->buffer);
+ pcap_close_common(p);
if (p->adapter != NULL) {
PacketCloseAdapter(p->adapter);
p->adapter = NULL;
}
+ if (p->Packet) {
+ PacketFreePacket(p->Packet);
+ p->Packet = NULL;
+ }
}
pcap_t *
@@ -231,6 +432,25 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
case NdisMedium802_3:
p->linktype = DLT_EN10MB;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
break;
case NdisMediumFddi:
@@ -253,6 +473,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->linktype = DLT_ATM_RFC1483;
break;
+ case NdisMediumCHDLC:
+ p->linktype = DLT_CHDLC;
+ break;
+
+ case NdisMediumPPPSerial:
+ p->linktype = DLT_PPP_SERIAL;
+ break;
+
+ case NdisMediumNull:
+ p->linktype = DLT_NULL;
+ break;
+
default:
p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
break;
@@ -265,15 +497,6 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/* Set the buffer size */
p->bufsize = PcapBufSize;
- p->buffer = (u_char *)malloc(PcapBufSize);
- if (p->buffer == NULL)
- {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
- goto bad;
- }
-
- p->snapshot = snaplen;
-
/* allocate Packet structure used during the capture */
if((p->Packet = PacketAllocatePacket())==NULL)
{
@@ -281,26 +504,105 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad;
}
- PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
-
- /* allocate the standard buffer in the driver */
- if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
+ if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
- goto bad;
+ /*
+ * Traditional Adapter
+ */
+
+ p->buffer = (u_char *)malloc(PcapBufSize);
+ if (p->buffer == NULL)
+ {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ goto bad;
+ }
+
+ PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
+
+ p->snapshot = snaplen;
+
+ /* allocate the standard buffer in the driver */
+ if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
+ {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
+ goto bad;
+ }
+
+ /* tell the driver to copy the buffer only if it contains at least 16K */
+ if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
+ {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
+ goto bad;
+ }
}
-
- /* tell the driver to copy the buffer only if it contains at least 16K */
- if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
+ else
+#ifdef HAVE_DAG_API
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
- goto bad;
+ /*
+ * Dag Card
+ */
+ LONG status;
+ HKEY dagkey;
+ DWORD lptype;
+ DWORD lpcbdata;
+ int postype = 0;
+ char keyname[512];
+
+ snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+ "SYSTEM\\CurrentControlSet\\Services\\DAG",
+ strstr(_strlwr((char*)device), "dag"));
+ do
+ {
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
+ if(status != ERROR_SUCCESS)
+ break;
+
+ status = RegQueryValueEx(dagkey,
+ "PosType",
+ NULL,
+ &lptype,
+ (char*)&postype,
+ &lpcbdata);
+
+ if(status != ERROR_SUCCESS)
+ {
+ postype = 0;
+ }
+
+ RegCloseKey(dagkey);
+ }
+ while(FALSE);
+
+
+ p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
+
+ /* Set the length of the FCS associated to any packet. This value
+ * will be subtracted to the packet length */
+ p->md.dag_fcs_bits = p->adapter->DagFcsLen;
}
-
+#else
+ goto bad;
+#endif /* HAVE_DAG_API */
+
PacketSetReadTimeout(p->adapter, to_ms);
-
- p->read_op = pcap_read_win32;
- p->setfilter_op = pcap_setfilter_win32;
+
+#ifdef HAVE_DAG_API
+ if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
+ {
+ /* install dag specific handlers for read and setfilter */
+ p->read_op = pcap_read_win32_dag;
+ p->setfilter_op = pcap_setfilter_win32_dag;
+ }
+ else
+ {
+#endif /* HAVE_DAG_API */
+ /* install traditional npf handlers for read and setfilter */
+ p->read_op = pcap_read_win32_npf;
+ p->setfilter_op = pcap_setfilter_win32_npf;
+#ifdef HAVE_DAG_API
+ }
+#endif /* HAVE_DAG_API */
+ p->inject_op = pcap_inject_win32;
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_win32;
p->setnonblock_op = pcap_setnonblock_win32;
@@ -313,22 +615,65 @@ bad:
PacketCloseAdapter(p->adapter);
if (p->buffer != NULL)
free(p->buffer);
+ if(p->Packet)
+ PacketFreePacket(p->Packet);
+ /*
+ * Get rid of any link-layer type list we allocated.
+ */
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
return (NULL);
}
static int
-pcap_setfilter_win32(pcap_t *p, struct bpf_program *fp)
+pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
{
if(PacketSetBpf(p->adapter,fp)==FALSE){
- /* kernel filter not installed. */
+ /*
+ * Kernel filter not installed.
+ * XXX - fall back on userland filtering, as is done
+ * on other platforms?
+ */
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
return (-1);
}
+
+ /*
+ * Discard any previously-received packets, as they might have
+ * passed whatever filter was formerly in effect, but might
+ * not pass this filter (BIOCSETF discards packets buffered
+ * in the kernel, so you can lose packets in any case).
+ */
+ p->cc = 0;
return (0);
}
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
+
+ if(!fp)
+ {
+ strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Install a user level filter */
+ if (install_bpf_program(p, fp) < 0)
+ {
+ snprintf(p->errbuf, sizeof(p->errbuf),
+ "setfilter, unable to install the filter: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ p->md.use_bpf = 0;
+
+ return (0);
+}
static int
pcap_getnonblock_win32(pcap_t *p, char *errbuf)
@@ -387,28 +732,6 @@ pcap_setmode(pcap_t *p, int mode){
return 0;
}
-/* Send a packet to the network */
-int
-pcap_sendpacket(pcap_t *p, u_char *buf, int size){
- LPPACKET PacketToSend;
-
- if (p->adapter==NULL)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
- return -1;
- }
-
- PacketToSend=PacketAllocatePacket();
- PacketInitPacket(PacketToSend,buf,size);
- if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
- PacketFreePacket(PacketToSend);
- return -1;
- }
-
- PacketFreePacket(PacketToSend);
- return 0;
-}
-
/* Set the dimension of the kernel-level capture buffer */
int
pcap_setbuff(pcap_t *p, int dim)
diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3
index 7aad4a181da0..1e8e27e6b418 100644
--- a/contrib/libpcap/pcap.3
+++ b/contrib/libpcap/pcap.3
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.51.2.9 2004/03/28 21:45:32 fenner Exp $
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64 2004/12/17 21:27:54 guy Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@@ -39,7 +39,9 @@ pcap_t *pcap_open_live(const char *device, int snaplen,
int promisc, int to_ms, char *errbuf)
pcap_t *pcap_open_dead(int linktype, int snaplen)
pcap_t *pcap_open_offline(const char *fname, char *errbuf)
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf)
pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname)
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp)
.ft
.LP
.ft B
@@ -88,6 +90,11 @@ void pcap_breakloop(pcap_t *)
.ft
.LP
.ft B
+int pcap_inject(pcap_t *p, const void *buf, size_t size)
+int pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
+.ft
+.LP
+.ft B
int pcap_datalink(pcap_t *p)
int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
int pcap_set_datalink(pcap_t *p, int dlt);
@@ -101,7 +108,7 @@ 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)
-int pcap_get_selectable_fd(pcap_t *p)
+int pcap_get_selectable_fd(pcap_t *p);
void pcap_perror(pcap_t *p, char *prefix)
char *pcap_geterr(pcap_t *p)
char *pcap_strerror(int error)
@@ -128,6 +135,7 @@ in
.BR pcap_open_live() ,
.BR pcap_open_dead() ,
.BR pcap_open_offline() ,
+.BR pcap_fopen_offline() ,
.BR pcap_setnonblock() ,
.BR pcap_getnonblock() ,
.BR pcap_findalldevs() ,
@@ -206,9 +214,16 @@ and
.BR tcpslice(1) .
The name "-" in a synonym for
.BR stdin .
+Alternatively, you may call
+.B pcap_fopen_offline()
+to read dumped data from an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
.I errbuf
is used to return error text and is only set when
.B pcap_open_offline()
+or
+.B pcap_fopen_offline()
fails and returns
.BR NULL .
.PP
@@ -226,13 +241,18 @@ struct as returned by
or
.BR pcap_open_live() .
.I fname
-specifies the name of the file to open.
+specifies the name of the file to open. Alternatively, you may call
+.B pcap_dump_fopen()
+to write data to an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
If
.B NULL
is returned,
.B pcap_geterr()
can be used to get the error text.
.PP
+.PP
.B pcap_setnonblock()
puts a capture descriptor, opened with
.BR pcap_open_live() ,
@@ -354,6 +374,13 @@ to by
may be null if the interface isn't a point-to-point interface
.RE
.PP
+Note that not all the addresses in the list of addresses are
+necessarily IPv4 or IPv6 addresses - you must check the
+.B sa_family
+member of the
+.B "struct sockaddr"
+before interpreting the contents of the address.
+.PP
.B \-1
is returned on failure, in which case
.B errbuf
@@ -628,6 +655,45 @@ the flag is cleared, so a subsequent call will resume reading packets.
If a positive number is returned, the flag is not cleared, so a
subsequent call will return \-2 and clear the flag.
.PP
+.B pcap_inject()
+sends a raw packet through the network interface;
+.I buf
+points to the data of the packet, including the link-layer header, and
+.I size
+is the number of bytes in the packet.
+It returns the number of bytes written on success. A return of \-1
+indicates an error in which case
+.B pcap_perror()
+or
+.B pcap_geterr()
+may be used to display the error text.
+Note that, even if you successfully open the network interface, you
+might not have permission to send packets on it, or it might not support
+sending packets; as
+.I pcap_open_live()
+doesn't have a flag to indicate whether to open for capturing, sending,
+or capturing and sending, you cannot request an open that supports
+sending and be notified at open time whether sending will be possible.
+Note also that some devices might not support sending packets.
+.PP
+Note that, on some platforms, the link-layer header of the packet that's
+sent might not be the same as the link-layer header of the packet
+supplied to
+.BR pcap_inject() ,
+as the source link-layer address, if the header contains such an
+address, might be changed to be the address assigned to the interface on
+which the packet it sent, if the platform doesn't support sending
+completely raw and unchanged packets.
+.PP
+.B pcap_sendpacket()
+is like
+.BR pcap_inject() ,
+but it returns 0 on success and \-1 on failure.
+.RB ( pcap_inject()
+comes from OpenBSD;
+.B pcap_sendpacket()
+comes from WinPcap. Both are provided for compatibility.)
+.PP
.B pcap_dump()
outputs a packet to the ``savefile'' opened with
.BR pcap_dump_open() .
diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c
index fbaceb5a06c5..7cad9ea18134 100644
--- a/contrib/libpcap/pcap.c
+++ b/contrib/libpcap/pcap.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.63.2.9 2004/03/25 22:40:52 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88 2005/02/08 20:03:15 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -49,7 +49,7 @@ static const char rcsid[] _U_ =
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifndef _MSC_VER
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
#include <unistd.h>
#endif
#include <fcntl.h>
@@ -59,6 +59,10 @@ static const char rcsid[] _U_ =
#include "os-proto.h"
#endif
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
#include "pcap-int.h"
#ifdef HAVE_DAG_API
@@ -275,6 +279,22 @@ pcap_set_datalink(pcap_t *p, int dlt)
break;
if (i >= p->dlt_count)
goto unsupported;
+ if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
+ dlt == DLT_DOCSIS) {
+ /*
+ * This is presumably an Ethernet device, as the first
+ * link-layer type it offers is DLT_EN10MB, and the only
+ * other type it offers is DLT_DOCSIS. That means that
+ * we can't tell the driver to supply DOCSIS link-layer
+ * headers - we're just pretending that's what we're
+ * getting, as, presumably, we're capturing on a dedicated
+ * link to a Cisco Cable Modem Termination System, and
+ * it's putting raw DOCSIS frames on the wire inside low-level
+ * Ethernet framing.
+ */
+ p->linktype = dlt;
+ return (0);
+ }
if (p->set_datalink_op(p, dlt) == -1)
return (-1);
p->linktype = dlt;
@@ -332,8 +352,23 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
+ DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
+ DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
+ DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
+ DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
+ DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+ DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
+ DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
+ DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
+ DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
+ DLT_CHOICE(DLT_GPF_T, "GPF-T"),
+ DLT_CHOICE(DLT_GPF_F, "GPF-F"),
+ DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
+ DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+ DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"),
+ DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
DLT_CHOICE_SENTINEL
};
@@ -502,7 +537,7 @@ pcap_fileno(pcap_t *p)
#endif
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
int
pcap_get_selectable_fd(pcap_t *p)
{
@@ -535,7 +570,7 @@ pcap_getnonblock(pcap_t *p, char *errbuf)
* We don't look at "p->nonblock", in case somebody tweaked the FD
* directly.
*/
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
int
pcap_getnonblock_fd(pcap_t *p, char *errbuf)
{
@@ -560,7 +595,7 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
return p->setnonblock_op(p, nonblock, errbuf);
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
/*
* Set non-blocking mode, under the assumption that it's just the
* standard POSIX non-blocking flag. (This can be called by the
@@ -603,6 +638,7 @@ pcap_win32strerror(void)
DWORD error;
static char errbuf[PCAP_ERRBUF_SIZE+1];
int errlen;
+ char *p;
error = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
@@ -617,6 +653,8 @@ pcap_win32strerror(void)
errbuf[errlen - 1] = '\0';
errbuf[errlen - 2] = '\0';
}
+ p = strchr(errbuf, '\0');
+ snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
return (errbuf);
}
#endif
@@ -654,15 +692,26 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
}
static int
-pcap_stats_dead(pcap_t *p, struct pcap_stat *ps)
+pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
{
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Statistics aren't available from a pcap_open_dead pcap_t");
return (-1);
}
+void
+pcap_close_common(pcap_t *p)
+{
+ if (p->buffer != NULL)
+ free(p->buffer);
+#if !defined(WIN32) && !defined(MSDOS)
+ if (p->fd >= 0)
+ close(p->fd);
+#endif
+}
+
static void
-pcap_close_dead(pcap_t *p)
+pcap_close_dead(pcap_t *p _U_)
{
/* Nothing to do. */
}
@@ -683,6 +732,30 @@ pcap_open_dead(int linktype, int snaplen)
return p;
}
+/*
+ * API compatible with WinPcap's "send a packet" routine - returns -1
+ * on error, 0 otherwise.
+ *
+ * XXX - what if we get a short write?
+ */
+int
+pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
+{
+ if (p->inject_op(p, buf, size) == -1)
+ return (-1);
+ return (0);
+}
+
+/*
+ * API compatible with OpenBSD's "send a packet" routine - returns -1 on
+ * error, number of bytes written otherwise.
+ */
+int
+pcap_inject(pcap_t *p, const void *buf, size_t size)
+{
+ return (p->inject_op(p, buf, size));
+}
+
void
pcap_close(pcap_t *p)
{
@@ -705,26 +778,32 @@ pcap_close(pcap_t *p)
* was linked, or even weirder things, such as the string being the one
* from the library but being truncated).
*/
+#ifdef HAVE_VERSION_H
+#include "version.h"
+#else
+static const char pcap_version_string[] = "libpcap version 0.9[.x]";
+#endif
+
#ifdef WIN32
/*
* XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
* version numbers when building WinPcap. (It'd be nice to do so for
* the packet.dll version number as well.)
*/
-static const char wpcap_version_string[] = "3.0";
+static const char wpcap_version_string[] = "3.1";
static const char pcap_version_string_fmt[] =
- "WinPcap version %s, based on libpcap version 0.8";
+ "WinPcap version %s, based on %s";
static const char pcap_version_string_packet_dll_fmt[] =
- "WinPcap version %s (packet.dll version %s), based on libpcap version 0.8";
-static char *pcap_version_string;
+ "WinPcap version %s (packet.dll version %s), based on %s";
+static char *full_pcap_version_string;
const char *
pcap_lib_version(void)
{
char *packet_version_string;
- size_t pcap_version_string_len;
+ size_t full_pcap_version_string_len;
- if (pcap_version_string == NULL) {
+ if (full_pcap_version_string == NULL) {
/*
* Generate the version string.
*/
@@ -735,12 +814,15 @@ pcap_lib_version(void)
* string are the same; just report the WinPcap
* version.
*/
- pcap_version_string_len =
- (sizeof pcap_version_string_fmt - 2) +
- strlen(wpcap_version_string);
- pcap_version_string = malloc(pcap_version_string_len);
- sprintf(pcap_version_string, pcap_version_string_fmt,
- wpcap_version_string);
+ full_pcap_version_string_len =
+ (sizeof pcap_version_string_fmt - 4) +
+ strlen(wpcap_version_string) +
+ strlen(pcap_version_string);
+ full_pcap_version_string =
+ malloc(full_pcap_version_string_len);
+ sprintf(full_pcap_version_string,
+ pcap_version_string_fmt, wpcap_version_string,
+ pcap_version_string);
} else {
/*
* WinPcap version string and packet.dll version
@@ -749,20 +831,48 @@ pcap_lib_version(void)
* same version of WinPcap), so we report both
* versions.
*/
- pcap_version_string_len =
- (sizeof pcap_version_string_packet_dll_fmt - 4) +
+ full_pcap_version_string_len =
+ (sizeof pcap_version_string_packet_dll_fmt - 6) +
strlen(wpcap_version_string) +
- strlen(packet_version_string);
- pcap_version_string = malloc(pcap_version_string_len);
- sprintf(pcap_version_string,
+ strlen(packet_version_string) +
+ strlen(pcap_version_string);
+ full_pcap_version_string = malloc(full_pcap_version_string_len);
+
+ sprintf(full_pcap_version_string,
pcap_version_string_packet_dll_fmt,
- wpcap_version_string, packet_version_string);
+ wpcap_version_string, packet_version_string,
+ pcap_version_string);
}
}
- return (pcap_version_string);
+ return (full_pcap_version_string);
}
-#else
-#include "version.h"
+
+#elif defined(MSDOS)
+
+static char *full_pcap_version_string;
+
+const char *
+pcap_lib_version (void)
+{
+ char *packet_version_string;
+ size_t full_pcap_version_string_len;
+ static char dospfx[] = "DOS-";
+
+ if (full_pcap_version_string == NULL) {
+ /*
+ * Generate the version string.
+ */
+ full_pcap_version_string_len =
+ sizeof dospfx + strlen(pcap_version_string);
+ full_pcap_version_string =
+ malloc(full_pcap_version_string_len);
+ strcpy(full_pcap_version_string, dospfx);
+ strcat(full_pcap_version_string, pcap_version_string);
+ }
+ return (full_pcap_version_string);
+}
+
+#else /* UN*X */
const char *
pcap_lib_version(void)
diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h
index 450ac00deecf..d3f1ba0d2935 100644
--- a/contrib/libpcap/pcap.h
+++ b/contrib/libpcap/pcap.h
@@ -31,18 +31,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.45.2.4 2004/01/27 22:56:20 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52 2004/12/18 08:52:11 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
#define lib_pcap_h
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
-#include <sys/types.h>
-#include <sys/time.h>
-#endif /* WIN32 */
+#if defined(WIN32)
+ #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+ #include <sys/types.h>
+ #include <sys/socket.h> /* u_int, u_char etc. */
+#else /* UN*X */
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <pcap-bpf.h>
@@ -140,6 +143,39 @@ struct pcap_stat {
#endif /* WIN32 */
};
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+ u_long rx_packets; /* total packets received */
+ u_long tx_packets; /* total packets transmitted */
+ u_long rx_bytes; /* total bytes received */
+ u_long tx_bytes; /* total bytes transmitted */
+ u_long rx_errors; /* bad packets received */
+ u_long tx_errors; /* packet transmit problems */
+ u_long rx_dropped; /* no space in Rx buffers */
+ u_long tx_dropped; /* no space available for Tx */
+ u_long multicast; /* multicast packets received */
+ u_long collisions;
+
+ /* detailed rx_errors: */
+ u_long rx_length_errors;
+ u_long rx_over_errors; /* receiver ring buff overflow */
+ u_long rx_crc_errors; /* recv'd pkt with crc error */
+ u_long rx_frame_errors; /* recv'd frame alignment error */
+ u_long rx_fifo_errors; /* recv'r fifo overrun */
+ u_long rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ u_long tx_aborted_errors;
+ u_long tx_carrier_errors;
+ u_long tx_fifo_errors;
+ u_long tx_heartbeat_errors;
+ u_long tx_window_errors;
+ };
+#endif
+
/*
* Item in a list of interfaces.
*/
@@ -172,6 +208,7 @@ int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_offline(const char *, char *);
+pcap_t *pcap_fopen_offline(FILE *, 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 *);
@@ -184,6 +221,8 @@ int pcap_setfilter(pcap_t *, struct bpf_program *);
int pcap_getnonblock(pcap_t *, char *);
int pcap_setnonblock(pcap_t *, int, char *);
void pcap_perror(pcap_t *, char *);
+int pcap_inject(pcap_t *, const void *, size_t);
+int pcap_sendpacket(pcap_t *, const u_char *, int);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
@@ -207,6 +246,7 @@ FILE *pcap_file(pcap_t *);
int pcap_fileno(pcap_t *);
pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
int pcap_dump_flush(pcap_dumper_t *);
void pcap_dump_close(pcap_dumper_t *);
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -223,33 +263,44 @@ int bpf_validate(struct bpf_insn *f, int len);
char *bpf_image(struct bpf_insn *, int);
void bpf_dump(struct bpf_program *, int);
-#ifdef WIN32
+#if defined(WIN32)
+
/*
* Win32 definitions
*/
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
-int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
int pcap_setmintocopy(pcap_t *p, int size);
#ifdef WPCAP
/* Include file with the wpcap-specific extensions */
#include <Win32-Extensions.h>
-#endif
+#endif /* WPCAP */
#define MODE_CAPT 0
#define MODE_STAT 1
#define MODE_MON 2
-#else
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
/*
* UN*X definitions
*/
int pcap_get_selectable_fd(pcap_t *);
-#endif /* WIN32 */
+#endif /* WIN32/MSDOS/UN*X */
#ifdef __cplusplus
}
diff --git a/contrib/libpcap/pcap1.h b/contrib/libpcap/pcap1.h
new file mode 100644
index 000000000000..08d0c5a6e7a1
--- /dev/null
+++ b/contrib/libpcap/pcap1.h
@@ -0,0 +1,302 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap1.h,v 1.2 2004/03/30 14:42:50 mcr Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_h
+#define lib_pcap_h
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#include <sys/types.h>
+#include <sys/time.h>
+#endif /* WIN32 */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap-bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PCAP_VERSION_MAJOR 3
+#define PCAP_VERSION_MINOR 0
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ * introduce a new structure for the new format, if the layout
+ * of the structure changed;
+ *
+ * send mail to "tcpdump-workers@tcpdump.org", requesting a new
+ * magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed file
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old file header as well as files with the new file header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes to "patches@tcpdump.org", so that future
+ * versions of libpcap and programs that use it (such as tcpdump) will
+ * be able to read your new capture file format.
+ */
+
+enum pcap1_info_types {
+ PCAP_DATACAPTURE,
+ PCAP_TIMESTAMP,
+ PCAP_WALLTIME,
+ PCAP_TIMESKEW,
+ PCAP_PROBEPLACE, /* aka direction */
+ PCAP_COMMENT, /* comment */
+};
+
+struct pcap1_info_container {
+ bpf_u_int32 info_len; /* in bytes */
+ bpf_u_int32 info_type; /* enum pcap1_info_types */
+ unsigned char info_data[0];
+};
+
+struct pcap1_info_timestamp {
+ struct pcap1_info_container pic;
+ bpf_u_int32 nanoseconds; /* 10^-9 of seconds */
+ bpf_u_int32 seconds; /* seconds since Unix epoch - GMT */
+ bpf_u_int16 macroseconds; /* 16 bits more of MSB of time */
+ bpf_u_int16 sigfigs; /* accuracy of timestamps - LSB bits */
+};
+
+struct pcap1_info_packet {
+ struct pcap1_info_container pic;
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
+ bpf_u_int32 ifIndex; /* abstracted interface index */
+ unsigned char packet_data[0];
+};
+
+enum pcap1_probe {
+ INBOUND =1,
+ OUTBOUND =2,
+ FORWARD =3,
+ PREENCAP =4,
+ POSTDECAP=5,
+};
+
+struct pcap1_info_probe {
+ struct pcap1_info_container pic;
+ bpf_u_int32 probeloc; /* enum pcap1_probe */
+ unsigned char probe_desc[0];
+};
+
+struct pcap1_info_comment {
+ struct pcap1_info_container pic;
+ unsigned char comment[0];
+};
+
+struct pcap1_packet_header {
+ bpf_u_int32 magic;
+ u_short version_major;
+ u_short version_minor;
+ bpf_u_int32 block_len;
+ struct pcap1_info_container pics[0];
+};
+
+/*
+ * Each packet in the dump file is prepended with this generic header.
+ * This gets around the problem of different headers for different
+ * packet interfaces.
+ */
+
+/*
+ * 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 */
+#ifdef WIN32
+ u_int bs_capt; /* number of packets that reach the application */
+#endif /* WIN32 */
+};
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+ struct pcap_if *next;
+ char *name; /* name to hand to "pcap_open_live()" */
+ char *description; /* textual description of interface, or NULL */
+ struct pcap_addr *addresses;
+ bpf_u_int32 flags; /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+ struct pcap_addr *next;
+ struct sockaddr *addr; /* address */
+ struct sockaddr *netmask; /* netmask for that address */
+ struct sockaddr *broadaddr; /* broadcast address for that address */
+ struct sockaddr *dstaddr; /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+ const u_char *);
+
+char *pcap_lookupdev(char *);
+int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
+pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_offline(const char *, char *);
+void pcap_close(pcap_t *);
+int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+ pcap_next(pcap_t *, struct pcap_pkthdr *);
+int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+void pcap_breakloop(pcap_t *);
+int pcap_stats(pcap_t *, struct pcap_stat *);
+int pcap_setfilter(pcap_t *, struct bpf_program *);
+int pcap_getnonblock(pcap_t *, char *);
+int pcap_setnonblock(pcap_t *, int, char *);
+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);
+int pcap_compile_nopcap(int, int, struct bpf_program *,
+ char *, int, bpf_u_int32);
+void pcap_freecode(struct bpf_program *);
+int pcap_datalink(pcap_t *);
+int pcap_list_datalinks(pcap_t *, int **);
+int pcap_set_datalink(pcap_t *, int);
+int pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+int pcap_snapshot(pcap_t *);
+int pcap_is_swapped(pcap_t *);
+int pcap_major_version(pcap_t *);
+int pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE *pcap_file(pcap_t *);
+int pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+int pcap_dump_flush(pcap_dumper_t *);
+void pcap_dump_close(pcap_dumper_t *);
+void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+FILE *pcap_dump_file(pcap_dumper_t *);
+
+int pcap_findalldevs(pcap_if_t **, char *);
+void pcap_freealldevs(pcap_if_t *);
+
+const char *pcap_lib_version(void);
+
+/* XXX this guy lives in the bpf tree */
+u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+int bpf_validate(struct bpf_insn *f, int len);
+char *bpf_image(struct bpf_insn *, int);
+void bpf_dump(struct bpf_program *, int);
+
+#ifdef WIN32
+/*
+ * Win32 definitions
+ */
+
+int pcap_setbuff(pcap_t *p, int dim);
+int pcap_setmode(pcap_t *p, int mode);
+int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
+int pcap_setmintocopy(pcap_t *p, int size);
+
+#ifdef WPCAP
+/* Include file with the wpcap-specific extensions */
+#include <Win32-Extensions.h>
+#endif
+
+#define MODE_CAPT 0
+#define MODE_STAT 1
+
+#else
+/*
+ * UN*X definitions
+ */
+
+int pcap_get_selectable_fd(pcap_t *);
+
+#endif /* WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libpcap/pf.h b/contrib/libpcap/pf.h
index ad6649cf4e10..a9b127ac29ca 100644
--- a/contrib/libpcap/pf.h
+++ b/contrib/libpcap/pf.h
@@ -26,11 +26,11 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/pf.h,v 1.1.2.1 2004/03/28 21:45:33 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pf.h,v 1.3 2004/04/02 06:33:30 guy Exp $ (LBL)
*/
/* from $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
-
+
enum { PF_INOUT=0, PF_IN=1, PF_OUT=2 };
enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2, PF_NAT=3, PF_NONAT=4,
PF_BINAT=5, PF_NOBINAT=6, PF_RDR=7, PF_NORDR=8, PF_SYNPROXY_DROP=9 };
@@ -64,7 +64,7 @@ enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2, PF_NAT=3, PF_NONAT=4,
struct pfloghdr {
u_int8_t length;
- sa_family_t af;
+ u_int8_t af;
u_int8_t action;
u_int8_t reason;
char ifname[IFNAMSIZ];
diff --git a/contrib/libpcap/ppp.h b/contrib/libpcap/ppp.h
index b7b987d3a547..80a6851691b2 100644
--- a/contrib/libpcap/ppp.h
+++ b/contrib/libpcap/ppp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.8 1999/10/19 15:18:31 itojun Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.12 2005/02/08 19:52:19 guy Exp $ (LBL) */
/*
* Point to Point Protocol (PPP) RFC1331
*
@@ -18,6 +18,9 @@
#define PPP_ADDRESS 0xff /* The address byte value */
#define PPP_CONTROL 0x03 /* The control byte value */
+#define PPP_PPPD_IN 0x00 /* non-standard for DLT_PPP_PPPD */
+#define PPP_PPPD_OUT 0x01 /* non-standard for DLT_PPP_PPPD */
+
/* Protocol numbers */
#define PPP_IP 0x0021 /* Raw IP */
#define PPP_OSI 0x0023 /* OSI Network Layer */
@@ -35,6 +38,8 @@
#define PPP_HELLO 0x0201 /* 802.1d Hello Packets */
#define PPP_LUXCOM 0x0231 /* Luxcom */
#define PPP_SNS 0x0233 /* Sigma Network Systems */
+#define PPP_MPLS_UCAST 0x0281 /* rfc 3032 */
+#define PPP_MPLS_MCAST 0x0283 /* rfc 3022 */
#define PPP_IPCP 0x8021 /* IP Control Protocol */
#define PPP_OSICP 0x8023 /* OSI Network Layer Control Protocol */
@@ -45,6 +50,7 @@
#define PPP_STIICP 0x8033 /* Strean Protocol Control Protocol */
#define PPP_VINESCP 0x8035 /* Banyan Vines Control Protocol */
#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
+#define PPP_MPLSCP 0x8281 /* rfc 3022 */
#define PPP_LCP 0xc021 /* Link Control Protocol */
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c
index cc307bdff13b..0a739fa82192 100644
--- a/contrib/libpcap/savefile.c
+++ b/contrib/libpcap/savefile.c
@@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.92.2.11 2004/03/11 23:46:14 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126 2005/02/08 20:03:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -49,8 +49,27 @@ static const char rcsid[] _U_ =
#include "os-proto.h"
#endif
-#define TCPDUMP_MAGIC 0xa1b2c3d4
-#define PATCHED_TCPDUMP_MAGIC 0xa1b2cd34
+/*
+ * Standard libpcap format.
+ */
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/*
+ * Alexey Kuznetzov's modified libpcap format.
+ */
+#define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
+
+/*
+ * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
+ * for another modified format.
+ */
+#define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd
+
+/*
+ * Navtel Communcations' format, with nanosecond timestamps,
+ * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
+ */
+#define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d
/*
* We use the "receiver-makes-right" approach to byte order,
@@ -76,6 +95,19 @@ static const char rcsid[] _U_ =
#define SFERR_EOF 4 /* not really an error, just a status */
/*
+ * Setting O_BINARY on DOS/Windows is a bit tricky
+ */
+#if defined(WIN32)
+ #define SET_BINMODE(f) _setmode(fileno(f), O_BINARY)
+#elif defined(MSDOS)
+ #if defined(__HIGHC__)
+ #define SET_BINMODE(f) setmode(f, O_BINARY)
+ #else
+ #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
+ #endif
+#endif
+
+/*
* We don't write DLT_* values to the capture file header, because
* they're not the same on all platforms.
*
@@ -156,11 +188,6 @@ static const char rcsid[] _U_ =
#define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */
-/*
- * This isn't supported in libpcap 0.8[.x], but is supported in the
- * current CVS version; we include it here to note that it's not available
- * for anybody else to use.
- */
#define LINKTYPE_SYMANTEC_FIREWALL 99 /* Symantec Enterprise Firewall */
#define LINKTYPE_ATM_RFC1483 100 /* LLC/SNAP-encapsulated ATM */
@@ -247,11 +274,6 @@ static const char rcsid[] _U_ =
#define LINKTYPE_RAWSS7_MTP3 141 /* definitions */
#define LINKTYPE_RAWSS7_SCCP 142
-/*
- * This isn't supported in libpcap 0.8[.x], but is supported in the
- * current CVS version; we include it here to note that it's not available
- * for anybody else to use.
- */
#define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */
#define LINKTYPE_LINUX_IRDA 144 /* Linux-IrDA */
@@ -325,6 +347,63 @@ static const char rcsid[] _U_ =
*/
#define LINKTYPE_JUNIPER_MONITOR 164
+/*
+ * Reserved for BACnet MS/TP.
+ */
+#define LINKTYPE_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define LINKTYPE_PPP_PPPD 166
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define LINKTYPE_JUNIPER_PPPOE 167
+#define LINKTYPE_JUNIPER_PPPOE_ATM 168
+
+#define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */
+#define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define LINKTYPE_GCOM_T1E1 172
+#define LINKTYPE_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define LINKTYPE_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define LINKTYPE_ERF_ETH 175 /* Ethernet */
+#define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */
+
static struct linktype_map {
int dlt;
int linktype;
@@ -483,8 +562,37 @@ static struct linktype_map {
* LINKTYPE_* values, either).
*/
+ /* Juniper-internal chassis encapsulation */
+ { DLT_JUNIPER_MONITOR, LINKTYPE_JUNIPER_MONITOR },
+
+ /* BACnet MS/TP */
+ { DLT_BACNET_MS_TP, LINKTYPE_BACNET_MS_TP },
+
+ /* PPP for pppd, with direction flag in the PPP header */
+ { DLT_PPP_PPPD, LINKTYPE_PPP_PPPD},
+
+ /* Juniper-internal chassis encapsulation */
+ { DLT_JUNIPER_PPPOE, LINKTYPE_JUNIPER_PPPOE },
+ { DLT_JUNIPER_PPPOE_ATM,LINKTYPE_JUNIPER_PPPOE_ATM },
+
+ /* GPRS LLC */
+ { DLT_GPRS_LLC, LINKTYPE_GPRS_LLC },
+
+ /* Transparent Generic Framing Procedure (ITU-T G.7041/Y.1303) */
+ { DLT_GPF_T, LINKTYPE_GPF_T },
+
+ /* Framed Generic Framing Procedure (ITU-T G.7041/Y.1303) */
+ { DLT_GPF_F, LINKTYPE_GPF_F },
+
+ { DLT_GCOM_T1E1, LINKTYPE_GCOM_T1E1 },
+ { DLT_GCOM_SERIAL, LINKTYPE_GCOM_SERIAL },
+
/* Juniper-internal chassis encapsulation */
- { DLT_JUNIPER_MONITOR, LINKTYPE_JUNIPER_MONITOR },
+ { DLT_JUNIPER_PIC_PEER, LINKTYPE_JUNIPER_PIC_PEER },
+
+ /* Endace types */
+ { DLT_ERF_ETH, LINKTYPE_ERF_ETH },
+ { DLT_ERF_POS, LINKTYPE_ERF_POS },
{ -1, -1 }
};
@@ -584,6 +692,14 @@ sf_stats(pcap_t *p, struct pcap_stat *ps)
return (-1);
}
+static int
+sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+ strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
static void
sf_close(pcap_t *p)
{
@@ -596,9 +712,37 @@ sf_close(pcap_t *p)
pcap_t *
pcap_open_offline(const char *fname, char *errbuf)
{
+ FILE *fp;
+ pcap_t *p;
+
+ if (fname[0] == '-' && fname[1] == '\0')
+ fp = stdin;
+ else {
+#if !defined(WIN32) && !defined(MSDOS)
+ fp = fopen(fname, "r");
+#else
+ fp = fopen(fname, "rb");
+#endif
+ if (fp == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+ pcap_strerror(errno));
+ return (NULL);
+ }
+ }
+ p = pcap_fopen_offline(fp, errbuf);
+ if (p == NULL) {
+ if (fp != stdin)
+ fclose(fp);
+ }
+ return (p);
+}
+
+pcap_t *
+pcap_fopen_offline(FILE *fp, char *errbuf)
+{
register pcap_t *p;
- register FILE *fp;
struct pcap_file_header hdr;
+ size_t amt_read;
bpf_u_int32 magic;
int linklen;
@@ -610,29 +754,24 @@ pcap_open_offline(const char *fname, char *errbuf)
memset((char *)p, 0, sizeof(*p));
- if (fname[0] == '-' && fname[1] == '\0')
- fp = stdin;
- else {
-#ifndef WIN32
- fp = fopen(fname, "r");
-#else
- fp = fopen(fname, "rb");
-#endif
- if (fp == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+ amt_read = fread((char *)&hdr, 1, sizeof(hdr), fp);
+ if (amt_read != sizeof(hdr)) {
+ if (ferror(fp)) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "error reading dump file: %s",
pcap_strerror(errno));
- goto bad;
+ } else {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %lu file header bytes, only got %lu",
+ (unsigned long)sizeof(hdr),
+ (unsigned long)amt_read);
}
- }
- if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "fread: %s",
- pcap_strerror(errno));
goto bad;
}
magic = hdr.magic;
- if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) {
+ if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
magic = SWAPLONG(magic);
- if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) {
+ if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bad dump file format");
goto bad;
@@ -640,12 +779,23 @@ pcap_open_offline(const char *fname, char *errbuf)
p->sf.swapped = 1;
swap_hdr(&hdr);
}
- if (magic == PATCHED_TCPDUMP_MAGIC) {
+ if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
/*
* XXX - the patch that's in some versions of libpcap
- * changes the packet header but not the magic number;
+ * changes the packet header but not the magic number,
+ * and some other versions with this magic number have
+ * some extra debugging information in the packet header;
* we'd have to use some hacks^H^H^H^H^Hheuristics to
- * detect that.
+ * detect those variants.
+ *
+ * Ethereal does that, but it does so by trying to read
+ * the first two packets of the file with each of the
+ * record header formats. That currently means it seeks
+ * backwards and retries the reads, which doesn't work
+ * on pipes. We want to be able to read from a pipe, so
+ * that strategy won't work; we'd have to buffer some
+ * data ourselves and read from that buffer in order to
+ * make that work.
*/
p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
} else
@@ -694,8 +844,8 @@ pcap_open_offline(const char *fname, char *errbuf)
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;
+ /* Padding only needed for live capture fcode */
+ p->fddipad = 0;
#endif
/*
@@ -728,7 +878,7 @@ pcap_open_offline(const char *fname, char *errbuf)
break;
}
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
/*
* You can do "select()" and "poll()" on plain files on most
* platforms, and should be able to do so on pipes.
@@ -740,6 +890,7 @@ pcap_open_offline(const char *fname, char *errbuf)
#endif
p->read_op = pcap_offline_read;
+ p->inject_op = sf_inject;
p->setfilter_op = install_bpf_program;
p->set_datalink_op = NULL; /* we don't support munging link-layer headers */
p->getnonblock_op = sf_getnonblock;
@@ -747,10 +898,17 @@ pcap_open_offline(const char *fname, char *errbuf)
p->stats_op = sf_stats;
p->close_op = sf_close;
+#if defined(WIN32) || defined(MSDOS)
+ /*
+ * If we're reading from the standard input, put it in binary
+ * mode, as savefiles are binary files.
+ */
+ if (fp == stdin)
+ SET_BINMODE(fp);
+#endif
+
return (p);
bad:
- if(fp)
- fclose(fp);
free(p);
return (NULL);
}
@@ -906,7 +1064,7 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen)
int
pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
- struct bpf_insn *fcode = p->fcode.bf_insns;
+ struct bpf_insn *fcode;
int status = 0;
int n = 0;
@@ -937,7 +1095,7 @@ pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (status);
}
- if (fcode == NULL ||
+ if ((fcode = p->fcode.bf_insns) == NULL ||
bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
(*callback)(user, &h, p->buffer);
if (++n >= cnt && cnt > 0)
@@ -967,6 +1125,33 @@ pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
(void)fwrite((char *)sp, h->caplen, 1, f);
}
+static pcap_dumper_t *
+pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
+{
+
+#if defined(WIN32) || defined(MSDOS)
+ /*
+ * If we're writing to the standard output, put it in binary
+ * mode, as savefiles are binary files.
+ *
+ * Otherwise, we turn off buffering.
+ * XXX - why? And why not on the standard output?
+ */
+ if (f == stdout)
+ SET_BINMODE(f);
+ else
+ setbuf(f, NULL);
+#endif
+ if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+ fname, pcap_strerror(errno));
+ if (f != stdout)
+ (void)fclose(f);
+ return (NULL);
+ }
+ return ((pcap_dumper_t *)f);
+}
+
/*
* Initialize so that sf_write() will output to the file named 'fname'.
*/
@@ -986,15 +1171,12 @@ pcap_dump_open(pcap_t *p, const char *fname)
if (fname[0] == '-' && fname[1] == '\0') {
f = stdout;
-#ifdef WIN32
- _setmode(_fileno(f), _O_BINARY);
-#endif
+ fname = "standard output";
} else {
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MSDOS)
f = fopen(fname, "w");
#else
f = fopen(fname, "wb");
- setbuf(f, NULL); /* XXX - why? */
#endif
if (f == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
@@ -1002,8 +1184,26 @@ pcap_dump_open(pcap_t *p, const char *fname)
return (NULL);
}
}
- (void)sf_write_header(f, linktype, p->tzoff, p->snapshot);
- return ((pcap_dumper_t *)f);
+ return (pcap_setup_dump(p, linktype, f, fname));
+}
+
+/*
+ * Initialize so that sf_write() will output to the given stream.
+ */
+pcap_dumper_t *
+pcap_dump_fopen(pcap_t *p, FILE *f)
+{
+ int linktype;
+
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "stream: link-layer type %d isn't supported in savefiles",
+ linktype);
+ return (NULL);
+ }
+
+ return (pcap_setup_dump(p, linktype, f, "stream"));
}
FILE *
diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l
index 8acc61a77263..73cb6d8a2b20 100644
--- a/contrib/libpcap/scanner.l
+++ b/contrib/libpcap/scanner.l
@@ -22,7 +22,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.95.2.3 2004/03/28 21:45:33 fenner Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99 2004/06/16 08:20:28 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -260,6 +260,7 @@ inbound return INBOUND;
outbound return OUTBOUND;
vlan return VLAN;
+mpls return MPLS;
lane return LANE;
llc return LLC;