diff options
Diffstat (limited to 'contrib/libpcap')
43 files changed, 6642 insertions, 1058 deletions
diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES index 01b1581..015836d 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 fadf77f..870ec50 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 4f8193c..95b75cf 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 5a1310b..2f9075d 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 2671eb8..0ed0cb0 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 35ab2f8..90571a1 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 d6d27a2..88c27f8 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 0000000..25794d8 --- /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 ee94dd8..e80fc25 100644 --- a/contrib/libpcap/VERSION +++ b/contrib/libpcap/VERSION @@ -1 +1 @@ -0.8.3 +0.9-PRE-CVS diff --git a/contrib/libpcap/bpf/net/bpf_filter.c b/contrib/libpcap/bpf/net/bpf_filter.c index a2cfbc1..40df32a 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 99aa0a0..303602e 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 b1d76fe..7f31d9c 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 1c41d04..2ecdbc1 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 a0abec5e..ba01786 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 4846499..d970fd5 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 11f34f2..9d29955 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 3af5576..f258936 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 55a6bf1..e9ec409 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 0214d59..4ed02f9 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 d365ae1..8ad7a6c 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 be1a0ed..676ff71 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 cc2ce5a..91b0ef9 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/inet.c b/contrib/libpcap/inet.c index 43eafe7..561781a 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/optimize.c b/contrib/libpcap/optimize.c index ea9f50d..173bc55 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 5b0eab6..085f181 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 80d589d..deb15ac 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 67ffaa7..a30f970 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 f8a917a..c927629 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 0000000..21fd113 --- /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, ðpk_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 0000000..c9737ba --- /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 bbfe3e5..a484207 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-linux.c b/contrib/libpcap/pcap-linux.c index df1b646..89ad5c4 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-nit.c b/contrib/libpcap/pcap-nit.c index 86aad0f..097c3be 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 a4dd72f..06e3ab3 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 e84d1c7..1c3158a 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 d022dd3..47bf443 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 1260bd7..acbe548 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 ef1b0f3..cb6c696 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.c b/contrib/libpcap/pcap.c index fbaceb5..7cad9ea 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/pcap1.h b/contrib/libpcap/pcap1.h new file mode 100644 index 0000000..08d0c5a --- /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 ad6649c..a9b127a 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 b7b987d..80a6851 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 cc307bd..0a739fa 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 * |