diff --git a/contrib/libpcap/.cvsignore b/contrib/libpcap/.cvsignore index 12a60dd038c1..a1cfe23a02e0 100644 --- a/contrib/libpcap/.cvsignore +++ b/contrib/libpcap/.cvsignore @@ -3,6 +3,8 @@ config.cache config.status config.h .devel +stamp-h +stamp-h.in Makefile scanner.c grammar.c diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES index 5793de0671c6..87c27845907c 100644 --- a/contrib/libpcap/CHANGES +++ b/contrib/libpcap/CHANGES @@ -1,4 +1,11 @@ -@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.55 2001/01/10 04:10:33 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.56 2001/10/23 04:37:31 mcr Exp $ (LBL) + +Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release + + Added pcap_findalldevs() call to get list of interfaces in a MI way. + + pcap_stats() has been documented as to what its counters mean on + each platform. Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release diff --git a/contrib/libpcap/CREDITS b/contrib/libpcap/CREDITS index 57972372e39d..77127dcfe9fe 100644 --- a/contrib/libpcap/CREDITS +++ b/contrib/libpcap/CREDITS @@ -13,22 +13,41 @@ The current maintainers: Additional people who have contributed patches: Arkadiusz Miskiewicz + Armando L. Caro Jr. Fulvio Risso Charles M. Hannum Chris G. Demetriou + Chris Pepper Darren Reed + Franz Schaefer Greg Troxel + Hyung Sik Yoon + Igor Khristophorov + Jason R. Thorpe + Javier Achirica Jefferson Ogata Juergen Schoenwaelder + Klaus Klein Lorenzo Cavallaro Love Hörnquist-Åstrand + Maciej W. Rozycki + Marcus Felipe Pereira + Martin Husemann Monroe Williams Olaf Kirch + Onno van der Linden + Pavel Kankovsky Peter Jeremy + Phil Wood Rafal Maszkowski Rick Jones + Scott Barron + Scott Gifford + Stefan Hudson Tony Li + Uns Lider Uwe Girlich + Xianjie Zhang The original LBL crew: Steve McCanne diff --git a/contrib/libpcap/FILES b/contrib/libpcap/FILES index 36141caed197..bf18f7e5ca81 100644 --- a/contrib/libpcap/FILES +++ b/contrib/libpcap/FILES @@ -1,17 +1,19 @@ CHANGES CREDITS FILES -INSTALL +INSTALL.txt LICENSE Makefile.in README README.aix README.linux +README.tru64 SUNOS4/nit_if.o.sparc SUNOS4/nit_if.o.sun3 SUNOS4/nit_if.o.sun4c.4.0.3c VERSION aclocal.m4 +arcnet.h bpf/net/bpf.h bpf/net/bpf_filter.c bpf_dump.c @@ -32,6 +34,7 @@ lbl/os-osf4.h lbl/os-solaris2.h lbl/os-sunos4.h lbl/os-ultrix4.h +llc.h mkdep nametoaddr.c nlpid.h diff --git a/contrib/libpcap/INSTALL.txt b/contrib/libpcap/INSTALL.txt new file mode 100644 index 000000000000..1325f8089d85 --- /dev/null +++ b/contrib/libpcap/INSTALL.txt @@ -0,0 +1,342 @@ +@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.2 2001/06/05 03:45:53 guy Exp $ (LBL) + +To build libpcap, run "./configure" (a shell script). The configure +script will determine your system attributes and generate an +appropriate Makefile from Makefile.in. Next run "make". If everything +goes well you can su to root and run "make install". However, you need +not install libpcap if you just want to build tcpdump; just make sure +the tcpdump and libpcap directory trees have the same parent +directory. + +If configure says: + + configure: warning: cannot determine packet capture interface + configure: warning: (see INSTALL for more info) + +then your system either does not support packet capture or your system +does support packet capture but libpcap does not support that +particular type. (If you have HP-UX, see below.) If your system uses a +packet capture not supported by libpcap, please send us patches; don't +forget to include an autoconf fragment suitable for use in +configure.in. + +It is possible to override the default packet capture type, although +the circumstance where this works are limited. For example if you have +installed bpf under SunOS 4 and wish to build a snit libpcap: + + ./configure --with-pcap=snit + +Another example is to force a supported packet capture type in the case +where the configure scripts fails to detect it. + +You will need an ANSI C compiler to build libpcap. The configure script +will abort if your compiler is not ANSI compliant. If this happens, use +the GNU C compiler, available via anonymous ftp: + + ftp://ftp.gnu.org/pub/gnu/gcc/ + +If you use flex, you must use version 2.4.6 or higher. The configure +script automatically detects the version of flex and will not use it +unless it is new enough. You can use "flex -V" to see what version you +have (unless it's really old). The current version of flex is available +via anonymous ftp: + + ftp://ftp.ee.lbl.gov/flex-*.tar.Z + +As of this writing, the current version is 2.5.4. + +If you use bison, you must use flex (and visa versa). The configure +script automatically falls back to lex and yacc if both flex and bison +are not found. + +Sometimes the stock C compiler does not interact well with flex and +bison. The list of problems includes undefined references for alloca. +You can get around this by installing gcc or manually disabling flex +and bison with: + + ./configure --without-flex --without-bison + +If your system only has AT&T lex, this is okay unless your libpcap +program uses other lex/yacc generated code. (Although it's possible to +map the yy* identifiers with a script, we use flex and bison so we +don't feel this is necessary.) + +Some systems support the Berkeley Packet Filter natively; for example +out of the box OSF and BSD/OS have bpf. If your system does not support +bpf, you will need to pick up: + + ftp://ftp.ee.lbl.gov/bpf-*.tar.Z + +Note well: you MUST have kernel source for your operating system in +order to install bpf. An exception is SunOS 4; the bpf distribution +includes replacement kernel objects for some of the standard SunOS 4 +network device drivers. See the bpf INSTALL document for more +information. + +If you use Solaris, there is a bug with bufmod(7) that is fixed in +Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the +broken bufmod(7) results in data be truncated from the FRONT of the +packet instead of the end. The work around is to not set a snapshot +length but this results in performance problems since the entire packet +is copied to user space. If you must run an older version of Solaris, +there is a patch available from Sun; ask for bugid 1149065. After +installing the patch, use "setenv BUFMOD_FIXED" to enable use of +bufmod(7). However, we recommend you run a more current release of +Solaris. + +If you use the SPARCompiler, you must be careful to not use the +/usr/ucb/cc interface. If you do, you will get bogus warnings and +perhaps errors. Either make sure your path has /opt/SUNWspro/bin +before /usr/ucb or else: + + setenv CC /opt/SUNWspro/bin/cc + +before running configure. (You might have to do a "make distclean" +if you already ran configure once). + +Also note that "make depend" won't work; while all of the known +universe uses -M, the SPARCompiler uses -xM to generate makefile +dependencies. + +If you are trying to do packet capture with a FORE ATM card, you may or +may not be able to. They usually only release their driver in object +code so unless their driver supports packet capture, there's not much +libpcap can do. + +If you get an error like: + + tcpdump: recv_ack: bind error 0x??? + +when using DLPI, look for the DL_ERROR_ACK error return values, usually +in /usr/include/sys/dlpi.h, and find the corresponding value. + +Under {DEC OSF/1, Digital UNIX, Tru64 UNIX}, packet capture must be +enabled before it can be used. For instructions on how to enable packet +filter support, see: + + ftp://ftp.digital.com/pub/Digital/dec-faq/Digital-UNIX + +Look for the "How do I configure the Berkeley Packet Filter and capture +tcpdump traces?" item. + +Once you enable packet filter support, your OSF system will support bpf +natively. + +Under Ultrix, packet capture must be enabled before it can be used. For +instructions on how to enable packet filter support, see: + + ftp://ftp.digital.com/pub/Digital/dec-faq/ultrix + +If you use HP-UX, you must have at least version 9 and either the +version of cc that supports ANSI C (cc -Aa) or else use the GNU C +compiler. You must also buy the optional streams package. If you don't +have: + + /usr/include/sys/dlpi.h + /usr/include/sys/dlpi_ext.h + +then you don't have the streams package. In addition, we believe you +need to install the "9.X LAN and DLPI drivers cumulative" patch +(PHNE_6855) to make the version 9 DLPI work with libpcap. + +The DLPI streams package is standard starting with HP-UX 10. + +The HP implementation of DLPI is a little bit eccentric. Unlike +Solaris, you must attach /dev/dlpi instead of the specific /dev/* +network pseudo device entry in order to capture packets. The PPA is +based on the ifnet "index" number. Under HP-UX 9, it is necessary to +read /dev/kmem and the kernel symbol file (/hp-ux). Under HP-UX 10, +DLPI can provide information for determining the PPA. It does not seem +to be possible to trace the loopback interface. Unlike other DLPI +implementations, PHYS implies MULTI and SAP and you get an error if you +try to enable more than one promiscuous mode at a time. + +It is impossible to capture outbound packets on HP-UX 9. To do so on +HP-UX 10, you will, apparently, need a late "LAN products cumulative +patch" (at one point, it was claimed that this would be PHNE_18173 for +s700/10.20; at another point, it was claimed that the required patches +were PHNE_20892, PHNE_20725 and PHCO_10947, or newer patches), and to do +so on HP-UX 11 you will, apparently, need the latest lancommon/DLPI +patches and the latest driver patch for the interface(s) in use on HP-UX +11 (at one point, it was claimed that patches PHNE_19766, PHNE_19826, +PHNE_20008, and PHNE_20735 did the trick). + +Furthermore, on HP-UX 10, you will need to turn on a kernel switch by +doing + + echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem + +You would have to arrange that this happen on reboots; the right way to +do that would probably be to put it into an executable script file +"/sbin/init.d/outbound_promisc" and making +"/sbin/rc2.d/S350outbound_promisc" a symbolic link to that script. + +Finally, testing shows that there can't be more than one simultaneous +DLPI user per network interface. + +If you use Linux, this version of libpcap is known to compile and run +under Red Hat 4.0 with the 2.0.25 kernel. It may work with earlier 2.X +versions but is guaranteed not to work with 1.X kernels. Running more +than one libpcap program at a time, on a system with a 2.0.X kernel, can +cause problems since promiscuous mode is implemented by twiddling the +interface flags from the libpcap application; the packet capture +mechanism in the 2.2 and later kernels doesn't have this problem. Also, +packet timestamps aren't very good. This appears to be due to haphazard +handling of the timestamp in the kernel. + +Note well: there is rumoured to be a version of tcpdump floating around +called 3.0.3 that includes libpcap and is supposed to support Linux. +You should be advised that neither the Network Research Group at LBNL +nor the Tcpdump Group ever generated a release with this version number. +The LBNL Network Research Group notes with interest that a standard +cracker trick to get people to install trojans is to distribute bogus +packages that have a version number higher than the current release. +They also noted with annoyance that 90% of the Linux related bug reports +they got are due to changes made to unofficial versions of their page. +If you are having trouble but aren't using a version that came from +tcpdump.org, please try that before submitting a bug report! + +On Linux, libpcap will not work if the kernel does not have the packet +socket option enabled; see the README.linux file for information about +this. + +If you use AIX, you may not be able to build libpcap from this release. +We do not have an AIX system in house so it's impossible for us to test +AIX patches submitted to us. We are told that you must link against +/lib/pse.exp, that you must use AIX cc or a GNU C compiler newer than +2.7.2, and that you may need to run strload before running a libpcap +application. + +Read the README.aix file for information on installing libpcap and +configuring your system to be able to support libpcap. + +If you use NeXTSTEP, you will not be able to build libpcap from this +release. We hope to support this operating system in some future +release of libpcap. + +If you use SINIX, you should be able to build libpcap from this +release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS +V1.0 or V1.1 compiler. But note that in some releases of SINIX, yacc +emits incorrect code; if grammar.y fails to compile, change every +occurence of: + + #ifdef YYDEBUG + +to: + #if YYDEBUG + +Another workaround is to use flex and bison. + +If you use SCO, you might have trouble building libpcap from this +release. We do not have a machine running SCO and have not had reports +of anyone successfully building on it. Since SCO apparently supports +DLPI, it's possible the current version works. Meanwhile, SCO provides +a tcpdump binary as part of their "Network/Security Tools" package: + + http://www.sco.com/technology/internet/goodies/#SECURITY + +There is also a README that explains how to enable packet capture. + +If you use UnixWare, you will not be able to build libpcap from this +release. We hope to support this operating system in some future +release of libpcap. Meanwhile, there appears to be an UnixWare port of +libpcap 0.0 (and tcpdump 3.0) in: + + ftp://ftp1.freebird.org/pub/mirror/freebird/internet/systools/ + +UnixWare appears to use a hacked version of DLPI. + +If linking tcpdump fails with "Undefined: _alloca" when using bison on +a Sun4, your version of bison is broken. In any case version 1.16 or +higher is recommended (1.14 is known to cause problems 1.16 is known to +work). Either pick up a current version from: + + ftp://ftp.gnu.org/pub/gnu/bison + +or hack around it by inserting the lines: + + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else + #ifdef sparc + #include + #else + char *alloca (); + #endif + #endif + +right after the (100 line!) GNU license comment in bison.simple, remove +grammar.[co] and fire up make again. + +If you use SunOS 4, your kernel must support streams NIT. If you run a +libpcap program and it dies with: + + /dev/nit: No such device + +You must add streams NIT support to your kernel configuration, run +config and boot the new kernel. + +If you are running a version of SunOS earlier than 4.1, you will need +to replace the Sun supplied /sys/sun{3,4,4c}/OBJ/nit_if.o with the +appropriate version from this distribution's SUNOS4 subdirectory and +build a new kernel: + + nit_if.o.sun3-sunos4 (any flavor of sun3) + nit_if.o.sun4c-sunos4.0.3c (SS1, SS1+, IPC, SLC, etc.) + nit_if.o.sun4-sunos4 (Sun4's not covered by + nit_if.o.sun4c-sunos4.0.3c) + +These nit replacements fix a bug that makes nit essentially unusable in +pre-SunOS 4.1. In addition, our sun4c-sunos4.0.3c nit gives you +timestamps to the resolution of the SS-1 clock (1 us) rather than the +lousy 20ms timestamps Sun gives you (tcpdump will print out the full +timestamp resolution if it finds it's running on a SS-1). + +FILES +----- +CHANGES - description of differences between releases +FILES - list of files exported as part of the distribution +INSTALL - this file +Makefile.in - compilation rules (input to the configure script) +README - description of distribution +SUNOS4 - pre-SunOS 4.1 replacement kernel nit modules +VERSION - version of this release +aclocal.m4 - autoconf macros +bpf/net - copies of bpf_filter.c and bpf.h +bpf_filter.c - symlink to bpf/net/bpf_filter.c +bpf_image.c - bpf disassembly routine +config.guess - autoconf support +config.sub - autoconf support +configure - configure script (run this first) +configure.in - configure script source +etherent.c - /etc/ethers support routines +ethertype.h - ethernet protocol types and names definitions +gencode.c - bpf code generation routines +gencode.h - bpf code generation definitions +grammar.y - filter string grammar +inet.c - network routines +install-sh - BSD style install script +lbl/gnuc.h - gcc macros and defines +lbl/os-*.h - os dependent defines and prototypes +mkdep - construct Makefile dependency list +nametoaddr.c - hostname to address routines +net - symlink to bpf/net +optimize.c - bpf optimization routines +pcap-bpf.c - BSD Packet Filter support +pcap-dlpi.c - Data Link Provider Interface support +pcap-enet.c - enet support +pcap-int.h - internal libpcap definitions +pcap-namedb.h - public libpcap name database definitions +pcap-nit.c - Network Interface Tap support +pcap-nit.h - Network Interface Tap definitions +pcap-null.c - dummy monitor support (allows offline use of libpcap) +pcap-pf.c - Packet Filter support +pcap-pf.h - Packet Filter definitions +pcap-snit.c - Streams based Network Interface Tap support +pcap-snoop.c - Snoop network monitoring support +pcap.3 - manual entry +pcap.c - pcap utility routines +pcap.h - public libpcap definitions +ppp.h - Point to Point Protocol definitions +savefile.c - offline support +scanner.l - filter string scanner diff --git a/contrib/libpcap/Makefile.in b/contrib/libpcap/Makefile.in index 600087a6bd7c..9b0ae7967b8e 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.87.2.1 2001/01/18 04:06:24 guy Exp $ (LBL) +# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.88 2001/01/18 04:05:12 guy Exp $ (LBL) # # Various configurable paths (remember to edit Makefile.in, not Makefile) diff --git a/contrib/libpcap/README b/contrib/libpcap/README index c4161cd0049f..ca6347c5ebf6 100644 --- a/contrib/libpcap/README +++ b/contrib/libpcap/README @@ -1,18 +1,18 @@ -@(#) $Header: /tcpdump/master/libpcap/README,v 1.22 2000/07/13 06:24:14 guy Exp $ (LBL) +@(#) $Header: /tcpdump/master/libpcap/README,v 1.24 2001/06/05 03:45:55 guy Exp $ (LBL) -LIBPCAP 0.5 +LIBPCAP 0.6.2 Now maintained by "The Tcpdump Group" See www.tcpdump.org Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org Anonymous CVS is available via: - cvs -d cvs.tcpdump.org:/tcpdump/master login + cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master login (password "anoncvs") - cvs -d cvs.tcpdump.org:/tcpdump/master checkout libpcap + cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout libpcap -Version 0.5 of LIBPCAP can be retrived with the CVS tag "libpcap_0_5": - cvs -d cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_5 libpcap +Version 0.6.2 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_6rel2": + cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_6rel2 libpcap Please send patches against the master copy to patches@tcpdump.org. diff --git a/contrib/libpcap/README.aix b/contrib/libpcap/README.aix index c78a40b0bb40..ad2ce451785f 100644 --- a/contrib/libpcap/README.aix +++ b/contrib/libpcap/README.aix @@ -1,6 +1,20 @@ -(1) To configure libpcap under AIX 4.x, you should use DLPI instead - of BPF, since IBM's version of BPF includes some undocumented - and unsupported changes to the original BPF. +(1) AIX 4.x's version of BPF is undocumented and somewhat unstandard; the + current BPF support code includes changes that should work around + that, but, lacking an AIX machine on which to compile it, we don't + know whether the BPF support for AIX will compile. + + If it doesn't, or if the workarounds fail to make it work correctly, + you should send to tcpdump-workers@tcpdump.org a detailed bug report + (if the compile fails, send us the compile error messages; if it + compiles but fails to work correctly, send us as detailed as + possible a description of the symptoms, including indications of the + network link-layer type being wrong or time stamps being wrong). + + If you fix the problems yourself, please send to patches@tcpdump.org + a patch, so we can incorporate them into the next release. + + If you don't fix the problems yourself, you can, as a workaround, + make libpcap use DLPI instead of BPF. This can be done by specifying the flag: @@ -8,39 +22,39 @@ to the "configure" script for libpcap. -(2) Also, it is a good idea to have the latest version of the DLPI - driver on your system, since certain versions may be buggy and - cause your AIX system to crash. DLPI is included in the - fileset bos.rte.tty. I found that the DLPI driver that came with - AIX 4.3.2 was buggy, and had to upgrade to bos.rte.tty 4.3.2.4: +(2) Also, it is a good idea to have the latest version of the DLPI + driver on your system, since certain versions may be buggy and + cause your AIX system to crash. DLPI is included in the + fileset bos.rte.tty. I found that the DLPI driver that came with + AIX 4.3.2 was buggy, and had to upgrade to bos.rte.tty 4.3.2.4: - lslpp -l bos.rte.tty + lslpp -l bos.rte.tty - bos.rte.tty 4.3.2.4 COMMITTED Base TTY Support and Commands + bos.rte.tty 4.3.2.4 COMMITTED Base TTY Support and Commands - Updates for AIX filesets can be obtained from: - ftp://service.software.ibm.com/aix/fixes/ + Updates for AIX filesets can be obtained from: + ftp://service.software.ibm.com/aix/fixes/ - These updates can be installed with the smit program. + These updates can be installed with the smit program. -(3) After compiling libpcap, you need to make sure that the DLPI driver - is loaded. Type: +(3) After compiling libpcap, you need to make sure that the DLPI driver + is loaded. Type: - strload -q -d dlpi + strload -q -d dlpi - If the result is: - dlpi: yes + If the result is: + dlpi: yes - then the DLPI driver is loaded correctly. + then the DLPI driver is loaded correctly. - If it is: - dlpi: no + If it is: + dlpi: no - Then you need to type: - strload -f /etc/dlpi.conf + Then you need to type: + strload -f /etc/dlpi.conf - Check again with strload -q -d dlpi that the dlpi driver is loaded. + Check again with strload -q -d dlpi that the dlpi driver is loaded. - Alternatively, you can uncomment the lines for DLPI in - /etc/pse.conf and reboot the machine; this way DLPI will always - be loaded when you boot your system. + Alternatively, you can uncomment the lines for DLPI in + /etc/pse.conf and reboot the machine; this way DLPI will always + be loaded when you boot your system. diff --git a/contrib/libpcap/README.linux b/contrib/libpcap/README.linux index ecd00e8fe893..dd959139d3f9 100644 --- a/contrib/libpcap/README.linux +++ b/contrib/libpcap/README.linux @@ -68,3 +68,21 @@ file says: Filtering works on all socket types except TCP for now. See the text file linux/Documentation/networking/filter.txt for more information. If unsure, say N. + + +Statistics: +Statistics reported by pcap are platform specific. The statistics +reported by pcap_stats on Linux are as follows: + +2.2.x +===== +ps_recv Number of packets that were accepted by the pcap filter +ps_drops Always 0, this statistic is not gatherd on this platform + +2.4.x +===== +ps_rec Number of packets that were accepted by the pcap filter +ps_drops Number of packets that had passed filtering but were not + passed on to pcap due to things like buffer shortage, etc. + This is useful because these are packets you are interested in + but won't be reported by, for example, tcpdump output. diff --git a/contrib/libpcap/README.tru64 b/contrib/libpcap/README.tru64 new file mode 100644 index 000000000000..7fe1ef07b530 --- /dev/null +++ b/contrib/libpcap/README.tru64 @@ -0,0 +1,49 @@ +The following instructions are applicable to Tru64 UNIX +(formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and +probably to later versions as well; at least some options apply to +Digital UNIX 3.2 - perhaps all do. + +In order to use kernel packet filtering on this system, you have +to configure it in such a way: + +Kernel configuration +-------------------- + +The packet filtering kernel option must be enabled at kernel +installation. If it was not the case, you can rebuild the kernel with +"doconfig -c" after adding the following line in the kernel +configuration file (/sys/conf/): + + option PACKETFILTER + +or use "doconfig" without any arguments to add the packet filter driver +option via the kernel option menu (see the system administration +documentation for information on how to do this). + +Device configuration +-------------------- + +Devices used for packet filtering must be created thanks to +the following command (executed in the /dev directory): + + ./MAKEDEV pfilt + +Interface configuration +----------------------- + +In order to capture all packets on a network, you may want to allow +applications to put the interface on that network into "local copy" +mode, so that tcpdump can see packets sent by the host on which it's +running as well as packets received by that host, and to put the +interface into "promiscuous" mode, so that tcpdump can see packets on +the network segment not sent to the host on which it's running, by using +the pfconfig(1) command: + + pfconfig +c +p + +or allow application to put any interface into "local copy" or +"promiscuous" mode by using the command: + + pfconfig +c +p -a + +Note: all instructions given require root privileges. diff --git a/contrib/libpcap/TODO b/contrib/libpcap/TODO index e90b9d83dcf5..633a776a6d9e 100644 --- a/contrib/libpcap/TODO +++ b/contrib/libpcap/TODO @@ -11,14 +11,14 @@ General should stick to the standard. - The source files should be better documented. There is no official - design guideline what is done where. There should be a common coding - style (okay, you can guess that bye looking at the code) and a guideline + design guideline for what is done where. There should be a common coding + style (okay, you can guess that by looking at the code) and a guide for what needs to be documented. Linux kernel interface - Currently there is a race condition in that a socket is activated at the - same time when it is opened - before applying a filter. This has to + same time it is opened - before applying a filter. This has to be corrected so that capture starts when pcap_read is called for the first time. @@ -28,9 +28,13 @@ Less urgent items - Better documentation and cleanup of the interface. I am seeing a few problems at the first glance which needs fixing: + pcap_lookupnet makes little to no sense with protocols != IPv4 - + not very suited for interactive programs (think ethereal). There should - be a way for the application to get a file descriptor which it has to - monitor and a callback in pcap which has to be called on activity + + not very well suited for interactive programs (think ethereal). There + should be a way for the application to get a file descriptor which it + has to monitor and a callback in pcap which has to be called on + activity (XXX - "pcap_fileno()" handles the first part, although + "select()" and "poll()" don't work on BPF devices on most BSDs, and + you can call "pcap_dispatch()" as the dispatch routine after putting + the descriptor into non-blocking mode) + too many functions. There are a lot of functions for everything which violates the KISS principle. Why do we need pcap_strerror, pcap_perror and pcap_geterr? diff --git a/contrib/libpcap/VERSION b/contrib/libpcap/VERSION index 5a2a5806df6e..eb49d7c7fdcb 100644 --- a/contrib/libpcap/VERSION +++ b/contrib/libpcap/VERSION @@ -1 +1 @@ -0.6 +0.7 diff --git a/contrib/libpcap/acconfig.h b/contrib/libpcap/acconfig.h new file mode 100644 index 000000000000..a23f320c2461 --- /dev/null +++ b/contrib/libpcap/acconfig.h @@ -0,0 +1,7 @@ +/* Long story short: aclocal.m4 depends on autoconf 2.13 + * implementation details wrt "const"; newer versions + * have different implementation details so for now we + * put "const" here. This may cause duplicate definitions + * in config.h but that should be OK since they're the same. + */ +#undef const diff --git a/contrib/libpcap/arcnet.h b/contrib/libpcap/arcnet.h new file mode 100644 index 000000000000..dce73353e540 --- /dev/null +++ b/contrib/libpcap/arcnet.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Id: arcnet.h,v 1.2 2001/04/24 02:17:52 guy Exp $ (LBL) + * + * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp + */ + +/* RFC 1051 */ +#define ARCTYPE_IP_OLD 240 /* IP protocol */ +#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ + +/* RFC 1201 */ +#define ARCTYPE_IP 212 /* IP protocol */ +#define ARCTYPE_ARP 213 /* address resolution protocol */ +#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ + +#define ARCTYPE_ATALK 221 /* Appletalk */ +#define ARCTYPE_BANIAN 247 /* Banyan Vines */ +#define ARCTYPE_IPX 250 /* Novell IPX */ + +#define ARCTYPE_INET6 0xc4 /* IPng */ +#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */ diff --git a/contrib/libpcap/config.guess b/contrib/libpcap/config.guess index 980ea5b09820..ba661651615d 100755 --- a/contrib/libpcap/config.guess +++ b/contrib/libpcap/config.guess @@ -1,9 +1,9 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. -timestamp='2000-12-15' +timestamp='2001-04-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -33,10 +33,6 @@ timestamp='2000-12-15' # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. -# -# Only a few systems have been added to this list; please add others -# (but try to keep the structure clean). -# me=`echo "$0" | sed -e 's,.*/,,'` @@ -93,7 +89,7 @@ fi dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still @@ -107,7 +103,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in CC_FOR_BUILD="$c"; break fi done - rm -f $dummy.c $dummy.o + rm -f $dummy.c $dummy.o $dummy.rel if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi @@ -276,7 +272,7 @@ EOF arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; - SR2?01:HI-UX/MPP:*:*) + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) @@ -412,10 +408,13 @@ EOF EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm $dummy.c $dummy && exit 0 + && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; @@ -463,9 +462,17 @@ EOF ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i?86:AIX:*:*) + i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then sed 's/^ //' << EOF >$dummy.c @@ -479,7 +486,7 @@ EOF exit(0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then @@ -488,9 +495,9 @@ EOF echo rs6000-ibm-aix3.2 fi exit 0 ;; - *:AIX:*:4) + *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc @@ -498,23 +505,10 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=4.${UNAME_RELEASE} + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; - *:AIX:*:5) - case "`lsattr -El proc0 -a type -F value`" in - PowerPC*) IBM_ARCH=powerpc - IBM_MANUF=ibm ;; - Itanium) IBM_ARCH=ia64 - IBM_MANUF=unknown ;; - POWER*) IBM_ARCH=power - IBM_MANUF=ibm ;; - *) IBM_ARCH=powerpc - IBM_MANUF=ibm ;; - esac - echo ${IBM_ARCH}-${IBM_MANUF}-aix${UNAME_VERSION}.${UNAME_RELEASE} - exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; @@ -599,6 +593,10 @@ EOF esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; 3050*:HI-UX:*:*) sed 's/^ //' << EOF >$dummy.c #include @@ -625,7 +623,7 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; @@ -644,7 +642,7 @@ EOF hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; - i?86:OSF1:*:*) + i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else @@ -701,18 +699,16 @@ EOF CRAY-2:*:*:*) echo cray2-cray-unicos exit 0 ;; - F300:UNIX_System_V:*:*) + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; - F301:UNIX_System_V:*:*) - echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` - exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) @@ -757,60 +753,38 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; - *:Linux:*:*) - - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_emulations=`cd /; ld --help 2>&1 \ - | sed -ne '/supported emulations:/!d - s/[ ][ ]*/ /g - s/.*supported emulations: *// - s/ .*// - p'` - case "$ld_supported_emulations" in - *ia64) - echo "${UNAME_MACHINE}-unknown-linux" - exit 0 - ;; - i?86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i?86) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - i?86coff) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 - ;; - sparclinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - elf32_sparc) - echo "${UNAME_MACHINE}-unknown-linux-gnu" - exit 0 - ;; - armlinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - elf32arm*) - echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" - exit 0 - ;; - armelf_linux*) - echo "${UNAME_MACHINE}-unknown-linux-gnu" - exit 0 - ;; - m68klinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - elf32ppc | elf32ppclinux) - # Determine Lib Version - cat >$dummy.c <$dummy.c < /* for printf() prototype */ +int main (int argc, char *argv[]) { +#else +int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + ;; + ppc:Linux:*:*) + # Determine Lib Version + cat >$dummy.c < #if defined(__GLIBC__) extern char __libc_version[]; @@ -823,143 +797,127 @@ main(argc, argv) #if defined(__GLIBC__) printf("%s %s\n", __libc_version, __libc_release); #else - printf("unkown\n"); + printf("unknown\n"); #endif return 0; } EOF - LIBC="" - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then LIBC="libc1" ; fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 ;; + alpha:Linux:*:*) + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) UNAME_MACHINE="alpha" ;; + 1-0) UNAME_MACHINE="alphaev5" ;; + 1-1) UNAME_MACHINE="alphaev56" ;; + 1-101) UNAME_MACHINE="alphapca56" ;; + 2-303) UNAME_MACHINE="alphaev6" ;; + 2-307) UNAME_MACHINE="alphaev67" ;; + esac + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null if test "$?" = 0 ; then - ./$dummy | grep 1\.99 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi + LIBC="libc1" fi - rm -f $dummy.c $dummy - echo powerpc-unknown-linux-gnu${LIBC} + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_supported_emulations=`cd /; ld --help 2>&1 \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i*86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; - shelf_linux) - echo "${UNAME_MACHINE}-unknown-linux-gnu" + elf_i*86) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + i*86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; esac - - if test "${UNAME_MACHINE}" = "alpha" ; then - cat <$dummy.s - .data - \$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main - main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - LIBC="" - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - - objdump --private-headers $dummy | \ - grep ld.so.1 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 - elif test "${UNAME_MACHINE}" = "mips" ; then - cat >$dummy.c < /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __MIPSEB__ - printf ("%s-unknown-linux-gnu\n", argv[1]); -#endif -#ifdef __MIPSEL__ - printf ("%sel-unknown-linux-gnu\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - elif test "${UNAME_MACHINE}" = "s390"; then - echo s390-ibm-linux && exit 0 - elif test "${UNAME_MACHINE}" = "x86_64"; then - echo x86_64-unknown-linux-gnu && exit 0 - elif test "${UNAME_MACHINE}" = "parisc" -o "${UNAME_MACHINE}" = "hppa"; then - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) - echo hppa1.1-unknown-linux-gnu - ;; - PA8*) - echo hppa2.0-unknown-linux-gnu - ;; - *) - echo hppa-unknown-linux-gnu - ;; - esac - exit 0 - else - # Either a pre-BFD a.out linker (linux-gnuoldld) - # or one that does not give us useful --help. - # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. - # If ld does not provide *any* "supported emulations:" - # that means it is gnuoldld. - test -z "$ld_supported_emulations" \ - && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - - case "${UNAME_MACHINE}" in - i?86) - VENDOR=pc; - ;; - *) - VENDOR=unknown; - ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c <$dummy.c < #ifdef __cplusplus #include /* for printf() prototype */ @@ -983,16 +941,16 @@ EOF return 0; } EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - fi ;; + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions # are messed up and put the nodename in both sysname and nodename. - i?86:DYNIX/ptx:4*:*) + i*86:DYNIX/ptx:4*:*) echo i386-sequent-sysv4 exit 0 ;; - i?86:UNIX_SV:4.2MP:2.*) + i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, @@ -1000,7 +958,7 @@ EOF # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; - i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} @@ -1008,7 +966,7 @@ EOF echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; - i?86:*:5:7*) + i*86:*:5:7*) # Fixed at (any) Pentium or better UNAME_MACHINE=i586 if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then @@ -1017,7 +975,7 @@ EOF echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} fi exit 0 ;; - i?86:*:3.2:*) + i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:*) + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; - rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; @@ -1188,11 +1149,29 @@ EOF fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; - i?86:OS/2:*:*) + i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1284,11 +1263,24 @@ main () #endif #if defined (vax) -#if !defined (ultrix) - printf ("vax-dec-bsd\n"); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif #endif #if defined (alliant) && defined (i860) @@ -1299,7 +1291,7 @@ main () } EOF -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. @@ -1335,8 +1327,9 @@ fi cat >&2 < in order to provide the needed information to handle your system. -config.guess version = $version +config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` diff --git a/contrib/libpcap/config.h.in b/contrib/libpcap/config.h.in index f012a9d500d9..dfa7b3607208 100644 --- a/contrib/libpcap/config.h.in +++ b/contrib/libpcap/config.h.in @@ -6,12 +6,17 @@ /* Define as __inline if that's what the C compiler calls it. */ #undef inline +/* Long story short: aclocal.m4 depends on autoconf 2.13 + * implementation details wrt "const"; newer versions + * have different implementation details so for now we + * put "const" here. This may cause duplicate definitions + * in config.h but that should be OK since they're the same. + */ +#undef const + /* Define if you have the ether_hostton function. */ #undef HAVE_ETHER_HOSTTON -/* Define if you have the freeifaddrs function. */ -#undef HAVE_FREEIFADDRS - /* Define if you have the strerror function. */ #undef HAVE_STRERROR @@ -21,12 +26,12 @@ /* Define if you have the header file. */ #undef HAVE_IFADDRS_H +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + /* Define if you have the header file. */ #undef HAVE_NETINET_IF_ETHER_H -/* Define if you have the header file. */ -#undef HAVE_NETPACKET_PACKET_H - /* Define if you have the header file. */ #undef HAVE_SYS_BUFMOD_H @@ -60,12 +65,24 @@ /* IPv6 */ #undef INET6 +/* Enable optimizer debugging */ +#undef BDEBUG + +/* Enable parser debugging */ +#undef YYDEBUG + /* define if you have a /dev/dlpi */ #undef HAVE_DEV_DLPI /* /dev/dlpi directory */ #undef PCAP_DEV_PREFIX +/* if if_packet.h has tpacket_stats defined */ +#undef HAVE_TPACKET_STATS + +/* define if you have a /proc/net/dev */ +#undef HAVE_PROC_NET_DEV + /* define on AIX to get certain functions */ #undef _SUN diff --git a/contrib/libpcap/config.sub b/contrib/libpcap/config.sub index 4849dfd81033..a06a480adafd 100755 --- a/contrib/libpcap/config.sub +++ b/contrib/libpcap/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. -timestamp='2000-12-15' +timestamp='2001-04-20' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -69,7 +69,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -117,7 +117,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos*) + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -226,12 +226,15 @@ case $basic_machine in | alphaev6[78] \ | we32k | ns16k | clipper | i370 | sh | sh[34] \ | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | 1750a | dsp16xx | pdp10 | pdp11 \ + | mips16 | mips64 | mipsel | mips64el \ | mips64orion | mips64orionel | mipstx39 | mipstx39el \ | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | miprs64vr5000el | mcore \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ - | thumb | d10v | d30v | fr30 | avr) + | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ + | v850 | c4x \ + | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ + | pj | pjl | h8500) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) @@ -239,13 +242,13 @@ case $basic_machine in basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. - i[234567]86 | x86_64) + i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. @@ -255,7 +258,7 @@ case $basic_machine in ;; # Recognize the basic CPU types with company name. # FIXME: clean up the formatting here. - vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ @@ -268,15 +271,17 @@ case $basic_machine in | alphaev6[78]-* \ | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ | clipper-* | orion-* \ - | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ - | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ + | mips16-* | mips64-* | mipsel-* \ | mips64el-* | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ | mipstx39-* | mipstx39el-* | mcore-* \ - | f30[01]-* | s390-* | sv1-* | t3e-* \ + | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ + | [cjt]90-* \ | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ - | bs2000-* | tic54x-* | c54x-* | x86_64-*) + | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -367,8 +372,8 @@ case $basic_machine in basic_machine=cray2-cray os=-unicos ;; - [ctj]90-cray) - basic_machine=c90-cray + [cjt]90) + basic_machine=${basic_machine}-cray os=-unicos ;; crds | unos) @@ -424,6 +429,10 @@ case $basic_machine in basic_machine=tron-gmicro os=-sysv ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 @@ -499,19 +508,19 @@ case $basic_machine in basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? - i[34567]86v32) + i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; - i[34567]86v4*) + i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; - i[34567]86v) + i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; - i[34567]86sol2) + i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; @@ -523,18 +532,6 @@ case $basic_machine in basic_machine=i386-unknown os=-vsta ;; - i386-go32 | go32) - basic_machine=i386-unknown - os=-go32 - ;; - i386-mingw32 | mingw32) - basic_machine=i386-unknown - os=-mingw32 - ;; - i[34567]86-pw32 | pw32) - basic_machine=i586-unknown - os=-pw32 - ;; iris | iris4d) basic_machine=mips-sgi case $os in @@ -560,6 +557,10 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; miniframe) basic_machine=m68000-convergent ;; @@ -590,7 +591,7 @@ case $basic_machine in os=-coff ;; msdos) - basic_machine=i386-unknown + basic_machine=i386-pc os=-msdos ;; mvs) @@ -729,6 +730,10 @@ case $basic_machine in ps2) basic_machine=i386-ibm ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -919,6 +924,10 @@ case $basic_machine in vax) basic_machine=vax-dec ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; pdp11) basic_machine=pdp11-dec ;; @@ -928,7 +937,7 @@ case $basic_machine in sh3 | sh4) basic_machine=sh-unknown ;; - sparc | sparcv9) + sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) @@ -950,6 +959,9 @@ case $basic_machine in basic_machine=c4x-none os=-coff ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 @@ -1009,12 +1021,13 @@ case $os in | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* | -storm-chaos*) + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in - x86-* | i[34567]86-*) + x86-* | i*86-*) ;; *) os=-nto$os @@ -1107,7 +1120,7 @@ case $os in -xenix) os=-xenix ;; - -*mint | -*MiNT) + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) @@ -1141,6 +1154,9 @@ case $basic_machine in arm*-semi) os=-aout ;; + pdp10-*) + os=-tops20 + ;; pdp11-*) os=-none ;; @@ -1249,7 +1265,7 @@ case $basic_machine in *-masscomp) os=-rtu ;; - f30[01]-fujitsu) + f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) @@ -1327,7 +1343,7 @@ case $basic_machine in -mpw* | -macos*) vendor=apple ;; - -*mint | -*MiNT) + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; esac diff --git a/contrib/libpcap/configure b/contrib/libpcap/configure index dea3a59e7b02..65d6393513cf 100755 --- a/contrib/libpcap/configure +++ b/contrib/libpcap/configure @@ -1,6 +1,7 @@ #! /bin/sh -# From configure.in Revision: 1.87.2.1 +# From configure.in Revision: 1.94 + @@ -54,6 +55,10 @@ ac_help="$ac_help --with-pcap=TYPE use packet capture TYPE" ac_help="$ac_help --enable-ipv6 build IPv6-capable version" +ac_help="$ac_help + --enable-optimizer-dbg build optimizer debugging code" +ac_help="$ac_help + --enable-yydebug build parser debugging code" ac_help="$ac_help --without-flex don't use flex" ac_help="$ac_help @@ -616,7 +621,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:620: checking host system type" >&5 +echo "configure:625: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -637,7 +642,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:641: checking target system type" >&5 +echo "configure:646: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -655,7 +660,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:659: checking build system type" >&5 +echo "configure:664: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -703,7 +708,7 @@ fi # Extract the first word of "shlicc2", so it can be a program name with args. set dummy shlicc2; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:707: checking for $ac_word" >&5 +echo "configure:712: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -744,7 +749,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:748: checking for $ac_word" >&5 +echo "configure:753: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -774,7 +779,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:778: checking for $ac_word" >&5 +echo "configure:783: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -825,7 +830,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:829: checking for $ac_word" >&5 +echo "configure:834: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -857,7 +862,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:861: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:866: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -868,12 +873,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 872 "configure" +#line 877 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -899,12 +904,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:903: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:908: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:908: checking whether we are using GNU C" >&5 +echo "configure:913: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -913,7 +918,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:922: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -932,7 +937,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:936: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:941: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -969,7 +974,7 @@ fi V_CCOPT="-O2" else echo $ac_n "checking gcc version""... $ac_c" 1>&6 -echo "configure:973: checking gcc version" >&5 +echo "configure:978: checking gcc version" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -987,19 +992,19 @@ fi fi else echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6 -echo "configure:991: checking that $CC handles ansi prototypes" >&5 +echo "configure:996: checking that $CC handles ansi prototypes" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int frob(int, char *) ; return 0; } EOF -if { (eval echo configure:1003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1008: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_ansi_prototypes=yes else @@ -1017,21 +1022,21 @@ fi hpux*) echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6 -echo "configure:1021: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 +echo "configure:1026: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5 savedcflags="$CFLAGS" CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS" if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int frob(int, char *) ; return 0; } EOF -if { (eval echo configure:1035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1040: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_hpux_cc_aa=yes else @@ -1075,12 +1080,12 @@ EOF ultrix*) echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6 -echo "configure:1079: checking that Ultrix $CC hacks const in prototypes" >&5 +echo "configure:1084: checking that Ultrix $CC hacks const in prototypes" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -1088,7 +1093,7 @@ struct a { int b; }; void c(const struct a *) ; return 0; } EOF -if { (eval echo configure:1092: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1097: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_cc_const_proto=yes else @@ -1112,21 +1117,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1116: checking for inline" >&5 +echo "configure:1121: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -1153,13 +1158,13 @@ esac echo $ac_n "checking for __attribute__""... $ac_c" 1>&6 -echo "configure:1157: checking for __attribute__" >&5 +echo "configure:1162: checking for __attribute__" >&5 if eval "test \"`echo '$''{'ac_cv___attribute__'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1176,7 +1181,7 @@ foo(void) ; return 0; } EOF -if { (eval echo configure:1180: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1185: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv___attribute__=yes else @@ -1198,12 +1203,12 @@ echo "$ac_t""$ac_cv___attribute__" 1>&6 echo $ac_n "checking for u_int8_t using $CC""... $ac_c" 1>&6 -echo "configure:1202: checking for u_int8_t using $CC" >&5 +echo "configure:1207: checking for u_int8_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int8_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1225: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int8_t=yes else @@ -1236,12 +1241,12 @@ EOF fi echo $ac_n "checking for u_int16_t using $CC""... $ac_c" 1>&6 -echo "configure:1240: checking for u_int16_t using $CC" >&5 +echo "configure:1245: checking for u_int16_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1263: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int16_t=yes else @@ -1274,12 +1279,12 @@ EOF fi echo $ac_n "checking for u_int32_t using $CC""... $ac_c" 1>&6 -echo "configure:1278: checking for u_int32_t using $CC" >&5 +echo "configure:1283: checking for u_int32_t using $CC" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_have_u_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_have_u_int32_t=yes else @@ -1313,7 +1318,7 @@ EOF fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1317: checking how to run the C preprocessor" >&5 +echo "configure:1322: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1328,13 +1333,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1338: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1343: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1345,13 +1350,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1355: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1360: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1362,13 +1367,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1372: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1392,21 +1397,21 @@ else fi echo "$ac_t""$CPP" 1>&6 -for ac_hdr in sys/ioccom.h sys/sockio.h ifaddrs.h netinet/if_ether.h +for ac_hdr in sys/ioccom.h sys/sockio.h ifaddrs.h limits.h netinet/if_ether.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1400: checking for $ac_hdr" >&5 +echo "configure:1405: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1410: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1415: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1435,12 +1440,12 @@ done if test "$GCC" = yes ; then echo $ac_n "checking for ANSI ioctl definitions""... $ac_c" 1>&6 -echo "configure:1439: checking for ANSI ioctl definitions" >&5 +echo "configure:1444: checking for ANSI ioctl definitions" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_gcc_fixincludes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1468: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_gcc_fixincludes=yes else @@ -1479,15 +1484,15 @@ fi fi fi -for ac_func in ether_hostton strerror freeifaddrs strlcpy +for ac_func in ether_hostton strerror strlcpy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1486: checking for $ac_func" >&5 +echo "configure:1491: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1519: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1536,7 +1541,7 @@ done echo $ac_n "checking if --disable-protochain option is specified""... $ac_c" 1>&6 -echo "configure:1540: checking if --disable-protochain option is specified" >&5 +echo "configure:1545: checking if --disable-protochain option is specified" >&5 # Check whether --enable-protochain or --disable-protochain was given. if test "${enable_protochain+set}" = set; then enableval="$enable_protochain" @@ -1567,7 +1572,7 @@ if test "${with_pcap+set}" = set; then fi echo $ac_n "checking packet capture type""... $ac_c" 1>&6 -echo "configure:1571: checking packet capture type" >&5 +echo "configure:1576: checking packet capture type" >&5 if test ! -z "$with_pcap" ; then V_PCAP="$withval" elif test -r /dev/bpf0 ; then @@ -1598,7 +1603,7 @@ fi echo "$ac_t""$V_PCAP" 1>&6 echo $ac_n "checking if --enable-ipv6 option is specified""... $ac_c" 1>&6 -echo "configure:1602: checking if --enable-ipv6 option is specified" >&5 +echo "configure:1607: checking if --enable-ipv6 option is specified" >&5 # Check whether --enable-ipv6 or --disable-ipv6 was given. if test "${enable_ipv6+set}" = set; then enableval="$enable_ipv6" @@ -1613,6 +1618,38 @@ EOF fi echo "$ac_t""${enable_ipv6-no}" 1>&6 +echo $ac_n "checking whether to build optimizer debugging code""... $ac_c" 1>&6 +echo "configure:1623: checking whether to build optimizer debugging code" >&5 +# Check whether --enable-optimizer-dbg or --disable-optimizer-dbg was given. +if test "${enable_optimizer_dbg+set}" = set; then + enableval="$enable_optimizer_dbg" + : +fi + +if test "$enable_optimizer_dbg" = "yes"; then + cat >> confdefs.h <<\EOF +#define BDEBUG 1 +EOF + +fi +echo "$ac_t""${enable_optimizer_dbg-no}" 1>&6 + +echo $ac_n "checking whether to build parser debugging code""... $ac_c" 1>&6 +echo "configure:1639: checking whether to build parser debugging code" >&5 +# Check whether --enable-yydebug or --disable-yydebug was given. +if test "${enable_yydebug+set}" = set; then + enableval="$enable_yydebug" + : +fi + +if test "$enable_yydebug" = "yes"; then + cat >> confdefs.h <<\EOF +#define YYDEBUG 1 +EOF + +fi +echo "$ac_t""${enable_yydebug-no}" 1>&6 + case "$V_PCAP" in dlpi) @@ -1620,17 +1657,17 @@ dlpi) do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1624: checking for $ac_hdr" >&5 +echo "configure:1661: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1634: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1671: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1657,7 +1694,7 @@ fi done echo $ac_n "checking for /dev/dlpi device""... $ac_c" 1>&6 -echo "configure:1661: checking for /dev/dlpi device" >&5 +echo "configure:1698: checking for /dev/dlpi device" >&5 if test -c /dev/dlpi ; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -1668,7 +1705,7 @@ EOF echo "$ac_t""no" 1>&6 dir="/dev/dlpi" echo $ac_n "checking for $dir directory""... $ac_c" 1>&6 -echo "configure:1672: checking for $dir directory" >&5 +echo "configure:1709: checking for $dir directory" >&5 if test -d $dir ; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <&6 -echo "configure:1690: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 -fi -done - echo $ac_n "checking Linux kernel version""... $ac_c" 1>&6 -echo "configure:1727: checking Linux kernel version" >&5 +echo "configure:1724: checking Linux kernel version" >&5 if test "$cross_compiling" = yes; then if eval "test \"`echo '$''{'ac_cv_linux_vers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1747,6 +1744,39 @@ fi if test $ac_cv_linux_vers -lt 2 ; then { echo "configure: error: version 2 or higher required; see the INSTALL doc for more info" 1>&2; exit 1; } fi + echo $ac_n "checking if if_packet.h has tpacket_stats defined""... $ac_c" 1>&6 +echo "configure:1749: checking if if_packet.h has tpacket_stats defined" >&5 + if eval "test \"`echo '$''{'ac_cv_lbl_tpacket_stats'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +struct tpacket_stats stats +; return 0; } +EOF +if { (eval echo configure:1762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_lbl_tpacket_stats=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_lbl_tpacket_stats=no +fi +rm -f conftest* +fi + + echo "$ac_t""$ac_cv_lbl_tpacket_stats" 1>&6 + if test $ac_cv_lbl_tpacket_stats = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TPACKET_STATS 1 +EOF + + fi ;; null) @@ -1756,6 +1786,21 @@ null) esac +echo $ac_n "checking whether we have /proc/net/dev""... $ac_c" 1>&6 +echo "configure:1791: checking whether we have /proc/net/dev" >&5 +if test -r /proc/net/dev ; then + ac_cv_lbl_proc_net_dev=yes +else + ac_cv_lbl_proc_net_dev=no +fi +if test $ac_cv_lbl_proc_net_dev = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_PROC_NET_DEV 1 +EOF + +fi +echo "$ac_t""$ac_cv_lbl_proc_net_dev" 1>&6 + # Check whether --with-flex or --without-flex was given. if test "${with_flex+set}" = set; then withval="$with_flex" @@ -1776,7 +1821,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1780: checking for $ac_word" >&5 +echo "configure:1825: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1810,7 +1855,7 @@ test -n "$V_LEX" || V_LEX="lex" if test "$V_LEX" = flex ; then # The -V flag was added in 2.4 echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6 -echo "configure:1814: checking for flex 2.4 or higher" >&5 +echo "configure:1859: checking for flex 2.4 or higher" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1836,7 +1881,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1840: checking for $ac_word" >&5 +echo "configure:1885: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1883,7 +1928,7 @@ if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . # Try lexing it and complain if it can't deal. echo $ac_n "checking for capable lex""... $ac_c" 1>&6 -echo "configure:1887: checking for capable lex" >&5 +echo "configure:1932: checking for capable lex" >&5 if eval "test \"`echo '$''{'tcpdump_cv_capable_lex'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1903,7 +1948,7 @@ echo "$ac_t""$tcpdump_cv_capable_lex" 1>&6 fi fi -case "$target_os" in +case "$host_os" in aix*) cat >> confdefs.h <<\EOF @@ -1934,19 +1979,19 @@ EOF sinix*) echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6 -echo "configure:1938: checking if SINIX compiler defines sinix" >&5 +echo "configure:1983: checking if SINIX compiler defines sinix" >&5 if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cc_sinix_defined=yes else @@ -1978,7 +2023,7 @@ esac # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1982: checking for $ac_word" >&5 +echo "configure:2027: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2046,12 +2091,12 @@ EOF fi echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6 -echo "configure:2050: checking if sockaddr struct has sa_len member" >&5 +echo "configure:2095: checking if sockaddr struct has sa_len member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2060,7 +2105,7 @@ int main() { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } EOF -if { (eval echo configure:2064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2109: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_sockaddr_has_sa_len=yes else @@ -2081,12 +2126,12 @@ EOF fi echo $ac_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member""... $ac_c" 1>&6 -echo "configure:2085: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 +echo "configure:2130: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2096,7 +2141,7 @@ int main() { u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1) ; return 0; } EOF -if { (eval echo configure:2100: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2145: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes else @@ -2117,14 +2162,14 @@ EOF fi echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6 -echo "configure:2121: checking if unaligned accesses fail" >&5 +echo "configure:2166: checking if unaligned accesses fail" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - case "$target_cpu" in + case "$host_cpu" in # XXX: should also check that they don't do weird things (like on arm) - alpha*|arm*|hp*|mips|sparc) + alpha*|arm*|hp*|mips*|sparc*|ia64) ac_cv_lbl_unaligned_fail=yes ;; @@ -2202,7 +2247,7 @@ ln -s ${srcdir}/bpf/net net # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2206: checking for a BSD compatible install" >&5 +echo "configure:2251: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.in index c2dfc99c9543..08c42f0a2b5d 100755 --- a/contrib/libpcap/configure.in +++ b/contrib/libpcap/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.87.2.1 2001/01/17 18:21:54 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.94 2001/12/10 08:33:42 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.87.2.1 $) +AC_REVISION($Revision: 1.94 $) AC_INIT(pcap.c) AC_CANONICAL_SYSTEM @@ -25,11 +25,11 @@ 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 netinet/if_ether.h) +AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h ifaddrs.h limits.h netinet/if_ether.h) AC_LBL_FIXINCLUDES -AC_CHECK_FUNCS(ether_hostton strerror freeifaddrs strlcpy) +AC_CHECK_FUNCS(ether_hostton strerror strlcpy) dnl to pacify those who hate protochain insn AC_MSG_CHECKING(if --disable-protochain option is specified) @@ -94,6 +94,20 @@ if test "$enable_ipv6" = "yes"; then fi AC_MSG_RESULT(${enable_ipv6-no}) +AC_MSG_CHECKING(whether to build optimizer debugging code) +AC_ARG_ENABLE(optimizer-dbg, [ --enable-optimizer-dbg build optimizer debugging code]) +if test "$enable_optimizer_dbg" = "yes"; then + AC_DEFINE(BDEBUG,1,[Enable optimizer debugging]) +fi +AC_MSG_RESULT(${enable_optimizer_dbg-no}) + +AC_MSG_CHECKING(whether to build parser debugging code) +AC_ARG_ENABLE(yydebug, [ --enable-yydebug build parser debugging code]) +if test "$enable_yydebug" = "yes"; then + AC_DEFINE(YYDEBUG,1,[Enable parser debugging]) +fi +AC_MSG_RESULT(${enable_yydebug-no}) + case "$V_PCAP" in dlpi) @@ -116,7 +130,6 @@ dlpi) ;; linux) - AC_CHECK_HEADERS(netpacket/packet.h) AC_MSG_CHECKING(Linux kernel version) if test "$cross_compiling" = yes; then AC_CACHE_VAL(ac_cv_linux_vers, @@ -133,6 +146,7 @@ linux) if test $ac_cv_linux_vers -lt 2 ; then AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info) fi + AC_LBL_TPACKET_STATS ;; null) @@ -142,6 +156,17 @@ null) esac +AC_MSG_CHECKING(whether we have /proc/net/dev) +if test -r /proc/net/dev ; then + ac_cv_lbl_proc_net_dev=yes +else + ac_cv_lbl_proc_net_dev=no +fi +if test $ac_cv_lbl_proc_net_dev = yes; then + AC_DEFINE(HAVE_PROC_NET_DEV, 1, [define if you have a /proc/net/dev]) +fi +AC_MSG_RESULT($ac_cv_lbl_proc_net_dev) + AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_) if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . @@ -160,7 +185,7 @@ if test "$V_LEX" = lex ; then fi fi -case "$target_os" in +case "$host_os" in aix*) dnl Workaround to enable certain features diff --git a/contrib/libpcap/ethertype.h b/contrib/libpcap/ethertype.h index 42afe9b0d35a..3af5576e8160 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.11 2000/10/22 04:15:55 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.12 2001/01/14 21:26:52 guy Exp $ (LBL) */ /* @@ -93,12 +93,15 @@ #ifndef ETHERTYPE_AARP #define ETHERTYPE_AARP 0x80f3 #endif -#ifndef ETHERTYPE_IPV6 -#define ETHERTYPE_IPV6 0x86dd -#endif #ifndef ETHERTYPE_8021Q #define ETHERTYPE_8021Q 0x8100 #endif +#ifndef ETHERTYPE_IPX +#define ETHERTYPE_IPX 0x8137 +#endif +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x86dd +#endif #ifndef ETHERTYPE_LOOPBACK #define ETHERTYPE_LOOPBACK 0x9000 #endif diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c index 0b5b69657baf..fa97aafe13ee 100644 --- a/contrib/libpcap/inet.c +++ b/contrib/libpcap/inet.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 1994, 1995, 1996, 1997, 1998 * The Regents of the University of California. All rights reserved. @@ -33,7 +34,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.36 2000/09/20 15:10:29 torsten Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.45 2001/10/28 20:40:43 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -61,6 +62,11 @@ struct rtentry; #include #include #include +#ifdef HAVE_LIMITS_H +#include +#else +#define INT_MAX 2147483647 +#endif #ifdef HAVE_IFADDRS_H #include #endif @@ -73,15 +79,873 @@ struct rtentry; /* Not all systems have IFF_LOOPBACK */ #ifdef IFF_LOOPBACK -#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) -#define ISLOOPBACK_IFA(p) ((p)->ifa_flags & IFF_LOOPBACK) +#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK) #else -#define ISLOOPBACK(p) ((p)->ifr_name[0] == 'l' && (p)->ifr_name[1] == 'o' && \ - (isdigit((p)->ifr_name[2]) || (p)->ifr_name[2] == '\0')) -#define ISLOOPBACK_IFA(p) ((p)->ifa_name[0] == 'l' && (p)->ifa_name[1] == 'o' && \ - (isdigit((p)->ifa_name[2]) || (p)->ifa_name[2] == '\0')) +#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \ + (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0')) #endif +/* + * This is fun. + * + * In older BSD systems, socket addresses were fixed-length, and + * "sizeof (struct sockaddr)" gave the size of the structure. + * All addresses fit within a "struct sockaddr". + * + * In newer BSD systems, the socket address is variable-length, and + * there's an "sa_len" field giving the length of the structure; + * this allows socket addresses to be longer than 2 bytes of family + * and 14 bytes of data. + * + * Some commercial UNIXes use the old BSD scheme, and some might use + * the new BSD scheme. + * + * GNU libc uses neither scheme, but has an "SA_LEN()" macro that + * determines the size based on the address family. + */ +#ifndef SA_LEN +#ifdef HAVE_SOCKADDR_SA_LEN +#define SA_LEN(addr) ((addr)->sa_len) +#else /* HAVE_SOCKADDR_SA_LEN */ +#define SA_LEN(addr) (sizeof (struct sockaddr)) +#endif /* HAVE_SOCKADDR_SA_LEN */ +#endif /* SA_LEN */ + +/* + * Description string for the "any" device. + */ +static const char any_descr[] = "Pseudo-device that captures on all interfaces"; + +static struct sockaddr * +dup_sockaddr(struct sockaddr *sa) +{ + struct sockaddr *newsa; + unsigned int size; + + size = SA_LEN(sa); + if ((newsa = malloc(size)) == NULL) + return (NULL); + return (memcpy(newsa, sa, size)); +} + +static int +get_instance(char *name) +{ + char *cp, *endcp; + int n; + + if (strcmp(name, "any") == 0) { + /* + * Give the "any" device an artificially high instance + * number, so it shows up after all other non-loopback + * interfaces. + */ + return INT_MAX; + } + + endcp = name + strlen(name); + for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) + continue; + + if (isdigit((unsigned char)*cp)) + n = atoi(cp); + else + n = 0; + return (n); +} + +static int +add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, 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? + */ + 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) { + if (strcmp(name, curdev->name) == 0) + break; /* yes, we found it */ + } + if (curdev == NULL) { + /* + * No, we didn't find it. + * Allocate a new entry. + */ + curdev = malloc(sizeof(pcap_if_t)); + if (curdev == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + /* + * Fill in the entry. + */ + curdev->next = NULL; + curdev->name = malloc(strlen(name) + 1); + strcpy(curdev->name, name); + if (description != NULL) { + /* + * We have a description for this interface. + */ + curdev->description = malloc(strlen(description) + 1); + strcpy(curdev->description, description); + } else { + /* + * We don't. + */ + curdev->description = NULL; + } + curdev->addresses = NULL; /* list starts out as empty */ + curdev->flags = 0; + if (ISLOOPBACK(name, flags)) + curdev->flags |= PCAP_IF_LOOPBACK; + + /* + * Add it to the list, in the appropriate location. + * First, get the instance number of this interface. + */ + this_instance = get_instance(name); + + /* + * Now look for the last interface with an instance number + * less than or equal to the new interface's instance + * number - except that non-loopback interfaces are + * arbitrarily treated as having interface numbers less + * than those of loopback interfaces, so the loopback + * interfaces are put at the end of the list. + * + * We start with "prevdev" being NULL, meaning we're before + * the first element in the list. + */ + prevdev = NULL; + for (;;) { + /* + * Get the interface after this one. + */ + if (prevdev == NULL) { + /* + * The next element is the first element. + */ + nextdev = *alldevs; + } else + nextdev = prevdev->next; + + /* + * Are we at the end of the list? + */ + if (nextdev == NULL) { + /* + * Yes - we have to put the new entry + * after "prevdev". + */ + break; + } + + /* + * Is the new interface a non-loopback interface + * and the next interface a loopback interface? + */ + if (!(curdev->flags & PCAP_IF_LOOPBACK) && + (nextdev->flags & PCAP_IF_LOOPBACK)) { + /* + * Yes, we should put the new entry + * before "nextdev", i.e. after "prevdev". + */ + break; + } + + /* + * Is the new interface's instance number less + * than the next interface's instance number, + * and is it the case that the new interface is a + * non-loopback interface or the next interface is + * a loopback interface? + * + * (The goal of both loopback tests is to make + * sure that we never put a loopback interface + * before any non-loopback interface and that we + * always put a non-loopback interface before all + * loopback interfaces.) + */ + if (this_instance < get_instance(nextdev->name) && + (!(curdev->flags & PCAP_IF_LOOPBACK) || + (nextdev->flags & PCAP_IF_LOOPBACK))) { + /* + * Yes - we should put the new entry + * before "nextdev", i.e. after "prevdev". + */ + break; + } + + prevdev = nextdev; + } + + /* + * Insert before "nextdev". + */ + curdev->next = nextdev; + + /* + * Insert after "prevdev" - unless "prevdev" is null, + * in which case this is the first interface. + */ + if (prevdev == NULL) { + /* + * This is the first interface. Pass back a + * pointer to it, and put "curdev" before + * "nextdev". + */ + *alldevs = curdev; + } else + prevdev->next = curdev; + } + + *curdev_ret = curdev; + return (0); +} + +static int +add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, + struct sockaddr *addr, struct sockaddr *netmask, + struct sockaddr *broadaddr, struct sockaddr *dstaddr, char *errbuf) +{ + pcap_if_t *curdev; + pcap_addr_t *curaddr, *prevaddr, *nextaddr; + + if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { + /* + * Error - give up. + */ + return (-1); + } + if (curdev == NULL) { + /* + * Device wasn't added because it can't be opened. + * Not a fatal error. + */ + return (0); + } + + /* + * "curdev" is an entry for this interface; add an entry for this + * address to its list of addresses. + * + * Allocate the new entry and fill it in. + */ + curaddr = malloc(sizeof(pcap_addr_t)); + if (curaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + curaddr->next = NULL; + if (addr != NULL) { + curaddr->addr = dup_sockaddr(addr); + if (curaddr->addr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->addr = NULL; + + if (netmask != NULL) { + curaddr->netmask = dup_sockaddr(netmask); + if (curaddr->netmask == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->netmask = NULL; + + if (broadaddr != NULL) { + curaddr->broadaddr = dup_sockaddr(broadaddr); + if (curaddr->broadaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->broadaddr = NULL; + + if (dstaddr != NULL) { + curaddr->dstaddr = dup_sockaddr(dstaddr); + if (curaddr->dstaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->dstaddr = NULL; + + /* + * Find the end of the list of addresses. + */ + for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { + nextaddr = prevaddr->next; + if (nextaddr == NULL) { + /* + * This is the end of the list. + */ + break; + } + } + + if (prevaddr == NULL) { + /* + * The list was empty; this is the first member. + */ + curdev->addresses = curaddr; + } else { + /* + * "prevaddr" is the last member of the list; append + * this member to it. + */ + prevaddr->next = curaddr; + } + + return (0); +} + +static int +pcap_add_if(pcap_if_t **devlist, char *name, u_int flags, + const char *description, char *errbuf) +{ + pcap_if_t *curdev; + + return (add_or_find_if(&curdev, devlist, name, flags, description, + errbuf)); +} + +/* + * Get a list of all interfaces that are up and that we can open. + * Returns -1 on error, 0 otherwise. + * The list, as returned through "alldevsp", may be null if no interfaces + * were up and could be opened. + */ +#ifdef HAVE_IFADDRS_H +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + struct ifaddrs *ifap, *ifa; + struct sockaddr *broadaddr, *dstaddr; + int ret = 0; + + /* + * Get the list of interface addresses. + * + * Note: this won't return information about interfaces + * with no addresses; are there any such interfaces + * that would be capable of receiving packets? + * (Interfaces incapable of receiving packets aren't + * very interesting from libpcap's point of view.) + * + * LAN interfaces will probably have link-layer + * addresses; I don't know whether all implementations + * of "getifaddrs()" now, or in the future, will return + * those. + */ + if (getifaddrs(&ifap) != 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "getifaddrs: %s", pcap_strerror(errno)); + return (-1); + } + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + /* + * Is this interface up? + */ + if (!(ifa->ifa_flags & IFF_UP)) { + /* + * No, so don't add it to the list. + */ + continue; + } + + /* + * "ifa_broadaddr" may be non-null even on + * non-broadcast interfaces; "ifa_dstaddr" + * was, on at least one FreeBSD 4.1 system, + * non-null on a non-point-to-point + * interface. + */ + if (ifa->ifa_flags & IFF_BROADCAST) + broadaddr = ifa->ifa_broadaddr; + else + broadaddr = NULL; + if (ifa->ifa_flags & IFF_POINTOPOINT) + dstaddr = ifa->ifa_dstaddr; + else + dstaddr = NULL; + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifa->ifa_name, + ifa->ifa_flags, ifa->ifa_addr, ifa->ifa_netmask, + broadaddr, dstaddr, errbuf) < 0) { + ret = -1; + break; + } + } + + freeifaddrs(ifap); + + if (ret != -1) { + /* + * We haven't had any errors yet; add the "any" device, + * if we can open it. + */ + if (pcap_add_if(&devlist, "any", 0, any_descr, errbuf) < 0) + ret = -1; + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} +#else /* HAVE_IFADDRS_H */ +#ifdef HAVE_PROC_NET_DEV +/* + * Get from "/proc/net/dev" all interfaces listed there; if they're + * already in the list of interfaces we have, that won't add another + * instance, but if they're not, that'll add them. + * + * We don't bother getting any addresses for them; it appears you can't + * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and, + * although some other types of addresses can be fetched with SIOCGIFADDR, + * we don't bother with them for now. + * + * We also don't fail if we couldn't open "/proc/net/dev"; we just leave + * the list of interfaces as is. + */ +static int +scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf) +{ + FILE *proc_net_f; + char linebuf[512]; + int linenum; + unsigned char *p; + char name[512]; /* XXX - pick a size */ + char *q, *saveq; + struct ifreq ifrflags; + int ret = 0; + + proc_net_f = fopen("/proc/net/dev", "r"); + if (proc_net_f == NULL) + return (0); + + for (linenum = 1; + fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) { + /* + * Skip the first two lines - they're headers. + */ + if (linenum <= 2) + continue; + + p = &linebuf[0]; + + /* + * Skip leading white space. + */ + while (*p != '\0' && isspace(*p)) + p++; + if (*p == '\0' || *p == '\n') + continue; /* blank line */ + + /* + * Get the interface name. + */ + q = &name[0]; + while (*p != '\0' && !isspace(*p)) { + if (*p == ':') { + /* + * This could be the separator between a + * name and an alias number, or it could be + * the separator between a name with no + * alias number and the next field. + * + * If there's a colon after digits, it + * separates the name and the alias number, + * otherwise it separates the name and the + * next field. + */ + saveq = q; + while (isdigit(*p)) + *q++ = *p++; + if (*p != ':') { + /* + * That was the next field, + * not the alias number. + */ + q = saveq; + } + break; + } else + *q++ = *p++; + } + *q = '\0'; + + /* + * Get the flags for this interface, and skip it if + * it's not up. + */ + strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.ifr_name), + ifrflags.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.ifr_flags & IFF_UP)) + continue; + + /* + * Add an entry for this interface, with no addresses. + */ + if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL, + errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + break; + } + } + if (ret != -1) { + /* + * Well, we didn't fail for any other reason; did we + * fail due to an error reading the file? + */ + if (ferror(proc_net_f)) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Error reading /proc/net/dev: %s", + pcap_strerror(errno)); + ret = -1; + } + } + + (void)fclose(proc_net_f); + return (ret); +} +#endif /* HAVE_PROC_NET_DEV */ + +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + register int fd; + register struct ifreq *ifrp, *ifend, *ifnext; + int n; + struct ifconf ifc; + char *buf = NULL; + unsigned buf_size; + struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; + struct sockaddr *netmask, *broadaddr, *dstaddr; + int ret = 0; + + /* + * Create a socket from which to fetch the list of interfaces. + */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + return (-1); + } + + /* + * Start with an 8K buffer, and keep growing the buffer until + * we get the entire interface list or fail to get it for some + * reason other than EINVAL (which is presumed here to mean + * "buffer is too small"). + */ + buf_size = 8192; + for (;;) { + buf = malloc(buf_size); + if (buf == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + (void)close(fd); + return (-1); + } + + ifc.ifc_len = buf_size; + ifc.ifc_buf = buf; + memset(buf, 0, buf_size); + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 + && errno != EINVAL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFCONF: %s", pcap_strerror(errno)); + (void)close(fd); + free(buf); + return (-1); + } + if (ifc.ifc_len < buf_size) + break; + free(buf); + buf_size *= 2; + } + + ifrp = (struct ifreq *)buf; + ifend = (struct ifreq *)(buf + ifc.ifc_len); + + for (; ifrp < ifend; ifrp = ifnext) { + n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); + if (n < sizeof(*ifrp)) + ifnext = ifrp + 1; + else + ifnext = (struct ifreq *)((char *)ifrp + n); + + /* + * Get the flags for this interface, and skip it if it's + * not up. + */ + strncpy(ifrflags.ifr_name, ifrp->ifr_name, + sizeof(ifrflags.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.ifr_name), + ifrflags.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.ifr_flags & IFF_UP)) + continue; + + /* + * Get the netmask for this address on this interface. + */ + strncpy(ifrnetmask.ifr_name, ifrp->ifr_name, + sizeof(ifrnetmask.ifr_name)); + memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr, + sizeof(ifrnetmask.ifr_addr)); + if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * Not available. + */ + netmask = NULL; + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFNETMASK: %.*s: %s", + (int)sizeof(ifrnetmask.ifr_name), + ifrnetmask.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + } else + netmask = &ifrnetmask.ifr_addr; + + /* + * Get the broadcast address for this address on this + * interface (if any). + */ + if (ifrflags.ifr_flags & IFF_BROADCAST) { + strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name, + sizeof(ifrbroadaddr.ifr_name)); + memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr, + sizeof(ifrbroadaddr.ifr_addr)); + if (ioctl(fd, SIOCGIFBRDADDR, + (char *)&ifrbroadaddr) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * Not available. + */ + broadaddr = NULL; + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFBRDADDR: %.*s: %s", + (int)sizeof(ifrbroadaddr.ifr_name), + ifrbroadaddr.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + } else + broadaddr = &ifrbroadaddr.ifr_broadaddr; + } else { + /* + * Not a broadcast interface, so no broadcast + * address. + */ + broadaddr = NULL; + } + + /* + * Get the destination address for this address on this + * interface (if any). + */ + if (ifrflags.ifr_flags & IFF_POINTOPOINT) { + strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name, + sizeof(ifrdstaddr.ifr_name)); + memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr, + sizeof(ifrdstaddr.ifr_addr)); + if (ioctl(fd, SIOCGIFDSTADDR, + (char *)&ifrdstaddr) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * Not available. + */ + dstaddr = NULL; + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFDSTADDR: %.*s: %s", + (int)sizeof(ifrdstaddr.ifr_name), + ifrdstaddr.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + } else + dstaddr = &ifrdstaddr.ifr_dstaddr; + } else + dstaddr = NULL; + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifrp->ifr_name, + ifrflags.ifr_flags, &ifrp->ifr_addr, + netmask, broadaddr, dstaddr, errbuf) < 0) { + ret = -1; + break; + } + } + free(buf); + +#ifdef HAVE_PROC_NET_DEV + if (ret != -1) { + /* + * We haven't had any errors yet; now read "/proc/net/dev", + * and add to the list of interfaces all interfaces listed + * there that we don't already have, because, on Linux, + * SIOCGIFCONF reports only interfaces with IPv4 addresses, + * so you need to read "/proc/net/dev" to get the names of + * the rest of the interfaces. + */ + ret = scan_proc_net_dev(&devlist, fd, errbuf); + } +#endif + (void)close(fd); + + if (ret != -1) { + /* + * We haven't had any errors yet; add the "any" device, + * if we can open it. + */ + if (pcap_add_if(&devlist, "any", 0, any_descr, errbuf) < 0) { + /* + * Oops, we had a fatal error. + */ + ret = -1; + } + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} +#endif /* HAVE_IFADDRS_H */ + +/* + * Free a list of interfaces. + */ +void +pcap_freealldevs(pcap_if_t *alldevs) +{ + pcap_if_t *curdev, *nextdev; + pcap_addr_t *curaddr, *nextaddr; + + for (curdev = alldevs; curdev != NULL; curdev = nextdev) { + nextdev = curdev->next; + + /* + * Free all addresses. + */ + for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { + nextaddr = curaddr->next; + if (curaddr->addr) + free(curaddr->addr); + if (curaddr->netmask) + free(curaddr->netmask); + if (curaddr->broadaddr) + free(curaddr->broadaddr); + if (curaddr->dstaddr) + free(curaddr->dstaddr); + free(curaddr); + } + + /* + * Free the name string. + */ + free(curdev->name); + + /* + * Free the description string, if any. + */ + if (curdev->description != NULL) + free(curdev->description); + + /* + * Free the interface. + */ + free(curdev); + } +} + /* * Return the name of a network interface attached to the system, or NULL * if none can be found. The interface must be configured up; the @@ -91,171 +955,42 @@ char * pcap_lookupdev(errbuf) register char *errbuf; { -#ifdef HAVE_IFADDRS_H - struct ifaddrs *ifap, *ifa, *mp; - int n, minunit; - char *cp; + pcap_if_t *alldevs; +/* for old BSD systems, including bsdi3 */ +#ifndef IF_NAMESIZE +#define IF_NAMESIZE IFNAMSIZ +#endif static char device[IF_NAMESIZE + 1]; + char *ret; - if (getifaddrs(&ifap) != 0) { - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "getifaddrs: %s", pcap_strerror(errno)); - return NULL; - } - - mp = NULL; - minunit = 666; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - const char *endcp; - - if ((ifa->ifa_flags & IFF_UP) == 0 || ISLOOPBACK_IFA(ifa)) - continue; - - endcp = ifa->ifa_name + strlen(ifa->ifa_name); - for (cp = ifa->ifa_name; cp < endcp && !isdigit(*cp); ++cp) - continue; - - if (isdigit (*cp)) { - n = atoi(cp); - } else { - n = 0; - } - if (n < minunit) { - minunit = n; - mp = ifa; - } - } - if (mp == NULL) { - (void)strlcpy(errbuf, "no suitable device found", - PCAP_ERRBUF_SIZE); -#ifdef HAVE_FREEIFADDRS - freeifaddrs(ifap); -#else - free(ifap); -#endif + if (pcap_findalldevs(&alldevs, errbuf) == -1) return (NULL); - } - - (void)strlcpy(device, mp->ifa_name, sizeof(device)); -#ifdef HAVE_FREEIFADDRS - freeifaddrs(ifap); -#else - free(ifap); -#endif - return (device); -#else - register int fd, minunit, n; - register char *cp; - register struct ifreq *ifrp, *ifend, *ifnext, *mp; - struct ifconf ifc; - char *buf; - struct ifreq ifr; - static char device[sizeof(ifrp->ifr_name) + 1]; - unsigned buf_size; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "socket: %s", pcap_strerror(errno)); - return (NULL); - } - - buf_size = 8192; - - for (;;) { - buf = malloc (buf_size); - if (buf == NULL) { - close (fd); - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "out of memory"); - return (NULL); - } - - ifc.ifc_len = buf_size; - ifc.ifc_buf = buf; - memset (buf, 0, buf_size); - if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 - && errno != EINVAL) { - free (buf); - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "SIOCGIFCONF: %s", pcap_strerror(errno)); - (void)close(fd); - return (NULL); - } - if (ifc.ifc_len < buf_size) - break; - free (buf); - buf_size *= 2; - } - - ifrp = (struct ifreq *)buf; - ifend = (struct ifreq *)(buf + ifc.ifc_len); - - mp = NULL; - minunit = 666; - for (; ifrp < ifend; ifrp = ifnext) { - const char *endcp; - -#ifdef HAVE_SOCKADDR_SA_LEN - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ifnext = ifrp + 1; - else - ifnext = (struct ifreq *)((char *)ifrp + n); - if (ifrp->ifr_addr.sa_family != AF_INET) - continue; -#else - ifnext = ifrp + 1; -#endif + + if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { /* - * Need a template to preserve address info that is - * used below to locate the next entry. (Otherwise, - * SIOCGIFFLAGS stomps over it because the requests - * are returned in a union.) + * There are no devices on the list, or the first device + * on the list is a loopback device, which means there + * are no non-loopback devices on the list. This means + * we can't return any device. + * + * XXX - why not return a loopback device? If we can't + * capture on it, it won't be on the list, and if it's + * on the list, there aren't any non-loopback devices, + * so why not just supply it as the default device? */ - strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); - if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { - if (errno == ENXIO) - continue; - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "SIOCGIFFLAGS: %.*s: %s", - (int)sizeof(ifr.ifr_name), ifr.ifr_name, - pcap_strerror(errno)); - (void)close(fd); - free (buf); - return (NULL); - } - - /* Must be up and not the loopback */ - if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) - continue; - - endcp = ifrp->ifr_name + strlen(ifrp->ifr_name); - for (cp = ifrp->ifr_name; cp < endcp && !isdigit(*cp); ++cp) - continue; - - if (isdigit (*cp)) { - n = atoi(cp); - } else { - n = 0; - } - if (n < minunit) { - minunit = n; - mp = ifrp; - } - } - (void)close(fd); - if (mp == NULL) { (void)strlcpy(errbuf, "no suitable device found", PCAP_ERRBUF_SIZE); - free(buf); - return (NULL); + ret = NULL; + } else { + /* + * Return the name of the first device on the list. + */ + (void)strlcpy(device, alldevs->name, sizeof(device)); + ret = device; } - (void)strlcpy(device, mp->ifr_name, sizeof(device)); - free(buf); - return (device); -#endif + pcap_freealldevs(alldevs); + return (ret); } int diff --git a/contrib/libpcap/llc.h b/contrib/libpcap/llc.h index 28003153cd54..ffd3a60143d4 100644 --- a/contrib/libpcap/llc.h +++ b/contrib/libpcap/llc.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/llc.h,v 1.1 2001/01/14 21:26:53 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/llc.h,v 1.2 2001/01/28 09:44:50 guy Exp $ (LBL) */ /* @@ -58,9 +58,12 @@ #ifndef LLCSAP_SNAP #define LLCSAP_SNAP 0xaa #endif -#ifndef LLCSAP_ISONS -#define LLCSAP_ISONS 0xfe -#endif #ifndef LLCSAP_IPX #define LLCSAP_IPX 0xe0 #endif +#ifndef LLCSAP_NETBEUI +#define LLCSAP_NETBEUI 0xf0 +#endif +#ifndef LLCSAP_ISONS +#define LLCSAP_ISONS 0xfe +#endif diff --git a/contrib/libpcap/optimize.c b/contrib/libpcap/optimize.c index bb3b6c957d03..a3ef13e3d082 100644 --- a/contrib/libpcap/optimize.c +++ b/contrib/libpcap/optimize.c @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.67 2000/11/19 13:37:20 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.69 2001/11/12 21:57:06 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -940,7 +940,10 @@ opt_stmt(s, val, alter) op = BPF_OP(s->code); if (alter) { if (s->k == 0) { - if (op == BPF_ADD || op == BPF_SUB || + /* don't optimize away "sub #0" + * as it may be needed later to + * fixup the generated math code */ + if (op == BPF_ADD || op == BPF_LSH || op == BPF_RSH || op == BPF_OR) { s->code = NOP; @@ -1578,8 +1581,10 @@ opt_loop(root, do_stmts) { #ifdef BDEBUG - if (dflag > 1) + if (dflag > 1) { + printf("opt_loop(root, %d) begin\n", do_stmts); opt_dump(root); + } #endif do { done = 1; @@ -1590,8 +1595,10 @@ opt_loop(root, do_stmts) find_edom(root); opt_blks(root, do_stmts); #ifdef BDEBUG - if (dflag > 1) + if (dflag > 1) { + printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done); opt_dump(root); + } #endif } while (!done); } @@ -1611,7 +1618,19 @@ bpf_optimize(rootp) opt_loop(root, 0); opt_loop(root, 1); intern_blocks(root); +#ifdef BDEBUG + if (dflag > 1) { + printf("after intern_blocks()\n"); + opt_dump(root); + } +#endif opt_root(rootp); +#ifdef BDEBUG + if (dflag > 1) { + printf("after opt_root()\n"); + opt_dump(root); + } +#endif opt_cleanup(); } @@ -2075,7 +2094,7 @@ icode_to_fcode(root, lenp) struct bpf_insn *fp; /* - * Loop doing convert_codr_r() until no branches remain + * Loop doing convert_code_r() until no branches remain * with too-large offsets. */ while (1) { diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c index fc563657d8b5..0d97d41e61c1 100644 --- a/contrib/libpcap/pcap-bpf.c +++ b/contrib/libpcap/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.44 2000/10/28 00:01:28 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.48 2001/12/10 07:14:14 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -35,6 +35,16 @@ static const char rcsid[] = #include #include +#ifdef _AIX +/* + * XXX - I'm guessing here AIX defines IFT_ values in , + * as BSD does. 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.... + */ +#include /* for IFT_ values */ +#endif #include #include @@ -57,6 +67,19 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps) { struct bpf_stat s; + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. This includes packets later dropped + * because we ran out of buffer space. + * + * "ps_drop" counts packets dropped inside the BPF device + * because we ran out of buffer space. It doesn't count + * packets dropped by the interface driver. It counts + * only packets that passed the filter. + * + * Both statistics include packets not yet read from the kernel + * by libpcap, and thus not yet seen by the application. + */ if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s", pcap_strerror(errno)); @@ -123,6 +146,20 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* * XXX A bpf_hdr matches a pcap_pkthdr. */ +#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; +#endif (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { @@ -235,17 +272,32 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) pcap_strerror(errno)); goto bad; } -#ifdef __OpenBSD__ +#ifdef _AIX + /* + * AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT. + */ switch (v) { - case DLT_LOOP: - /* - * XXX - DLT_LOOP has a network-byte-order, rather than - * a host-byte-order, AF_ value as the link-layer - * header; will the BPF code generator handle that - * correctly on little-endian machines? - */ - v = DLT_NULL; + + case IFT_ETHER: + case IFT_ISO88023: + v = DLT_EN10MB; break; + + case IFT_FDDI: + v = DLT_FDDI; + break; + + case IFT_ISO88025: + v = DLT_IEEE802; + break; + + default: + /* + * We don't know what to map this to yet. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown interface type %lu", + v); + goto bad; } #endif #if _BSDI_VERSION - 0 >= 199510 @@ -340,9 +392,13 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) #endif /* BIOCIMMEDIATE */ #endif /* _AIX */ - if (promisc) + if (promisc) { /* set promiscuous mode, okay if it fails */ - (void)ioctl(p->fd, BIOCPROMISC, NULL); + if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", + pcap_strerror(errno)); + } + } if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c index 1a152bc76eb9..16a36c5c6073 100644 --- a/contrib/libpcap/pcap-dlpi.c +++ b/contrib/libpcap/pcap-dlpi.c @@ -38,7 +38,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.63 2000/11/22 05:32:55 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.74 2001/12/10 07:14:15 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -89,12 +89,17 @@ static const char rcsid[] = #endif #ifndef PCAP_DEV_PREFIX +#ifdef _AIX +#define PCAP_DEV_PREFIX "/dev/dlpi" +#else #define PCAP_DEV_PREFIX "/dev" #endif +#endif #define MAXDLBUF 8192 /* Forwards */ +static char *split_dname(char *, int *, char *); static int dlattachreq(int, bpf_u_int32, char *); static int dlbindack(int, char *, char *); static int dlbindreq(int, bpf_u_int32, char *); @@ -102,6 +107,8 @@ static int dlinfoack(int, char *, char *); static int dlinforeq(int, char *); static int dlokack(int, const char *, char *, char *); static int recv_ack(int, int, const char *, char *, char *); +static 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 *); @@ -121,6 +128,23 @@ int pcap_stats(pcap_t *p, struct pcap_stat *ps) { + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this does not include packets dropped because we ran out + * of buffer space. + * + * "ps_drop" counts packets dropped inside the 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. + * + * 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; return (0); } @@ -226,9 +250,8 @@ pcap_t * pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) { register char *cp; - char *eos; register pcap_t *p; - register int ppa; + int ppa; register dl_info_ack_t *infop; #ifdef HAVE_SYS_BUFMOD_H bpf_u_int32 ss, flag; @@ -249,6 +272,7 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) return (NULL); } memset(p, 0, sizeof(*p)); + p->fd = -1; /* indicate that it hasn't been opened yet */ #ifdef HAVE_DEV_DLPI /* @@ -262,20 +286,12 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) strlcpy(dname, cp, sizeof(dname)); /* - * Split the name into a device type and a unit number. + * Split the device name into a device type name and a unit number; + * chop off the unit number, so "dname" is just a device type name. */ - cp = strpbrk(dname, "0123456789"); - if (cp == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "%s missing unit number", device); + cp = split_dname(dname, &ppa, ebuf); + if (cp == NULL) goto bad; - } - ppa = strtol(cp, &eos, 10); - if (*eos != '\0') { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "%s bad unit number", device); - goto bad; - } *cp = '\0'; /* @@ -305,30 +321,33 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) goto bad; #else /* - ** Determine device and ppa - */ - cp = strpbrk(device, "0123456789"); - if (cp == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", - device); + * Get the unit number, and a pointer to the end of the device + * type name. + */ + cp = split_dname(device, &ppa, ebuf); + if (cp == NULL) goto bad; - } - ppa = strtol(cp, &eos, 10); - if (*eos != '\0') { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); - goto bad; - } + /* + * If the device name begins with "/", assume it begins with + * the pathname of the directory containing the device to open; + * otherwise, concatenate the device directory name and the + * device name. + */ if (*device == '/') strlcpy(dname, device, sizeof(dname)); else snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, device); + /* + * Make a copy of the device pathname, and then remove the unit + * number from the device pathname. + */ + strlcpy(dname2, dname, sizeof(dname)); + *(dname + strlen(dname) - strlen(cp)) = '\0'; + /* Try device without unit number */ - strlcpy(dname2, dname, sizeof(dname2)); - cp = strchr(dname, *cp); - *cp = '\0'; if ((p->fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, @@ -366,10 +385,24 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) */ #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) #ifdef _AIX - /* According to IBM's AIX Support Line, the dl_sap value - ** should not be less than 0x600 (1536) for standard ethernet - */ - if (dlbindreq(p->fd, 1537, ebuf) < 0 || + /* According to IBM's AIX Support Line, the dl_sap value + ** should not be less than 0x600 (1536) for standard Ethernet. + ** However, we seem to get DL_BADADDR - "DLSAP addr in improper + ** format or invalid" - errors if we use 1537 on the "tr0" + ** device, which, given that its name starts with "tr" and that + ** it's IBM, probably means a Token Ring device. (Perhaps we + ** need to use 1537 on "/dev/dlpi/en" because that device is for + ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and + ** it rejects invalid Ethernet types.) + ** + ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea + ** says that works on Token Ring (he says that 0 does *not* + ** work; perhaps that's considered an invalid LLC SAP value - I + ** assume the SAP value in a DLPI bind is an LLC SAP for network + ** types that use 802.2 LLC). + */ + if ((dlbindreq(p->fd, 1537, ebuf) < 0 && + dlbindreq(p->fd, 2, ebuf) < 0) || #else if (dlbindreq(p->fd, 0, ebuf) < 0 || #endif @@ -448,6 +481,11 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) p->offset = 3; break; + case DL_TPR: + p->linktype = DLT_IEEE802; + p->offset = 2; + break; + default: snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", infop->dl_mac_type); @@ -547,10 +585,50 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) return (p); bad: + if (p->fd >= 0) + close(p->fd); free(p); return (NULL); } +/* + * Split a device name into a device type name and a unit number; + * return the a pointer to the beginning of the unit number, which + * is the end of the device type name, and set "*unitp" to the unit + * number. + * + * Returns NULL on error, and fills "ebuf" with an error message. + */ +static char * +split_dname(char *device, int *unitp, char *ebuf) +{ + char *cp; + char *eos; + int unit; + + /* + * Look for a number at the end of the device name string. + */ + cp = device + strlen(device) - 1; + if (*cp < '0' || *cp > '9') { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", + device); + return (NULL); + } + + /* Digits at end of string are unit number */ + while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') + cp--; + + unit = strtol(cp, &eos, 10); + if (*eos != '\0') { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); + return (NULL); + } + *unitp = unit; + return (cp); +} + int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { @@ -607,54 +685,245 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) #ifdef DL_HP_PPA_ACK case DL_HP_PPA_ACK: #endif - /* These are OK */ break; case DL_ERROR_ACK: switch (dlp->error_ack.dl_errno) { - case DL_BADPPA: - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s bad ppa (device unit)", what); - break; - - case DL_SYSERR: - snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "recv_ack: %s: UNIX error - %s", what, pcap_strerror(dlp->error_ack.dl_unix_errno)); break; - case DL_UNSUPPORTED: - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s: Service not supplied by provider", - what); - break; - default: - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s error 0x%x", - what, (bpf_u_int32)dlp->error_ack.dl_errno); + snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", + what, dlstrerror(dlp->error_ack.dl_errno)); break; } return (-1); default: snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s unexpected primitive ack 0x%x ", - what, (bpf_u_int32)dlp->dl_primitive); + "recv_ack: %s: Unexpected primitive ack %s", + what, dlprim(dlp->dl_primitive)); return (-1); } if (ctl.len < size) { snprintf(ebuf, PCAP_ERRBUF_SIZE, - "recv_ack: %s ack too small (%d < %d)", + "recv_ack: %s: Ack too small (%d < %d)", what, ctl.len, size); return (-1); } return (ctl.len); } +static char * +dlstrerror(bpf_u_int32 dl_errno) +{ + static char errstring[6+2+8+1]; + + switch (dl_errno) { + + case DL_ACCESS: + return ("Improper permissions for request"); + + case DL_BADADDR: + return ("DLSAP addr in improper format or invalid"); + + case DL_BADCORR: + return ("Seq number not from outstand DL_CONN_IND"); + + case DL_BADDATA: + return ("User data exceeded provider limit"); + + case DL_BADPPA: +#ifdef HAVE_DEV_DLPI + /* + * With a single "/dev/dlpi" device used for all + * DLPI providers, PPAs have nothing to do with + * unit numbers. + */ + return ("Specified PPA was invalid"); +#else + /* + * We have separate devices for separate devices; + * the PPA is just the unit number. + */ + return ("Specified PPA (device unit) was invalid"); +#endif + + case DL_BADPRIM: + return ("Primitive received not known by provider"); + + case DL_BADQOSPARAM: + return ("QOS parameters contained invalid values"); + + case DL_BADQOSTYPE: + return ("QOS structure type is unknown/unsupported"); + + case DL_BADSAP: + return ("Bad LSAP selector"); + + case DL_BADTOKEN: + return ("Token used not an active stream"); + + case DL_BOUND: + return ("Attempted second bind with dl_max_conind"); + + case DL_INITFAILED: + return ("Physical link initialization failed"); + + case DL_NOADDR: + return ("Provider couldn't allocate alternate address"); + + case DL_NOTINIT: + return ("Physical link not initialized"); + + case DL_OUTSTATE: + return ("Primitive issued in improper state"); + + case DL_SYSERR: + return ("UNIX system error occurred"); + + case DL_UNSUPPORTED: + return ("Requested service not supplied by provider"); + + case DL_UNDELIVERABLE: + return ("Previous data unit could not be delivered"); + + case DL_NOTSUPPORTED: + return ("Primitive is known but not supported"); + + case DL_TOOMANY: + return ("Limit exceeded"); + + case DL_NOTENAB: + return ("Promiscuous mode not enabled"); + + case DL_BUSY: + return ("Other streams for PPA in post-attached"); + + case DL_NOAUTO: + return ("Automatic handling XID&TEST not supported"); + + case DL_NOXIDAUTO: + return ("Automatic handling of XID not supported"); + + case DL_NOTESTAUTO: + return ("Automatic handling of TEST not supported"); + + case DL_XIDAUTO: + return ("Automatic handling of XID response"); + + case DL_TESTAUTO: + return ("Automatic handling of TEST response"); + + case DL_PENDING: + return ("Pending outstanding connect indications"); + + default: + sprintf(errstring, "Error %02x", dl_errno); + return (errstring); + } +} + +static char * +dlprim(bpf_u_int32 prim) +{ + static char primbuf[80]; + + switch (prim) { + + case DL_INFO_REQ: + return ("DL_INFO_REQ"); + + case DL_INFO_ACK: + return ("DL_INFO_ACK"); + + case DL_ATTACH_REQ: + return ("DL_ATTACH_REQ"); + + case DL_DETACH_REQ: + return ("DL_DETACH_REQ"); + + case DL_BIND_REQ: + return ("DL_BIND_REQ"); + + case DL_BIND_ACK: + return ("DL_BIND_ACK"); + + case DL_UNBIND_REQ: + return ("DL_UNBIND_REQ"); + + case DL_OK_ACK: + return ("DL_OK_ACK"); + + case DL_ERROR_ACK: + return ("DL_ERROR_ACK"); + + case DL_SUBS_BIND_REQ: + return ("DL_SUBS_BIND_REQ"); + + case DL_SUBS_BIND_ACK: + return ("DL_SUBS_BIND_ACK"); + + case DL_UNITDATA_REQ: + return ("DL_UNITDATA_REQ"); + + case DL_UNITDATA_IND: + return ("DL_UNITDATA_IND"); + + case DL_UDERROR_IND: + return ("DL_UDERROR_IND"); + + case DL_UDQOS_REQ: + return ("DL_UDQOS_REQ"); + + case DL_CONNECT_REQ: + return ("DL_CONNECT_REQ"); + + case DL_CONNECT_IND: + return ("DL_CONNECT_IND"); + + case DL_CONNECT_RES: + return ("DL_CONNECT_RES"); + + case DL_CONNECT_CON: + return ("DL_CONNECT_CON"); + + case DL_TOKEN_REQ: + return ("DL_TOKEN_REQ"); + + case DL_TOKEN_ACK: + return ("DL_TOKEN_ACK"); + + case DL_DISCONNECT_REQ: + return ("DL_DISCONNECT_REQ"); + + case DL_DISCONNECT_IND: + return ("DL_DISCONNECT_IND"); + + case DL_RESET_REQ: + return ("DL_RESET_REQ"); + + case DL_RESET_IND: + return ("DL_RESET_IND"); + + case DL_RESET_RES: + return ("DL_RESET_RES"); + + case DL_RESET_CON: + return ("DL_RESET_CON"); + + default: + (void) sprintf(primbuf, "unknown primitive 0x%x", prim); + return (primbuf); + } +} + static int dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) { @@ -765,7 +1034,7 @@ get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) return ("?"); cp = buf; - if (!isdigit(*cp)) + if (!isdigit((unsigned char)*cp)) return (buf); *majorp = strtol(cp, &cp, 10); if (*cp++ != '.') @@ -829,18 +1098,85 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, register u_long majdev; struct stat statbuf; dl_hp_ppa_req_t req; - bpf_u_int32 buf[MAXDLBUF]; + char buf[MAXDLBUF]; + char *ppa_data_buf; + dl_hp_ppa_ack_t *dlp; + struct strbuf ctl; + int flags; + int ppa; memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_HP_PPA_REQ; memset((char *)buf, 0, sizeof(buf)); - if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0 || - recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0) + if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) return (-1); + ctl.maxlen = DL_HP_PPA_ACK_SIZE; + ctl.len = 0; + ctl.buf = (char *)buf; + + flags = 0; + /* + * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal + * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) + * which is NOT big enough for a DL_HP_PPA_REQ. + * + * This causes libpcap applications to fail on a system with HP-APA + * installed. + * + * To figure out how big the returned data is, we first call getmsg + * to get the small head and peek at the head to get the actual data + * length, and then issue another getmsg to get the actual PPA data. + */ + /* get the head first */ + if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + return (-1); + } + + dlp = (dl_hp_ppa_ack_t *)ctl.buf; + if (dlp->dl_primitive != DL_HP_PPA_ACK) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", + (bpf_u_int32)dlp->dl_primitive); + return (-1); + } + + if (ctl.len < DL_HP_PPA_ACK_SIZE) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa ack too small (%d < %d)", + ctl.len, DL_HP_PPA_ACK_SIZE); + return (-1); + } + + /* allocate buffer */ + if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); + return (-1); + } + ctl.maxlen = dlp->dl_length; + ctl.len = 0; + ctl.buf = (char *)ppa_data_buf; + /* get the data */ + if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + free(ppa_data_buf); + return (-1); + } + if (ctl.len < dlp->dl_length) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa ack too small (%d < %d)", + ctl.len, dlp->dl_length); + free(ppa_data_buf); + return (-1); + } + ap = (dl_hp_ppa_ack_t *)buf; - ipstart = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset); + ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart; #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 @@ -858,8 +1194,8 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, * instance number. */ for (i = 0; i < ap->dl_count; i++) { - if ((strcmp(ip->dl_module_id_1, device) == 0 || - strcmp(ip->dl_module_id_2, device) == 0) && + if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || + strcmp((const char *)ip->dl_module_id_2, device) == 0) && ip->dl_instance_num == unit) break; @@ -915,9 +1251,12 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit, if (ip->dl_hdw_state == HDW_DEAD) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s%d: hardware state: DOWN\n", device, unit); + free(ppa_data_buf); return (-1); } - return ((int)ip->dl_ppa); + ppa = ip->dl_ppa; + free(ppa_data_buf); + return (ppa); } #endif diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c index 1199f8f6caad..179cbc01dc77 100644 --- a/contrib/libpcap/pcap-linux.c +++ b/contrib/libpcap/pcap-linux.c @@ -26,7 +26,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.51.2.3 2001/01/18 03:59:56 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.73 2001/12/10 07:14:16 guy Exp $ (LBL)"; #endif /* @@ -51,6 +51,24 @@ static const char rcsid[] = * do, if another socket also requested promiscuous mode between * the time when we opened the socket and the time when we close * the socket. + * + * - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()" + * return the amount of data that you could have read, rather than + * the amount that was returned, so we can't just allocate a buffer + * whose size is the snapshot length and pass the snapshot length + * as the byte count, and also pass MSG_TRUNC, so that the return + * value tells us how long the packet was on the wire. + * + * This means that, if we want to get the actual size of the packet, + * so we can return it in the "len" field of the packet header, + * we have to read the entire packet, not just the part that fits + * within the snapshot length, and thus waste CPU time copying data + * from the kernel that our caller won't see. + * + * We have to get the actual size, and supply it in "len", because + * otherwise, the IP dissector in tcpdump, for example, will complain + * about "truncated-ip", as the packet will appear to have been + * shorter, on the wire, than the IP header said it should have been. */ @@ -74,37 +92,38 @@ static const char rcsid[] = #include #include -#ifdef HAVE_NETPACKET_PACKET_H -# include +/* + * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET + * sockets rather than SOCK_PACKET sockets. + * + * To use them, we include rather than + * ; we do so because + * + * some Linux distributions (e.g., Slackware 4.0) have 2.2 or + * later kernels and libc5, and don't provide a + * file; + * + * not all versions of glibc2 have a file + * that defines stuff needed for some of the 2.4-or-later-kernel + * features, so if the system has a 2.4 or later kernel, we + * still can't use those features. + * + * We're already including a number of other headers, and + * this code is Linux-specific (no other OS has PF_PACKET sockets as + * a raw packet capture mechanism), so it's not as if you gain any + * useful portability by using + * + * XXX - should we just include even if PF_PACKET + * isn't defined? It only defines one data structure in 2.0.x, so + * it shouldn't cause any problems. + */ +#ifdef PF_PACKET +# include /* - * We assume this means we really do have PF_PACKET sockets. - */ -# define HAVE_PF_PACKET_SOCKETS -#else - /* - * Oh, joy. Some Linux distributions have 2.2 or later kernels and - * libc5. On at least one of those systems (Slackware 4.0), it - * appears that "/usr/include/sys/socket.h" includes , - * which means it picks up all the AF_, PF_, and SO_ definitions - * appropriate for the current kernel; however, it also appears that - * they did not see fit to provide a "/usr/include/netpacket/packet.h" - * file. - * - * However, you should be able to get the right definitions by including - * . - * - * So if this system has PF_PACKET defined but doesn't have the - * header file, we include - * instead. - */ -# ifdef PF_PACKET -# include - - /* - * However, on at least some Linux distributions (for example, Red Hat - * 5.2), there's no file, but PF_PACKET is defined - * if you include , but doesn't define + * On at least some Linux distributions (for example, Red Hat 5.2), + * there's no file, but PF_PACKET is defined if + * you include , but doesn't define * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of * the PACKET_xxx stuff. * @@ -114,8 +133,7 @@ static const char rcsid[] = # ifdef PACKET_HOST # define HAVE_PF_PACKET_SOCKETS # endif /* PACKET_HOST */ -# endif /* PF_PACKET */ -#endif /* HAVE_NETPACKET_PACKET_H */ +#endif /* PF_PACKET */ #ifdef SO_ATTACH_FILTER #include @@ -127,7 +145,15 @@ typedef int socklen_t; #endif #ifndef MSG_TRUNC -#define MSG_TRUNC 0 +/* + * This is being compiled on a system that lacks MSG_TRUNC; define it + * with the value it has in the 2.2 and later kernels, so that, on + * those kernels, when we pass it in the flags argument to "recvfrom()" + * we're passing the right value and thus get the MSG_TRUNC behavior + * we want. (We don't get that behavior on 2.0[.x] kernels, because + * they didn't support MSG_TRUNC.) + */ +#define MSG_TRUNC 0x20 #endif #define MAX_LINKHEADER_SIZE 256 @@ -142,7 +168,7 @@ typedef int socklen_t; /* * Prototypes for internal functions */ -static int map_arphrd_to_dlt(int arptype ); +static void map_arphrd_to_dlt(pcap_t *, int); static int live_open_old(pcap_t *, char *, int, int, char *); static int live_open_new(pcap_t *, char *, int, int, char *); static int pcap_read_packet(pcap_t *, pcap_handler, u_char *); @@ -163,6 +189,13 @@ static int iface_bind_old(int fd, const char *device, char *ebuf); #ifdef SO_ATTACH_FILTER static int fix_program(pcap_t *handle, struct sock_fprog *fcode); static int fix_offset(struct bpf_insn *p); +static int set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode); +static int reset_kernel_filter(pcap_t *handle); + +static struct sock_filter total_insn + = BPF_STMT(BPF_RET | BPF_K, 0); +static struct sock_fprog total_fcode + = { 1, &total_insn }; #endif /* @@ -178,9 +211,13 @@ static int fix_offset(struct bpf_insn *p); pcap_t * pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) { + pcap_t *handle; + int mtu; + struct utsname utsname; + /* Allocate a handle for this session. */ - pcap_t *handle = malloc(sizeof(*handle)); + handle = malloc(sizeof(*handle)); if (handle == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); @@ -200,6 +237,13 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) if (!device || strcmp(device, "any") == 0) { device = NULL; handle->md.device = strdup("any"); + if (promisc) { + promisc = 0; + /* Just a warning. */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "Promiscuous mode not supported on the \"any\" device"); + } + } else handle->md.device = strdup(device); @@ -234,6 +278,93 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) return NULL; } + /* + * Compute the buffer size. + * + * If we're using SOCK_PACKET, this might be a 2.0[.x] kernel, + * and might require special handling - check. + */ + if (handle->md.sock_packet && (uname(&utsname) < 0 || + strncmp(utsname.release, "2.0", 3) == 0)) { + /* + * We're using a SOCK_PACKET structure, and either + * we couldn't find out what kernel release this is, + * or it's a 2.0[.x] kernel. + * + * In the 2.0[.x] kernel, a "recvfrom()" on + * a SOCK_PACKET socket, with MSG_TRUNC set, will + * return the number of bytes read, so if we pass + * a length based on the snapshot length, it'll + * return the number of bytes from the packet + * copied to userland, not the actual length + * of the packet. + * + * This means that, for example, the IP dissector + * in tcpdump will get handed a packet length less + * than the length in the IP header, and will + * complain about "truncated-ip". + * + * So we don't bother trying to copy from the + * kernel only the bytes in which we're interested, + * but instead copy them all, just as the older + * versions of libpcap for Linux did. + * + * The buffer therefore needs to be big enough to + * hold the largest packet we can get from this + * device. Unfortunately, we can't get the MRU + * of the network; we can only get the MTU. The + * MTU may be too small, in which case a packet larger + * than the buffer size will be truncated *and* we + * won't get the actual packet size. + * + * However, if the snapshot length is larger than + * the buffer size based on the MTU, we use the + * snapshot length as the buffer size, instead; + * this means that with a sufficiently large snapshot + * length we won't artificially truncate packets + * to the MTU-based size. + * + * This mess just one of many problems with packet + * capture on 2.0[.x] kernels; you really want a + * 2.2[.x] or later kernel if you want packet capture + * to work well. + */ + mtu = iface_get_mtu(handle->fd, device, ebuf); + if (mtu == -1) { + close(handle->fd); + free(handle->md.device); + free(handle); + return NULL; + } + handle->bufsize = MAX_LINKHEADER_SIZE + mtu; + if (handle->bufsize < handle->snapshot) + handle->bufsize = handle->snapshot; + } else { + /* + * This is a 2.2[.x] or later kernel (we know that + * either because we're not using a SOCK_PACKET + * socket - PF_PACKET is supported only in 2.2 + * and later kernels - or because we checked the + * kernel version). + * + * We can safely pass "recvfrom()" a byte count + * based on the snapshot length. + */ + handle->bufsize = handle->snapshot; + } + + /* Allocate the buffer */ + + handle->buffer = malloc(handle->bufsize + handle->offset); + if (!handle->buffer) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + close(handle->fd); + free(handle->md.device); + free(handle); + return NULL; + } + return handle; } @@ -260,6 +391,7 @@ pcap_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) static int pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) { + u_char *bp; int offset; #ifdef HAVE_PF_PACKET_SOCKETS struct sockaddr_ll from; @@ -290,11 +422,12 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) /* Receive a single packet from the kernel */ + bp = handle->buffer + handle->offset; do { fromlen = sizeof(from); packet_len = recvfrom( - handle->fd, handle->buffer + offset + handle->offset, - handle->md.readlen - offset, MSG_TRUNC, + handle->fd, bp + offset, + handle->bufsize - offset, MSG_TRUNC, (struct sockaddr *) &from, &fromlen); } while (packet_len == -1 && errno == EINTR); @@ -337,7 +470,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) */ packet_len += SLL_HDR_LEN; - hdrp = (struct sll_header *)handle->buffer; + hdrp = (struct sll_header *)bp; /* * Map the PACKET_ value to a LINUX_SLL_ value; we @@ -422,7 +555,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) /* Run the packet filter if not using kernel filter */ if (!handle->md.use_bpf && handle->fcode.bf_insns) { - if (bpf_filter(handle->fcode.bf_insns, handle->buffer, + if (bpf_filter(handle->fcode.bf_insns, bp, packet_len, caplen) == 0) { /* rejected by filter */ @@ -440,20 +573,139 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) pcap_header.caplen = caplen; pcap_header.len = packet_len; - /* Call the user supplied callback function */ + /* + * Count the packet. + * + * Arguably, we should count them before we check the filter, + * as on many other platforms "ps_recv" counts packets + * handed to the filter rather than packets that passed + * the filter, but if filtering is done in the kernel, we + * can't get a count of packets that passed the filter, + * and that would mean the meaning of "ps_recv" wouldn't + * be the same on all Linux systems. + * + * XXX - it's not the same on all systems in any case; + * ideally, we should have a "get the statistics" call + * that supplies more counts and indicates which of them + * it supplies, so that we supply a count of packets + * handed to the filter only on platforms where that + * information is available. + * + * We count them here even if we can get the packet count + * from the kernel, as we can only determine at run time + * whether we'll be able to get it from the kernel (if + * HAVE_TPACKET_STATS isn't defined, we can't get it from + * the kernel, but if it is defined, the library might + * have been built with a 2.4 or later kernel, but we + * might be running on a 2.2[.x] kernel without Alexey + * Kuznetzov's turbopacket patches, and thus the kernel + * might not be able to supply those statistics). We + * could, I guess, try, when opening the socket, to get + * the statistics, and if we can not increment the count + * here, but it's not clear that always incrementing + * the count is more expensive than always testing a flag + * in memory. + */ handle->md.stat.ps_recv++; - callback(userdata, &pcap_header, handle->buffer + handle->offset); + + /* Call the user supplied callback function */ + callback(userdata, &pcap_header, bp); return 1; } /* * Get the statistics for the given packet capture handle. - * FIXME: Currently does not report the number of dropped packets. + * Reports the number of dropped packets iff the kernel supports + * the PACKET_STATISTICS "getsockopt()" argument (2.4 and later + * kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket + * patches); otherwise, that information isn't available, and we lie + * and report 0 as the count of dropped packets. */ int pcap_stats(pcap_t *handle, struct pcap_stat *stats) { +#ifdef HAVE_TPACKET_STATS + struct tpacket_stats kstats; + socklen_t len = sizeof (struct tpacket_stats); + + /* + * Try to get the packet counts from the kernel. + */ + if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, + &kstats, &len) > -1) { + /* + * In "linux/net/packet/af_packet.c", at least in the + * 2.4.9 kernel, "tp_packets" is incremented for every + * packet that passes the packet filter *and* is + * successfully queued on the socket; "tp_drops" is + * incremented for every packet dropped because there's + * not enough free space in the socket buffer. + * + * When the statistics are returned for a PACKET_STATISTICS + * "getsockopt()" call, "tp_drops" is added to "tp_packets", + * so that "tp_packets" counts all packets handed to + * the PF_PACKET socket, including packets dropped because + * there wasn't room on the socket buffer - but not + * including packets that didn't pass the filter. + * + * In the BSD BPF, the count of received packets is + * incremented for every packet handed to BPF, regardless + * of whether it passed the filter. + * + * We can't make "pcap_stats()" work the same on both + * platforms, but the best approximation is to return + * "tp_packets" as the count of packets and "tp_drops" + * as the count of drops. + */ + handle->md.stat.ps_recv = kstats.tp_packets; + handle->md.stat.ps_drop = kstats.tp_drops; + } + else + { + /* + * If the error was EOPNOTSUPP, fall through, so that + * if you build the library on a system with + * "struct tpacket_stats" and run it on a system + * that doesn't, it works as it does if the library + * is built on a system without "struct tpacket_stats". + */ + if (errno != EOPNOTSUPP) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "pcap_stats: %s", pcap_strerror(errno)); + return -1; + } + } +#endif + /* + * On systems where the PACKET_STATISTICS "getsockopt()" argument + * is supported on PF_PACKET sockets: + * + * "ps_recv" counts only packets that *passed* the filter, + * not packets that didn't pass the filter. This includes + * packets later dropped because we ran out of buffer space. + * + * "ps_drop" counts packets dropped because we ran out of + * buffer space. It doesn't count packets dropped by the + * interface driver. It counts only packets that passed + * the filter. + * + * Both statistics include packets not yet read from the + * kernel by libpcap, and thus not yet seen by the application. + * + * On systems where the PACKET_STATISTICS "getsockopt()" argument + * is not supported on PF_PACKET sockets: + * + * "ps_recv" counts only packets that *passed* the filter, + * not packets that didn't pass the filter. It does not + * count packets dropped because we ran out of buffer + * space. + * + * "ps_drop" is not supported. + * + * "ps_recv" doesn't include packets not yet read from + * the kernel by libpcap. + */ *stats = handle->md.stat; return 0; } @@ -557,8 +809,7 @@ pcap_setfilter(pcap_t *handle, struct bpf_program *filter) } if (can_filter_in_kernel) { - if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, - &fcode, sizeof(fcode)) == 0) + if (set_kernel_filter(handle, &fcode) == 0) { /* Installation succeded - using kernel filter. */ handle->md.use_bpf = 1; @@ -578,6 +829,17 @@ pcap_setfilter(pcap_t *handle, struct bpf_program *filter) } } + /* + * If we're not using the kernel filter, get rid of any kernel + * filter that might've been there before, e.g. because the + * previous filter could work in the kernel, or because some other + * code attached a filter to the socket by some means other than + * calling "pcap_setfilter()". Otherwise, the kernel filter may + * filter out packets that would pass the new userland filter. + */ + if (!handle->md.use_bpf) + reset_kernel_filter(handle); + /* * Free up the copy of the filter that was made by "fix_program()". */ @@ -591,37 +853,133 @@ pcap_setfilter(pcap_t *handle, struct bpf_program *filter) /* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This - * function maps the ARPHRD_xxx constant to an appropriate - * DLT_xxx constant. + * function takes a pointer to a "pcap_t", and an ARPHRD_xxx + * constant, as arguments, and sets "handle->linktype" to the + * appropriate DLT_XXX constant and sets "handle->offset" to + * the appropriate value (to make "handle->offset" plus link-layer + * header length be a multiple of 4, so that the link-layer payload + * will be aligned on a 4-byte boundary when capturing packets). + * (If the offset isn't set here, it'll be 0; add code as appropriate + * for cases where it shouldn't be 0.) * - * Returns -1 if unable to map the type; we print a message and, - * if we're using PF_PACKET/SOCK_RAW rather than PF_INET/SOCK_PACKET, - * we fall back on using PF_PACKET/SOCK_DGRAM. + * Sets the link type to -1 if unable to map the type. */ -static int map_arphrd_to_dlt(int arptype) +static void map_arphrd_to_dlt(pcap_t *handle, int arptype) { switch (arptype) { + case ARPHRD_ETHER: case ARPHRD_METRICOM: - case ARPHRD_LOOPBACK: return DLT_EN10MB; - case ARPHRD_EETHER: return DLT_EN3MB; - case ARPHRD_AX25: return DLT_AX25; - case ARPHRD_PRONET: return DLT_PRONET; - case ARPHRD_CHAOS: return DLT_CHAOS; + case ARPHRD_LOOPBACK: + handle->linktype = DLT_EN10MB; + handle->offset = 2; + break; + + case ARPHRD_EETHER: + handle->linktype = DLT_EN3MB; + break; + + case ARPHRD_AX25: + handle->linktype = DLT_AX25; + break; + + case ARPHRD_PRONET: + handle->linktype = DLT_PRONET; + break; + + case ARPHRD_CHAOS: + handle->linktype = DLT_CHAOS; + break; + #ifndef ARPHRD_IEEE802_TR #define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */ #endif case ARPHRD_IEEE802_TR: - case ARPHRD_IEEE802: return DLT_IEEE802; - case ARPHRD_ARCNET: return DLT_ARCNET; - case ARPHRD_FDDI: return DLT_FDDI; + case ARPHRD_IEEE802: + handle->linktype = DLT_IEEE802; + handle->offset = 2; + break; + + case ARPHRD_ARCNET: + handle->linktype = DLT_ARCNET; + break; + + case ARPHRD_FDDI: + handle->linktype = DLT_FDDI; + handle->offset = 3; + break; #ifndef ARPHRD_ATM /* FIXME: How to #include this? */ #define ARPHRD_ATM 19 #endif - case ARPHRD_ATM: return DLT_ATM_CLIP; + case ARPHRD_ATM: + /* + * The Classical IP implementation in ATM for Linux + * supports both what RFC 1483 calls "LLC Encapsulation", + * in which each packet has an LLC header, possibly + * with a SNAP header as well, prepended to it, and + * what RFC 1483 calls "VC Based Multiplexing", in which + * different virtual circuits carry different network + * layer protocols, and no header is prepended to packets. + * + * They both have an ARPHRD_ type of ARPHRD_ATM, so + * you can't use the ARPHRD_ type to find out whether + * captured packets will have an LLC header, and, + * while there's a socket ioctl to *set* the encapsulation + * type, there's no ioctl to *get* the encapsulation type. + * + * This means that + * + * programs that dissect Linux Classical IP frames + * would have to check for an LLC header and, + * depending on whether they see one or not, dissect + * the frame as LLC-encapsulated or as raw IP (I + * don't know whether there's any traffic other than + * IP that would show up on the socket, or whether + * there's any support for IPv6 in the Linux + * Classical IP code); + * + * filter expressions would have to compile into + * code that checks for an LLC header and does + * the right thing. + * + * Both of those are a nuisance - and, at least on systems + * that support PF_PACKET sockets, we don't have to put + * up with those nuisances; instead, we can just capture + * in cooked mode. That's what we'll do. + */ + handle->linktype = DLT_LINUX_SLL; + break; + +#ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */ +#define ARPHRD_IEEE80211 801 +#endif + case ARPHRD_IEEE80211: + handle->linktype = DLT_IEEE802_11; + break; case ARPHRD_PPP: + /* + * Some PPP code in the kernel supplies no link-layer + * header whatsoever to PF_PACKET sockets; other PPP + * code supplies PPP link-layer headers ("syncppp.c"); + * some PPP code might supply random link-layer + * headers (PPP over ISDN - there's code in Ethereal, + * for example, to cope with PPP-over-ISDN captures + * with which the Ethereal developers have had to cope, + * heuristically trying to determine which of the + * oddball link-layer headers particular packets have). + * + * As such, we just punt, and run all PPP interfaces + * in cooked mode. + */ + handle->linktype = DLT_LINUX_SLL; + break; + + case ARPHRD_HDLC: + handle->linktype = DLT_C_HDLC; + break; + /* Not sure if this is correct for all tunnels, but it * works for CIPE */ case ARPHRD_TUNNEL: @@ -632,10 +990,23 @@ static int map_arphrd_to_dlt(int arptype) case ARPHRD_CSLIP: case ARPHRD_SLIP6: case ARPHRD_CSLIP6: - case ARPHRD_SLIP: return DLT_RAW; - } + case ARPHRD_ADAPT: + case ARPHRD_SLIP: + /* + * XXX - should some of those be mapped to DLT_LINUX_SLL + * instead? Should we just map all of them to DLT_LINUX_SLL? + */ + handle->linktype = DLT_RAW; + break; - return -1; + case ARPHRD_LOCALTLK: + handle->linktype = DLT_LTALK; + break; + + default: + handle->linktype = -1; + break; + } } /* ===== Functions to interface to the newer kernels ================== */ @@ -650,7 +1021,7 @@ live_open_new(pcap_t *handle, char *device, int promisc, int to_ms, char *ebuf) { #ifdef HAVE_PF_PACKET_SOCKETS - int sock_fd = -1, device_id, mtu, arptype; + int sock_fd = -1, device_id, arptype; struct packet_mreq mr; /* One shot loop used for error handling - bail out with break */ @@ -687,6 +1058,12 @@ live_open_new(pcap_t *handle, char *device, int promisc, */ handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf); + /* + * Default value for offset to align link-layer payload + * on a 4-byte boundary. + */ + handle->offset = 0; + /* * What kind of frames do we have to deal with? Fall back * to cooked mode if we have an unknown interface type. @@ -699,21 +1076,20 @@ live_open_new(pcap_t *handle, char *device, int promisc, arptype = iface_get_arptype(sock_fd, device, ebuf); if (arptype == -1) break; - handle->linktype = map_arphrd_to_dlt(arptype); + map_arphrd_to_dlt(handle, arptype); if (handle->linktype == -1 || + handle->linktype == DLT_LINUX_SLL || (handle->linktype == DLT_EN10MB && (strncmp("isdn", device, 4) == 0 || - strncmp("isdY", device, 4) == 0)) || - (handle->linktype == DLT_RAW && - (strncmp("ippp", device, 4) == 0))) { + strncmp("isdY", device, 4) == 0))) { /* - * Unknown interface type (-1), or an ISDN - * device (whose link-layer type we - * can only determine by using APIs - * that may be different on different + * Unknown interface type (-1), or a + * device we explicitly chose to run + * in cooked mode (e.g., PPP devices), + * or an ISDN device (whose link-layer + * type we can only determine by using + * APIs that may be different on different * kernels) - reopen in cooked mode. - * - * XXX - do that with DLT_RAW as well? */ if (close(sock_fd) == -1) { snprintf(ebuf, PCAP_ERRBUF_SIZE, @@ -736,11 +1112,11 @@ live_open_new(pcap_t *handle, char *device, int promisc, * update "map_arphrd_to_dlt()" * to handle the new type. */ - fprintf(stderr, - "Warning: arptype %d not " + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "arptype %d not " "supported by libpcap - " "falling back to cooked " - "socket\n", + "socket", arptype); } handle->linktype = DLT_LINUX_SLL; @@ -793,34 +1169,10 @@ live_open_new(pcap_t *handle, char *device, int promisc, } #endif - /* Compute the buffersize */ - - mtu = iface_get_mtu(sock_fd, device, ebuf); - if (mtu == -1) - break; - handle->bufsize = MAX_LINKHEADER_SIZE + mtu; - - /* Fill in the pcap structure */ + /* Save the socket FD in the pcap structure */ handle->fd = sock_fd; - handle->offset = 0; - handle->buffer = malloc(handle->bufsize); - if (!handle->buffer) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "malloc: %s", pcap_strerror(errno)); - break; - } - - /* - * This is a 2.2 or later kernel, as it has PF_PACKET; - * "recvfrom()", when passed the MSG_TRUNC flag, will - * return the actual length of the packet, not the - * number of bytes from the packet copied to userland, - * so we can safely pass it a byte count based on the - * snapshot length. - */ - handle->md.readlen = handle->snapshot; return 1; } while(0); @@ -995,8 +1347,7 @@ static int live_open_old(pcap_t *handle, char *device, int promisc, int to_ms, char *ebuf) { - int sock_fd = -1, mtu, arptype; - struct utsname utsname; + int sock_fd = -1, arptype; struct ifreq ifr; do { @@ -1079,24 +1430,22 @@ live_open_old(pcap_t *handle, char *device, int promisc, } } - /* Compute the buffersize */ - - mtu = iface_get_mtu(sock_fd, device, ebuf); - if (mtu == -1) - break; - handle->bufsize = MAX_LINKHEADER_SIZE + mtu; - if (handle->bufsize < handle->snapshot) - handle->bufsize = handle->snapshot; - /* All done - fill in the pcap handle */ arptype = iface_get_arptype(sock_fd, device, ebuf); if (arptype == -1) break; + /* Save the socket FD in the pcap structure */ + handle->fd = sock_fd; + + /* + * Default value for offset to align link-layer payload + * on a 4-byte boundary. + */ handle->offset = 0; - handle->linktype = map_arphrd_to_dlt(arptype); + /* * XXX - handle ISDN types here? We can't fall back on * cooked sockets, so we'd have to figure out from the @@ -1108,62 +1457,14 @@ live_open_old(pcap_t *handle, char *device, int promisc, * type that has only an Ethernet packet type as * a link-layer header. */ - if (handle->linktype == -1) { + map_arphrd_to_dlt(handle, arptype); + if (handle->linktype == -1 || + handle->linktype == DLT_LINUX_SLL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "interface type of %s not supported", device); break; } - handle->buffer = malloc(handle->bufsize); - if (!handle->buffer) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "malloc: %s", pcap_strerror(errno)); - break; - } - /* - * This might be a 2.0[.x] kernel - check. - */ - if (uname(&utsname) < 0 || - strncmp(utsname.release, "2.0", 3) == 0) { - /* - * Either we couldn't find out what kernel release - * this is, or it's a 2.0[.x] kernel. - * - * In the 2.0[.x] kernel, a "recvfrom()" on - * a SOCK_PACKET socket, with MSG_TRUNC set, will - * return the number of bytes read, so if we pass - * a length based on the snapshot length, it'll - * return the number of bytes from the packet - * copied to userland, not the actual length - * of the packet. - * - * This means that, for example, the IP dissector - * in tcpdump will get handed a packet length less - * than the length in the IP header, and will - * complain about "truncated-ip". - * - * So we don't bother trying to copy from the - * kernel only the bytes in which we're interested, - * but instead copy them all, just as the older - * versions of libpcap for Linux did. - * - * Just one of many problems with packet capture - * on 2.0[.x] kernels; you really want a 2.2[.x] - * or later kernel if you want packet capture to - * work well. - */ - handle->md.readlen = handle->bufsize; - } else { - /* - * This is a 2.2[.x] or later kernel (although - * why we're using SOCK_PACKET on such a system - * is unknown to me). - * - * We can safely pass "recvfrom()" a byte count - * based on the snapshot length. - */ - handle->md.readlen = handle->snapshot; - } return 1; } while (0); @@ -1239,7 +1540,7 @@ iface_get_arptype(int fd, const char *device, char *ebuf) return ifr.ifr_hwaddr.sa_family; } -#ifdef HAVE_PF_PACKET_SOCKETS +#ifdef SO_ATTACH_FILTER static int fix_program(pcap_t *handle, struct sock_fprog *fcode) { @@ -1363,4 +1664,108 @@ fix_offset(struct bpf_insn *p) } return 0; } + +static int +set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) +{ + int total_filter_on = 0; + int save_mode; + int ret; + int save_errno; + + /* + * The socket filter code doesn't discard all packets queued + * up on the socket when the filter is changed; this means + * that packets that don't match the new filter may show up + * after the new filter is put onto the socket, if those + * packets haven't yet been read. + * + * This means, for example, that if you do a tcpdump capture + * with a filter, the first few packets in the capture might + * be packets that wouldn't have passed the filter. + * + * We therefore discard all packets queued up on the socket + * when setting a kernel filter. (This isn't an issue for + * userland filters, as the userland filtering is done after + * packets are queued up.) + * + * To flush those packets, we put the socket in read-only mode, + * and read packets from the socket until there are no more to + * read. + * + * In order to keep that from being an infinite loop - i.e., + * to keep more packets from arriving while we're draining + * the queue - we put the "total filter", which is a filter + * that rejects all packets, onto the socket before draining + * the queue. + * + * This code deliberately ignores any errors, so that you may + * get bogus packets if an error occurs, rather than having + * the filtering done in userland even if it could have been + * done in the kernel. + */ + if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, + &total_fcode, sizeof(total_fcode)) == 0) { + char drain[1]; + + /* + * Note that we've put the total filter onto the socket. + */ + total_filter_on = 1; + + /* + * Save the socket's current mode, and put it in + * non-blocking mode; we drain it by reading packets + * until we get an error (which we assume is a + * "nothing more to be read" error). + */ + save_mode = fcntl(handle->fd, F_GETFL, 0); + if (save_mode != -1 && + fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) { + while (recv(handle->fd, &drain, sizeof drain, + MSG_TRUNC) >= 0) + ; + fcntl(handle->fd, F_SETFL, save_mode); + } + } + + /* + * Now attach the new filter. + */ + ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, + fcode, sizeof(*fcode)); + if (ret == -1 && total_filter_on) { + /* + * Well, we couldn't set that filter on the socket, + * but we could set the total filter on the socket. + * + * This could, for example, mean that the filter was + * too big to put into the kernel, so we'll have to + * filter in userland; in any case, we'll be doing + * filtering in userland, so we need to remove the + * total filter so we see packets. + */ + save_errno = errno; + + /* + * XXX - if this fails, we're really screwed; + * we have the total filter on the socket, + * and it won't come off. What do we do then? + */ + reset_kernel_filter(handle); + + errno = save_errno; + } + return ret; +} + +static int +reset_kernel_filter(pcap_t *handle) +{ + /* setsockopt() barfs unless it get a dummy parameter */ + int dummy; + + return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER, + &dummy, sizeof(dummy)); +} #endif diff --git a/contrib/libpcap/pcap-nit.c b/contrib/libpcap/pcap-nit.c index 6be658d9f5a7..fe672995b888 100644 --- a/contrib/libpcap/pcap-nit.c +++ b/contrib/libpcap/pcap-nit.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.39 2000/10/28 00:01:29 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.41 2001/12/10 07:14:18 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -75,6 +75,22 @@ int pcap_stats(pcap_t *p, struct pcap_stat *ps) { + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this does not include packets dropped because we ran out + * of buffer space. + * + * "ps_drop" presumably counts packets dropped by the socket + * because of flow control requirements or resource exhaustion; + * it doesn't count packets dropped by the interface driver. + * As filtering is done in userland, it counts packets regardless + * of whether they would've passed the filter. + * + * These statistics don't include packets not yet read from the + * kernel by libpcap or packets not yet read from libpcap by the + * application. + */ *ps = p->md.stat; return (0); } diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c index 2dec9080f215..f29bc99a1e93 100644 --- a/contrib/libpcap/pcap-pf.c +++ b/contrib/libpcap/pcap-pf.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.62 2000/10/28 00:01:30 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.65 2001/12/10 07:14:19 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -195,6 +195,42 @@ int pcap_stats(pcap_t *p, struct pcap_stat *ps) { + /* + * If packet filtering is being done in the kernel: + * + * "ps_recv" counts only packets that passed the filter. + * This does not include packets dropped because we + * ran out of buffer space. (XXX - perhaps it should, + * by adding "ps_drop" to "ps_recv", for compatibility + * with some other platforms. On the other hand, on + * some platforms "ps_recv" counts only packets that + * passed the filter, and on others it counts packets + * that didn't pass the filter....) + * + * "ps_drop" counts packets that passed the kernel filter + * (if any) but were dropped because the input queue was + * full. + * + * "ps_ifdrop" counts packets dropped by the network + * inteface (regardless of whether they would have passed + * the input filter, of course). + * + * If packet filtering is not being done in the kernel: + * + * "ps_recv" counts only packets that passed the filter. + * + * "ps_drop" counts packets that were dropped because the + * input queue was full, regardless of whether they passed + * the userland filter. + * + * "ps_ifdrop" counts packets dropped by the network + * inteface (regardless of whether they would have passed + * the input filter, of course). + * + * These statistics don't include packets not yet read from + * the kernel by libpcap, but they may include packets not + * yet read from libpcap by the application. + */ ps->ps_recv = p->md.TotAccepted; ps->ps_drop = p->md.TotDrops; ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; @@ -265,21 +301,53 @@ your system may not be properly configured; see \"man packetfilter(4)\"\n", p->linktype = DLT_FDDI; break; - default: - /* - * XXX - * Currently, the Ultrix packet filter supports only - * Ethernet and FDDI. Eventually, support for SLIP and PPP - * (and possibly others: T1?) should be added. - */ -#ifdef notdef - warning( - "Packet filter data-link type %d unknown, assuming Ethernet", - devparams.end_dev_type); +#ifdef ENDT_SLIP + case ENDT_SLIP: + p->linktype = DLT_SLIP; + break; #endif + +#ifdef ENDT_PPP + case ENDT_PPP: + p->linktype = DLT_PPP; + break; +#endif + +#ifdef ENDT_LOOPBACK + case ENDT_LOOPBACK: + /* + * It appears to use Ethernet framing, at least on + * Digital UNIX 4.0. + */ p->linktype = DLT_EN10MB; p->offset = 2; break; +#endif + +#ifdef ENDT_TRN + case ENDT_TRN: + p->linktype = DLT_IEEE802; + break; +#endif + + default: + /* + * XXX - what about ENDT_IEEE802? The pfilt.h header + * file calls this "IEEE 802 networks (non-Ethernet)", + * but that doesn't specify a specific link layer type; + * it could be 802.4, or 802.5 (except that 802.5 is + * ENDT_TRN), or 802.6, or 802.11, or.... That's why + * DLT_IEEE802 was hijacked to mean Token Ring in various + * BSDs, and why we went along with that hijacking. + * + * XXX - what about ENDT_HDLC and ENDT_NULL? + * Presumably, as ENDT_OTHER is just "Miscellaneous + * framing", there's not much we can do, as that + * doesn't specify a particular type of header. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %lu", + devparams.end_dev_type); + goto bad; } /* set truncation */ #ifdef PCAP_FDDIPAD @@ -318,6 +386,8 @@ your system may not be properly configured; see \"man packetfilter(4)\"\n", return (p); bad: + if (p->fd >= 0) + close(p->fd); free(p); return (NULL); } diff --git a/contrib/libpcap/pcap-snit.c b/contrib/libpcap/pcap-snit.c index 59cf3acd9fe0..d3aaf1ddee34 100644 --- a/contrib/libpcap/pcap-snit.c +++ b/contrib/libpcap/pcap-snit.c @@ -25,7 +25,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.54 2000/10/28 00:01:30 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.56 2001/12/10 07:14:20 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -88,6 +88,23 @@ int pcap_stats(pcap_t *p, struct pcap_stat *ps) { + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this does not include packets dropped because we ran out + * of buffer space. + * + * "ps_drop" counts packets dropped inside the "/dev/nit" + * device because of flow control requirements or resource + * exhaustion; it doesn't count packets dropped by the + * interface driver, or packets dropped upstream. As filtering + * is done in userland, it counts packets regardless of whether + * they would've passed the filter. + * + * These statistics don't include packets not yet read from the + * kernel by libpcap or packets not yet read from libpcap by the + * application. + */ *ps = p->md.stat; return (0); } diff --git a/contrib/libpcap/pcap-snoop.c b/contrib/libpcap/pcap-snoop.c index 65ad27385426..5d58ba3c323e 100644 --- a/contrib/libpcap/pcap-snoop.c +++ b/contrib/libpcap/pcap-snoop.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.30 2000/10/28 00:01:30 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.33 2001/12/10 07:14:21 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -115,10 +115,28 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps) return (-1); } + /* + * "ifdrops" are those dropped by the network interface + * due to resource shortages or hardware errors. + * + * "sbdrops" are those dropped due to socket buffer limits. + * + * As filter is done in userland, "sbdrops" counts packets + * regardless of whether they would've passed the filter. + * + * XXX - does this count *all* Snoop or Drain sockets, + * rather than just this socket? If not, why does it have + * both Snoop and Drain statistics? + */ p->md.stat.ps_drop = rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops + rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops; + /* + * "ps_recv" counts only packets that passed the filter. + * As filtering is done in userland, this does not include + * packets dropped because we ran out of buffer space. + */ *ps = p->md.stat; return (0); } @@ -179,6 +197,7 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */ strncmp("fa", device, 2) == 0 || strncmp("qaa", device, 3) == 0 || + strncmp("cip", device, 3) == 0 || strncmp("el", device, 2) == 0) { p->linktype = DLT_EN10MB; p->offset = RAW_HDRPAD(sizeof(struct ether_header)); diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c index 9f32721a14a3..6b82453ddb8e 100644 --- a/contrib/libpcap/pcap.c +++ b/contrib/libpcap/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.36 2000/12/16 10:43:31 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.38 2001/12/29 21:55:32 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -46,6 +46,8 @@ static const char rcsid[] = #include #include #include +#include +#include #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -168,6 +170,65 @@ pcap_geterr(pcap_t *p) return (p->errbuf); } +/* + * NOTE: in the future, these may need to call platform-dependent routines, + * e.g. on platforms with memory-mapped packet-capture mechanisms where + * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive. + */ +int +pcap_getnonblock(pcap_t *p, char *errbuf) +{ + int fdflags; + + if (p->sf.rfile != NULL) { + /* + * This is a savefile, not a live capture file, so + * never say it's in non-blocking mode. + */ + return (0); + } + fdflags = fcntl(p->fd, F_GETFL, 0); + if (fdflags == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_strerror(errno)); + return (-1); + } + if (fdflags & O_NONBLOCK) + return (1); + else + return (0); +} + +int +pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) +{ + int fdflags; + + if (p->sf.rfile != NULL) { + /* + * This is a savefile, not a live capture file, so + * ignore requests to put it in non-blocking mode. + */ + return (0); + } + fdflags = fcntl(p->fd, F_GETFL, 0); + if (fdflags == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_strerror(errno)); + return (-1); + } + if (nonblock) + fdflags |= O_NONBLOCK; + else + fdflags &= ~O_NONBLOCK; + if (fcntl(p->fd, F_SETFL, fdflags) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", + pcap_strerror(errno)); + return (-1); + } + return (0); +} + /* * Not all systems have strerror(). */ diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c index cc5b47e28621..f952a198628d 100644 --- a/contrib/libpcap/savefile.c +++ b/contrib/libpcap/savefile.c @@ -30,7 +30,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.49 2000/12/21 10:29:23 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.55 2001/11/28 07:16:53 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -149,25 +149,35 @@ static const char rcsid[] = */ #define LINKTYPE_PPP_HDLC 50 /* PPP in HDLC-like framing */ +#define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */ + #define LINKTYPE_ATM_RFC1483 100 /* LLC/SNAP-encapsulated ATM */ #define LINKTYPE_RAW 101 /* raw IP */ #define LINKTYPE_SLIP_BSDOS 102 /* BSD/OS SLIP BPF header */ #define LINKTYPE_PPP_BSDOS 103 /* BSD/OS PPP BPF header */ #define LINKTYPE_C_HDLC 104 /* Cisco HDLC */ +#define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 (wireless) */ #define LINKTYPE_ATM_CLIP 106 /* Linux Classical IP over ATM */ +#define LINKTYPE_LOOP 108 /* OpenBSD loopback */ + +#define LINKTYPE_LINUX_SLL 113 /* Linux cooked socket capture */ +#define LINKTYPE_LTALK 114 /* Apple LocalTalk hardware */ +#define LINKTYPE_ECONET 115 /* Acorn Econet */ + +#define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */ +#define LINKTYPE_PRISM_HEADER 119 /* 802.11+Prism II monitor mode */ +#define LINKTYPE_AIRONET_HEADER 120 /* FreeBSD Aironet driver stuff */ /* - * Reserved for future use. + * These types are reserved for future use. */ -#define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 (wireless) */ #define LINKTYPE_FR 107 /* BSD/OS Frame Relay */ -#define LINKTYPE_LOOP 108 /* OpenBSD loopback */ #define LINKTYPE_ENC 109 /* OpenBSD IPSEC enc */ #define LINKTYPE_LANE8023 110 /* ATM LANE + 802.3 */ #define LINKTYPE_HIPPI 111 /* NetBSD HIPPI */ #define LINKTYPE_HDLC 112 /* NetBSD HDLC framing */ - -#define LINKTYPE_LINUX_SLL 113 /* Linux cooked socket capture */ +#define LINKTYPE_IPFILTER 116 /* IP Filter capture files */ +#define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */ static struct linktype_map { int dlt; @@ -216,6 +226,9 @@ static struct linktype_map { /* NetBSD sync/async serial PPP (or Cisco HDLC) */ { DLT_PPP_SERIAL, LINKTYPE_PPP_HDLC }, + /* NetBSD PPP over Ethernet */ + { DLT_PPP_ETHER, LINKTYPE_PPP_ETHER }, + /* IEEE 802.11 wireless */ { DLT_IEEE802_11, LINKTYPE_IEEE802_11 }, @@ -225,6 +238,21 @@ static struct linktype_map { /* Linux cooked socket capture */ { DLT_LINUX_SLL, LINKTYPE_LINUX_SLL }, + /* Apple LocalTalk hardware */ + { DLT_LTALK, LINKTYPE_LTALK }, + + /* Acorn Econet */ + { DLT_ECONET, LINKTYPE_ECONET }, + + /* For Cisco-internal use */ + { DLT_CISCO_IOS, LINKTYPE_CISCO_IOS }, + + /* Prism II monitor-mode header plus 802.11 header */ + { DLT_PRISM_HEADER, LINKTYPE_PRISM_HEADER }, + + /* FreeBSD Aironet driver stuff */ + { DLT_AIRONET_HEADER, LINKTYPE_AIRONET_HEADER }, + /* * Any platform that defines additional DLT_* codes should: *