From 0a94d38f0590468c79627c0140ef494c66616ae6 Mon Sep 17 00:00:00 2001 From: Bill Fenner Date: Fri, 21 Jun 2002 01:36:27 +0000 Subject: [PATCH] Import libpcap 0.7.1, from http://www.tcpdump.org/release/libpcap-0.7.1.tar.gz --- contrib/libpcap/.cvsignore | 2 + contrib/libpcap/CHANGES | 9 +- contrib/libpcap/CREDITS | 19 + contrib/libpcap/FILES | 5 +- contrib/libpcap/INSTALL.txt | 342 +++++++++++ contrib/libpcap/Makefile.in | 2 +- contrib/libpcap/README | 12 +- contrib/libpcap/README.aix | 68 ++- contrib/libpcap/README.linux | 18 + contrib/libpcap/README.tru64 | 49 ++ contrib/libpcap/TODO | 16 +- contrib/libpcap/VERSION | 2 +- contrib/libpcap/acconfig.h | 7 + contrib/libpcap/aclocal.m4 | 24 +- contrib/libpcap/arcnet.h | 52 ++ contrib/libpcap/bpf/net/bpf.h | 71 ++- contrib/libpcap/config.guess | 471 +++++++-------- contrib/libpcap/config.h.in | 29 +- contrib/libpcap/config.sub | 98 +-- contrib/libpcap/configure | 297 +++++---- contrib/libpcap/configure.in | 37 +- contrib/libpcap/ethertype.h | 11 +- contrib/libpcap/gencode.c | 762 +++++++++++++++++++++-- contrib/libpcap/gencode.h | 53 +- contrib/libpcap/grammar.y | 34 +- contrib/libpcap/inet.c | 1061 ++++++++++++++++++++++++++++----- contrib/libpcap/llc.h | 11 +- contrib/libpcap/nametoaddr.c | 5 +- contrib/libpcap/optimize.c | 29 +- contrib/libpcap/pcap-bpf.c | 80 ++- contrib/libpcap/pcap-dlpi.c | 463 ++++++++++++-- contrib/libpcap/pcap-int.h | 3 +- contrib/libpcap/pcap-linux.c | 735 ++++++++++++++++++----- contrib/libpcap/pcap-nit.c | 18 +- contrib/libpcap/pcap-pf.c | 94 ++- contrib/libpcap/pcap-snit.c | 19 +- contrib/libpcap/pcap-snoop.c | 21 +- contrib/libpcap/pcap.3 | 352 ++++++++++- contrib/libpcap/pcap.c | 63 +- contrib/libpcap/pcap.h | 34 +- contrib/libpcap/savefile.c | 40 +- contrib/libpcap/scanner.l | 58 +- 42 files changed, 4569 insertions(+), 1007 deletions(-) create mode 100644 contrib/libpcap/INSTALL.txt create mode 100644 contrib/libpcap/README.tru64 create mode 100644 contrib/libpcap/acconfig.h create mode 100644 contrib/libpcap/arcnet.h 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/aclocal.m4 b/contrib/libpcap/aclocal.m4 index d729741191b1..294a89c59b7b 100644 --- a/contrib/libpcap/aclocal.m4 +++ b/contrib/libpcap/aclocal.m4 @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.71 2000/09/19 03:56:26 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.75 2001/12/10 08:33:41 guy Exp $ (LBL) dnl dnl Copyright (c) 1995, 1996, 1997, 1998 dnl The Regents of the University of California. All rights reserved. @@ -517,10 +517,10 @@ dnl AC_DEFUN(AC_LBL_UNALIGNED_ACCESS, [AC_MSG_CHECKING(if unaligned accesses fail) AC_CACHE_VAL(ac_cv_lbl_unaligned_fail, - [case "$target_cpu" in + [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 ;; @@ -767,3 +767,21 @@ fi AC_MSG_RESULT($ac_cv___attribute__) ]) +dnl +dnl Checks to see if tpacket_stats is defined in linux/if_packet.h +dnl If so then pcap-linux.c can use this to report proper statistics. +dnl +dnl -Scott Barron +dnl +AC_DEFUN(AC_LBL_TPACKET_STATS, + [AC_MSG_CHECKING(if if_packet.h has tpacket_stats defined) + AC_CACHE_VAL(ac_cv_lbl_tpacket_stats, + AC_TRY_COMPILE([ +# include ], + [struct tpacket_stats stats], + ac_cv_lbl_tpacket_stats=yes, + ac_cv_lbl_tpacket_stats=no)) + AC_MSG_RESULT($ac_cv_lbl_tpacket_stats) + if test $ac_cv_lbl_tpacket_stats = yes; then + AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined]) + fi]) 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/bpf/net/bpf.h b/contrib/libpcap/bpf/net/bpf.h index 26abc79f261e..8c73f3ad4f6e 100644 --- a/contrib/libpcap/bpf/net/bpf.h +++ b/contrib/libpcap/bpf/net/bpf.h @@ -37,7 +37,7 @@ * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * - * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.44 2000/12/21 10:29:24 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.51 2001/11/28 05:50:05 guy Exp $ (LBL) */ #ifndef BPF_MAJOR_VERSION @@ -212,11 +212,18 @@ struct bpf_hdr { #define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ /* - * This value is defined by NetBSD; other platforms should refrain from - * using it for other purposes, so that NetBSD savefiles with a link - * type of 50 can be read as this type on all platforms. + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. */ #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ /* * This value was defined by libpcap 0.5; platforms that have defined @@ -235,16 +242,6 @@ struct bpf_hdr { #define DLT_C_HDLC 104 /* Cisco HDLC */ #define DLT_CHDLC DLT_C_HDLC -/* - * Reserved for future use. - * Do not pick other numerical value for these unless you have also - * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c", - * which will arrange that capture files for these DLT_ types have - * the same "network" value on all platforms, regardless of what - * value is chosen for their DLT_ type (thus allowing captures made - * on one platform to be read on other platforms, even if the two - * platforms don't use the same numerical values for all DLT_ types). - */ #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ /* @@ -260,14 +257,15 @@ struct bpf_hdr { * OpenBSD defines it as 12, but that collides with DLT_RAW, so we * define it as 108 here. If OpenBSD picks up this file, it should * define DLT_LOOP as 12 in its version, as per the comment above - - * and should not use 108 for any purpose. + * and should not use 108 as a DLT_ value. */ #define DLT_LOOP 108 /* * Values between 109 and 112 are used in capture file headers as * link-layer types corresponding to DLT_ types that might differ - * between platforms; don't use those values for new DLT_ new types. + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. */ /* @@ -275,6 +273,47 @@ struct bpf_hdr { */ #define DLT_LINUX_SLL 113 +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + /* * The instruction encodings. */ 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/gencode.c b/contrib/libpcap/gencode.c index 1b9cafc1169d..498539d8e354 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.140.2.1 2001/01/14 06:48:35 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.160 2001/11/30 07:25:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -51,20 +51,23 @@ struct rtentry; #include "ethertype.h" #include "nlpid.h" +#include "llc.h" #include "gencode.h" #include "ppp.h" #include "sll.h" +#include "arcnet.h" #include #ifdef INET6 #include #include #endif /*INET6*/ -#define LLC_SNAP_LSAP 0xaa -#define LLC_ISO_LSAP 0xfe - #define ETHERMTU 1500 +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -75,6 +78,9 @@ struct rtentry; static jmp_buf top_ctx; static pcap_t *bpf_pcap; +/* Hack for updating VLAN offsets. */ +static u_int orig_linktype = -1, orig_nl = -1; + /* XXX */ #ifdef PCAP_FDDIPAD int pcap_fddipad = PCAP_FDDIPAD; @@ -143,6 +149,7 @@ static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); #endif +static struct block *gen_ahostop(const u_char *, int); static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_thostop(const u_char *, int); @@ -547,8 +554,16 @@ init_linktype(type) { linktype = type; + orig_linktype = -1; + orig_nl = -1; + switch (type) { + case DLT_ARCNET: + off_linktype = 2; + off_nl = 6; /* XXX in reality, variable! */ + return; + case DLT_EN10MB: off_linktype = 12; off_nl = 14; @@ -577,12 +592,21 @@ init_linktype(type) return; case DLT_PPP: - case DLT_C_HDLC: - case DLT_PPP_SERIAL: + case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ + case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_nl = 4; return; + case DLT_PPP_ETHER: + /* + * This does no include the Ethernet header, and + * only covers session state. + */ + off_linktype = 6; + off_nl = 8; + return; + case DLT_PPP_BSDOS: off_linktype = 5; off_nl = 24; @@ -591,12 +615,13 @@ init_linktype(type) case DLT_FDDI: /* * FDDI doesn't really have a link-level type field. - * We assume that SSAP = SNAP is being used and pick - * out the encapsulated Ethernet type. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? */ - off_linktype = 19; + off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif @@ -609,9 +634,10 @@ init_linktype(type) case DLT_IEEE802: /* * Token Ring doesn't really have a link-level type field. - * We assume that SSAP = SNAP is being used and pick - * out the encapsulated Ethernet type. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. @@ -629,10 +655,42 @@ init_linktype(type) * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ - off_linktype = 20; + off_linktype = 14; off_nl = 22; return; + case DLT_IEEE802_11: + /* + * 802.11 doesn't really have a link-level type field. + * We set "off_linktype" to the offset of the LLC header. + * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. + * XXX - should we generate code to check for SNAP? + * + * XXX - the header is actually variable-length. We + * assume a 24-byte link-layer header, as appears in + * data frames in networks with no bridges. + */ + off_linktype = 24; + off_nl = 30; + return; + + case DLT_PRISM_HEADER: + /* + * Same as 802.11, but with an additional header before + * the 802.11 header, containing a bunch of additional + * information including radio-level information. + * + * The header is 144 bytes long. + * + * XXX - same variable-length header problem; at least + * the Prism header is fixed-length. + */ + off_linktype = 144+24; + off_nl = 144+30; + return; + case DLT_ATM_RFC1483: /* * assume routed, non-ISO PDUs @@ -656,6 +714,16 @@ init_linktype(type) off_linktype = 14; off_nl = 16; return; + + case DLT_LTALK: + /* + * LocalTalk does have a 1-byte type field in the LLAP header, + * but really it just indicates whether there is a "short" or + * "long" DDP packet following. + */ + off_linktype = -1; + off_nl = 0; + return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ @@ -702,30 +770,110 @@ gen_linktype(proto) { struct block *b0, *b1; - /* If we're not using encapsulation, we're done */ - if (off_linktype == -1) - return gen_true(); - switch (linktype) { case DLT_EN10MB: - /* - * XXX - handle other LLC-encapsulated protocols here - * (IPX, OSI)? - */ switch (proto) { - case LLC_ISO_LSAP: + case LLCSAP_ISONS: /* * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? */ b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLC_ISO_LSAP << 8) | LLC_ISO_LSAP)); + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); gen_and(b0, b1); return b1; + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Check for; + * + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which are 802.3 + * frames (i.e., the type/length field is + * a length field, <= ETHERMTU, rather than + * a type field) with the first two bytes + * after the Ethernet/802.3 header being + * 0xFFFF; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header and + * with the IPX LSAP as the DSAP in the LLC + * header; + * + * Ethernet_SNAP frames, which are 802.3 + * frames with an LLC header and a SNAP + * header and with an OUI of 0x000000 + * (encapsulated Ethernet) and a protocol + * ID of ETHERTYPE_IPX in the SNAP header. + * + * XXX - should we generate the same code both + * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? + */ + + /* + * This generates code to check both for the + * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_cmp(off_linktype + 2, BPF_H, + (bpf_int32)0xFFFF); + gen_or(b0, b1); + + /* + * Now we add code to check for SNAP frames with + * ETHERTYPE_IPX, i.e. Ethernet_SNAP. + */ + b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); + gen_or(b0, b1); + + /* + * Now we generate code to check for 802.3 + * frames in general. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + + /* + * Now add the check for 802.3 frames before the + * check for Ethernet_802.2 and Ethernet_802.3, + * as those checks should only be done on 802.3 + * frames, not on Ethernet frames. + */ + gen_and(b0, b1); + + /* + * Now add the check for Ethernet_II frames, and + * do that before checking for the other frame + * types. + */ + b0 = gen_cmp(off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); + gen_or(b0, b1); + return b1; + case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* @@ -767,14 +915,301 @@ gen_linktype(proto) gen_or(b0, b1); return b1; + + default: + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so the frames + * that match would be 802.2 frames. + * Check that the frame is an 802.2 frame + * (i.e., that the length/type field is + * a length field, <= ETHERMTU) and + * then check the DSAP. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)proto); + gen_and(b0, b1); + return b1; + } else { + /* + * This is an Ethernet type, so compare + * the length/type field with it (if + * the frame is an 802.2 frame, the length + * field will be <= ETHERMTU, and, as + * "proto" is > ETHERMTU, this test + * will fail and the frame won't match, + * which is what we want). + */ + return gen_cmp(off_linktype, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_IEEE802_11: + case DLT_PRISM_HEADER: + case DLT_FDDI: + case DLT_IEEE802: + case DLT_ATM_RFC1483: + case DLT_ATM_CLIP: + /* + * XXX - handle token-ring variable-length header. + */ + switch (proto) { + + case LLCSAP_ISONS: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + + case LLCSAP_NETBEUI: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)LLCSAP_IPX); + + case ETHERTYPE_ATALK: + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * XXX - check for an organization code of + * encapsulated Ethernet as well? + */ + return gen_snap(0x080007, ETHERTYPE_ATALK, + off_linktype); + break; + + default: + /* + * XXX - we don't have to check for IPX 802.3 + * here, but should we check for the IPX Ethertype? + */ + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so check + * the DSAP. + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)proto); + } else { + /* + * This is an Ethernet type; we assume + * that it's unlikely that it'll + * appear in the right place at random, + * and therefore check only the + * location that would hold the Ethernet + * type in a SNAP frame with an organization + * code of 0x000000 (encapsulated Ethernet). + * + * XXX - if we were to check for the SNAP DSAP + * and LSAP, as per XXX, and were also to check + * for an organization code of 0x000000 + * (encapsulated Ethernet), we'd do + * + * return gen_snap(0x000000, proto, + * off_linktype); + * + * here; for now, we don't, as per the above. + * I don't know whether it's worth the + * extra CPU time to do the right check + * or not. + */ + return gen_cmp(off_linktype+6, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_LINUX_SLL: + switch (proto) { + + case LLCSAP_ISONS: + /* + * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + gen_and(b0, b1); + return b1; + + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which have a frame + * type of LINUX_SLL_P_802_3; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header (i.e, have + * a frame type of LINUX_SLL_P_802_2) and + * with the IPX LSAP as the DSAP in the LLC + * header; + * + * Ethernet_SNAP frames, which are 802.3 + * frames with an LLC header and a SNAP + * header and with an OUI of 0x000000 + * (encapsulated Ethernet) and a protocol + * ID of ETHERTYPE_IPX in the SNAP header. + * + * First, do the checks on LINUX_SLL_P_802_2 + * frames; generate the check for either + * Ethernet_802.2 or Ethernet_SNAP frames, and + * then put a check for LINUX_SLL_P_802_2 frames + * before it. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_snap(0x000000, ETHERTYPE_IPX, + off_linktype + 2); + gen_or(b0, b1); + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + gen_and(b0, b1); + + /* + * Now check for 802.3 frames and OR that with + * the previous test. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3); + gen_or(b0, b1); + + /* + * Now add the check for Ethernet_II frames, and + * do that before checking for the other frame + * types. + */ + b0 = gen_cmp(off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); + gen_or(b0, b1); + return b1; + + case ETHERTYPE_ATALK: + case ETHERTYPE_AARP: + /* + * EtherTalk (AppleTalk protocols on Ethernet link + * layer) may use 802.2 encapsulation. + */ + + /* + * Check for 802.2 encapsulation (EtherTalk phase 2?); + * we check for the 802.2 protocol type in the + * "Ethernet type" field. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * 802.2-encapsulated ETHERTYPE_AARP packets are + * SNAP packets with an organization code of + * 0x000000 (encapsulated Ethernet) and a protocol + * type of ETHERTYPE_AARP (Appletalk ARP). + */ + if (proto == ETHERTYPE_ATALK) + b1 = gen_snap(0x080007, ETHERTYPE_ATALK, + off_linktype + 2); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, + off_linktype + 2); + gen_and(b0, b1); + + /* + * Check for Ethernet encapsulation (Ethertalk + * phase 1?); we just check for the Ethernet + * protocol type. + */ + b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + + gen_or(b0, b1); + return b1; + + default: + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so the frames + * that match would be 802.2 frames. + * Check for the 802.2 protocol type + * in the "Ethernet type" field, and + * then check the DSAP. + */ + b0 = gen_cmp(off_linktype, BPF_H, + LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)proto); + gen_and(b0, b1); + return b1; + } else { + /* + * This is an Ethernet type, so compare + * the length/type field with it (if + * the frame is an 802.2 frame, the length + * field will be <= ETHERMTU, and, as + * "proto" is > ETHERMTU, this test + * will fail and the frame won't match, + * which is what we want). + */ + return gen_cmp(off_linktype, BPF_H, + (bpf_int32)proto); + } } break; case DLT_SLIP: - return gen_false(); + case DLT_SLIP_BSDOS: + case DLT_RAW: + /* + * These types don't provide any type field; packets + * are always IP. + * + * XXX - for IPv4, check for a version number of 4, and, + * for IPv6, check for a version number of 6? + */ + switch (proto) { + + case ETHERTYPE_IP: +#ifdef INET6 + case ETHERTYPE_IPV6: +#endif + return gen_true(); /* always true */ + + default: + return gen_false(); /* always false */ + } + break; case DLT_PPP: case DLT_PPP_SERIAL: + case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. @@ -803,9 +1238,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -843,9 +1291,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -910,7 +1371,73 @@ gen_linktype(proto) proto = htonl(proto); } return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + + case DLT_ARCNET: + /* + * XXX should we check for first fragment if the protocol + * uses PHDS? + */ + switch(proto) { + default: + return gen_false(); +#ifdef INET6 + case ETHERTYPE_IPV6: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_INET6))); +#endif /* INET6 */ + case ETHERTYPE_IP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_IP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_IP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_ARP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_ARP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ARP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_REVARP: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_REVARP))); + case ETHERTYPE_ATALK: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ATALK))); + } + break; + + case DLT_LTALK: + switch (proto) { + case ETHERTYPE_ATALK: + return gen_true(); + default: + return gen_false(); + } + break; } + + /* + * All the types that have no encapsulation should either be + * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if + * all packets are IP packets, or should be handled in some + * special case, if none of them are (if some are and some + * aren't, the lack of encapsulation is a problem, as we'd + * have to find some other way of determining the packet type). + * + * Therefore, if "off_linktype" is -1, there's an error. + */ + if (off_linktype == -1) + abort(); + + /* + * Any type not handled above should always have an Ethernet + * type at an offset of "off_linktype". (PPP is partially + * handled above - the protocol type is mapped from the + * Ethernet and LLC types we use internally to the corresponding + * PPP type - but the PPP type is always specified by a value + * at "off_linktype", so we don't have to do the code generation + * above.) + */ return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); } @@ -929,8 +1456,8 @@ gen_snap(orgcode, ptype, offset) { u_char snapblock[8]; - snapblock[0] = LLC_SNAP_LSAP; /* DSAP = SNAP */ - snapblock[1] = LLC_SNAP_LSAP; /* SSAP = SNAP */ + snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ + snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */ snapblock[2] = 0x03; /* control = UI */ snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ @@ -1270,6 +1797,9 @@ gen_host(addr, mask, proto, dir) case Q_TCP: bpf_error("'tcp' modifier applied to host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_UDP: bpf_error("'udp' modifier applied to host"); @@ -1285,6 +1815,9 @@ gen_host(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1332,6 +1865,15 @@ gen_host(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1360,6 +1902,9 @@ gen_host6(addr, mask, proto, dir) case Q_ARP: bpf_error("'arp' modifier applied to ip6 host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_TCP: bpf_error("'tcp' modifier applied to host"); @@ -1378,6 +1923,9 @@ gen_host6(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1424,6 +1972,15 @@ gen_host6(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1485,6 +2042,14 @@ gen_proto_abbrev(proto) switch (proto) { + case Q_SCTP: + b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + case Q_TCP: b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); #ifdef INET6 @@ -1532,6 +2097,14 @@ gen_proto_abbrev(proto) #endif break; +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + + case Q_VRRP: + b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); + break; + case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; @@ -1611,7 +2184,7 @@ gen_proto_abbrev(proto) break; case Q_ISO: - b1 = gen_linktype(LLC_ISO_LSAP); + b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: @@ -1626,6 +2199,18 @@ gen_proto_abbrev(proto) b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; + case Q_STP: + b1 = gen_linktype(LLCSAP_8021D); + break; + + case Q_IPX: + b1 = gen_linktype(LLCSAP_IPX); + break; + + case Q_NETBEUI: + b1 = gen_linktype(LLCSAP_NETBEUI); + break; + default: abort(); } @@ -1735,6 +2320,7 @@ gen_port(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop(port, ip_proto, dir); break; @@ -1742,6 +2328,8 @@ gen_port(port, ip_proto, dir) tmp = gen_portop(port, IPPROTO_TCP, dir); b1 = gen_portop(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1805,6 +2393,7 @@ gen_port6(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; @@ -1812,6 +2401,8 @@ gen_port6(port, ip_proto, dir) tmp = gen_portop6(port, IPPROTO_TCP, dir); b1 = gen_portop6(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop6(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1833,6 +2424,7 @@ lookup_proto(name, proto) case Q_DEFAULT: case Q_IP: + case Q_IPV6: v = pcap_nametoproto(name); if (v == PROTO_UNDEF) bpf_error("unknown ip proto '%s'", name); @@ -2197,7 +2789,7 @@ gen_proto(v, proto, dir) return b1; case Q_ISO: - b0 = gen_linktype(LLC_ISO_LSAP); + b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(off_nl + 3, BPF_B, (long)v); gen_and(b0, b1); return b1; @@ -2245,6 +2837,10 @@ gen_proto(v, proto, dir) bpf_error("'tcp proto' is bogus"); /* NOTREACHED */ + case Q_SCTP: + bpf_error("'sctp proto' is bogus"); + /* NOTREACHED */ + case Q_ICMP: bpf_error("'icmp proto' is bogus"); /* NOTREACHED */ @@ -2261,6 +2857,10 @@ gen_proto(v, proto, dir) bpf_error("'pim proto' is bogus"); /* NOTREACHED */ + case Q_VRRP: + bpf_error("'vrrp proto' is bogus"); + /* NOTREACHED */ + #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); @@ -2282,6 +2882,15 @@ gen_proto(v, proto, dir) case Q_ESP: bpf_error("'ah proto' is bogus"); + case Q_STP: + bpf_error("'stp proto' is bogus"); + + case Q_IPX: + bpf_error("'ipx proto' is bogus"); + + case Q_NETBEUI: + bpf_error("'netbeui proto' is bogus"); + default: abort(); /* NOTREACHED */ @@ -2335,21 +2944,27 @@ gen_scode(name, q) if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); - return gen_ehostop(eaddr, dir); + b = gen_ehostop(eaddr, dir); + free(eaddr); + return b; case DLT_FDDI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown FDDI host '%s'", name); - return gen_fhostop(eaddr, dir); + b = gen_fhostop(eaddr, dir); + free(eaddr); + return b; case DLT_IEEE802: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown token ring host '%s'", name); - return gen_thostop(eaddr, dir); + b = gen_thostop(eaddr, dir); + free(eaddr); + return b; default: bpf_error( @@ -2410,6 +3025,8 @@ gen_scode(name, q) tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir); break; + default: + continue; } if (b) gen_or(b, tmp); @@ -2427,13 +3044,16 @@ gen_scode(name, q) } case Q_PORT: - if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) + if (proto != Q_DEFAULT && + proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'port'"); if (pcap_nametoport(name, &port, &real_proto) == 0) bpf_error("unknown port '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port '%s' is tcp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; @@ -2441,10 +3061,23 @@ gen_scode(name, q) if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } + if (proto == Q_SCTP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_SCTP; + } #ifndef INET6 return gen_port(port, real_proto, dir); #else @@ -2465,7 +3098,9 @@ gen_scode(name, q) alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); - return gen_gateway(eaddr, alist, proto, dir); + b = gen_gateway(eaddr, alist, proto, dir); + free(eaddr); + return b; #else bpf_error("'gateway' not supported in this configuration"); #endif /*INET6*/ @@ -2582,6 +3217,8 @@ gen_ncode(s, v, q) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; + else if (proto == Q_SCTP) + proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else @@ -2644,6 +3281,7 @@ gen_mcode6(s1, s2, masklen, q) if (sizeof(mask) * 8 < masklen) bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8)); + memset(&mask, 0, sizeof(mask)); memset(&mask, 0xff, masklen / 8); if (masklen % 8) { mask.s6_addr[masklen / 8] = @@ -2794,12 +3432,14 @@ gen_load(proto, index, size) index->b = b; break; + case Q_SCTP: case Q_TCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: case Q_PIM: + case Q_VRRP: s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; sappend(s, xfer_to_a(index)); @@ -3074,6 +3714,8 @@ gen_byteop(op, idx, val) return b; } +static u_char abroadcast[] = { 0x0 }; + struct block * gen_broadcast(proto) int proto; @@ -3086,6 +3728,8 @@ gen_broadcast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + return gen_ahostop(abroadcast, Q_DST); if (linktype == DLT_EN10MB) return gen_ehostop(ebroadcast, Q_DST); if (linktype == DLT_FDDI) @@ -3119,6 +3763,10 @@ gen_multicast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + /* all ARCnet multicasts use the same address */ + return gen_ahostop(abroadcast, Q_DST); + if (linktype == DLT_EN10MB) { /* ether[0] & 1 != 0 */ s = new_stmt(BPF_LD|BPF_B|BPF_ABS); @@ -3196,6 +3844,51 @@ gen_inbound(dir) return (b0); } +struct block * +gen_acode(eaddr, q) + register const u_char *eaddr; + struct qual q; +{ + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { + if (linktype == DLT_ARCNET) + return gen_ahostop(eaddr, (int)q.dir); + } + bpf_error("ARCnet address used in non-arc expression"); + /* NOTREACHED */ +} + +static struct block * +gen_ahostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + /* src comes first, different from Ethernet */ + case Q_SRC: + return gen_bcmp(0, 1, eaddr); + + case Q_DST: + return gen_bcmp(1, 1, eaddr); + + case Q_AND: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + /* * support IEEE 802.1Q VLAN trunk over ethernet */ @@ -3203,7 +3896,6 @@ struct block * gen_vlan(vlan_num) int vlan_num; { - static u_int orig_linktype = -1, orig_nl = -1; struct block *b0; /* diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h index 589c62325a11..2fbec91634e1 100644 --- a/contrib/libpcap/gencode.h +++ b/contrib/libpcap/gencode.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.47 2000/11/04 10:09:55 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.53 2001/05/10 14:48:02 fenner Exp $ (LBL) */ /* Address qualifiers. */ @@ -36,34 +36,42 @@ #define Q_IP 2 #define Q_ARP 3 #define Q_RARP 4 -#define Q_TCP 5 -#define Q_UDP 6 -#define Q_ICMP 7 -#define Q_IGMP 8 -#define Q_IGRP 9 +#define Q_SCTP 5 +#define Q_TCP 6 +#define Q_UDP 7 +#define Q_ICMP 8 +#define Q_IGMP 9 +#define Q_IGRP 10 -#define Q_ATALK 10 -#define Q_DECNET 11 -#define Q_LAT 12 -#define Q_SCA 13 -#define Q_MOPRC 14 -#define Q_MOPDL 15 +#define Q_ATALK 11 +#define Q_DECNET 12 +#define Q_LAT 13 +#define Q_SCA 14 +#define Q_MOPRC 15 +#define Q_MOPDL 16 -#define Q_IPV6 16 -#define Q_ICMPV6 17 -#define Q_AH 18 -#define Q_ESP 19 +#define Q_IPV6 17 +#define Q_ICMPV6 18 +#define Q_AH 19 +#define Q_ESP 20 -#define Q_PIM 20 +#define Q_PIM 21 +#define Q_VRRP 22 -#define Q_AARP 21 +#define Q_AARP 23 -#define Q_ISO 22 -#define Q_ESIS 23 -#define Q_ISIS 24 -#define Q_CLNP 25 +#define Q_ISO 24 +#define Q_ESIS 25 +#define Q_ISIS 26 +#define Q_CLNP 27 + +#define Q_STP 28 + +#define Q_IPX 29 + +#define Q_NETBEUI 30 /* Directional qualifiers. */ @@ -166,6 +174,7 @@ void gen_not(struct block *); struct block *gen_scode(const char *, struct qual); struct block *gen_ecode(const u_char *, struct qual); +struct block *gen_acode(const u_char *, struct qual); struct block *gen_mcode(const char *, const char *, int, struct qual); #ifdef INET6 struct block *gen_mcode6(const char *, const char *, int, struct qual); diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y index 570d5713363b..e978de46016e 100644 --- a/contrib/libpcap/grammar.y +++ b/contrib/libpcap/grammar.y @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.64 2000/10/28 10:18:40 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.71 2001/07/03 19:15:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -106,21 +106,25 @@ pcap_parse() %token DST SRC HOST GATEWAY %token NET MASK PORT LESS GREATER PROTO PROTOCHAIN BYTE -%token ARP RARP IP TCP UDP ICMP IGMP IGRP PIM +%token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token LINK %token GEQ LEQ NEQ -%token ID EID HID HID6 +%token ID EID HID HID6 AID %token LSH RSH %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN %token ISO ESIS ISIS CLNP +%token STP +%token IPX +%token NETBEUI %type ID %type EID +%type AID %type HID HID6 %type NUM @@ -184,7 +188,24 @@ nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } "in this configuration"); #endif /*INET6*/ } - | EID { $$.b = gen_ecode($1, $$.q = $0.q); } + | EID { + $$.b = gen_ecode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } + | AID { + $$.b = gen_acode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } | not id { gen_not($2.b); $$ = $2; } ; not: '!' { $$ = $0; } @@ -242,12 +263,14 @@ pname: LINK { $$ = Q_LINK; } | IP { $$ = Q_IP; } | ARP { $$ = Q_ARP; } | RARP { $$ = Q_RARP; } + | SCTP { $$ = Q_SCTP; } | TCP { $$ = Q_TCP; } | UDP { $$ = Q_UDP; } | ICMP { $$ = Q_ICMP; } | IGMP { $$ = Q_IGMP; } | IGRP { $$ = Q_IGRP; } | PIM { $$ = Q_PIM; } + | VRRP { $$ = Q_VRRP; } | ATALK { $$ = Q_ATALK; } | AARP { $$ = Q_AARP; } | DECNET { $$ = Q_DECNET; } @@ -263,6 +286,9 @@ pname: LINK { $$ = Q_LINK; } | ESIS { $$ = Q_ESIS; } | ISIS { $$ = Q_ISIS; } | CLNP { $$ = Q_CLNP; } + | STP { $$ = Q_STP; } + | IPX { $$ = Q_IPX; } + | NETBEUI { $$ = Q_NETBEUI; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } 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/nametoaddr.c b/contrib/libpcap/nametoaddr.c index e3c0ca58ce7a..40a4d2933a81 100644 --- a/contrib/libpcap/nametoaddr.c +++ b/contrib/libpcap/nametoaddr.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.57.2.1 2001/01/17 18:21:56 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.60 2001/07/28 22:56:35 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -313,7 +313,7 @@ pcap_ether_aton(const char *s) if (*s == ':') s += 1; d = xdtoi(*s++); - if (isxdigit(*s)) { + if (isxdigit((unsigned char)*s)) { d <<= 4; d |= xdtoi(*s++); } @@ -404,5 +404,6 @@ __pcap_nametodnaddr(const char *name) #else bpf_error("decnet name support not included, '%s' cannot be translated\n", name); + return(0); #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-int.h b/contrib/libpcap/pcap-int.h index fc4ab90ad280..82f7beff4e21 100644 --- a/contrib/libpcap/pcap-int.h +++ b/contrib/libpcap/pcap-int.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.32 2000/12/21 10:29:23 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.33 2001/08/24 07:46:52 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -65,7 +65,6 @@ struct pcap_md { long OrigMissed; /* missed by i/f before this run */ #ifdef linux int sock_packet; /* using Linux 2.0 compatible interface */ - int readlen; /* byte count to hand to "recvmsg()" */ int timeout; /* timeout specified to pcap_open_live */ int clear_promisc; /* must clear promiscuous mode when we close */ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ 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.3 b/contrib/libpcap/pcap.3 index 77fd072d1049..8aaeb4ea8314 100644 --- a/contrib/libpcap/pcap.3 +++ b/contrib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.17.2.1 2001/01/18 04:42:11 guy Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.31 2001/12/29 21:57:07 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -28,17 +28,28 @@ pcap \- Packet Capture library #include .ft .LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP .ft B pcap_t *pcap_open_live(char *device, int snaplen, .ti +8 -int promisc, int to_ms, char *ebuf) +int promisc, int to_ms, char *errbuf) pcap_t *pcap_open_dead(int linktype, int snaplen) -pcap_t *pcap_open_offline(char *fname, char *ebuf) +pcap_t *pcap_open_offline(char *fname, char *errbuf) pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname) .ft .LP .ft B -char errbuf[PCAP_ERRBUF_SIZE]; +int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); +int pcap_getnonblock(pcap_t *p, char *errbuf); +.ft +.LP +.ft B +int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +void pcap_freealldevs(pcap_if_t *) char *pcap_lookupdev(char *errbuf) int pcap_lookupnet(char *device, bpf_u_int32 *netp, .ti +8 @@ -98,9 +109,13 @@ through this mechanism. NOTE: .I errbuf in -.B pcap_open_live(), -.B pcap_open_offline(), -.B pcap_lookupdev(), +.BR pcap_open_live() , +.BR pcap_open_dead() , +.BR pcap_open_offline() , +.BR pcap_setnonblock() , +.BR pcap_getnonblock() , +.BR pcap_findalldevs() , +.BR pcap_lookupdev() , and .B pcap_lookupnet() is assumed to be able to hold at least @@ -134,11 +149,21 @@ is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored. -.I ebuf -is used to return error text and is only set when +.I errbuf +is used to return error or warning text. It will be set to error text when .B pcap_open_live() fails and returns .BR NULL . +.I errbuf +may also be set to warning text when +.B pcap_open_live() +succeds; to detect this case the caller should store a zero-length string in +.I errbuf +before calling +.B pcap_open_live() +and display the warning to the user if +.I errbuf +is no longer a zero-length string. .PP .B pcap_open_dead() is used for creating a @@ -156,7 +181,7 @@ and .BR tcpslice(1) . The name "-" in a synonym for .BR stdin . -.I ebuf +.I errbuf is used to return error text and is only set when .B pcap_open_offline() fails and returns @@ -183,6 +208,131 @@ is returned, .B pcap_geterr() can be used to get the error text. .PP +.B pcap_setnonblock() +puts a capture descriptor, opened with +.BR pcap_open_live() , +into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, +depending on whether the +.I nonblock +argument is non-zero or zero. It has no effect on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message; otherwise, 0 is +returned. +In +``non-blocking'' mode, an attempt to read from the capture descriptor +with +.B pcap_dispatch() +will, if no packets are currently available to be read, return 0 +immediately rather than blocking waiting for packets to arrive. +.B pcap_loop() +and +.B pcap_next() +will not work in ``non-blocking'' mode. +.PP +.B pcap_getnonblock() +returns the current ``non-blocking'' state of the capture descriptor; it +always returns 0 on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message. +.PP +.B pcap_findalldevs() +constructs a list of network devices that can be opened with +.BR pcap_open_live() . +(Note that there may be network devices that cannot be opened with +.BR pcap_open_live() +by the +process calling +.BR pcap_findalldevs() , +because, for example, that process might not have sufficient privileges +to open them for capturing; if so, those devices will not appear on the +list.) +.I alldevsp +is set to point to the first element of the list; each element of the +list is of type +.BR pcap_if_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B name +a pointer to a string giving a name for the device to pass to +.B pcap_open_live() +.TP +.B description +if not +.BR NULL , +a pointer to a string giving a human-readable description of the device +.TP +.B addresses +a pointer to the first element of a list of addresses for the interface +.TP +.B flags +interface flags: +.RS +.TP +.B PCAP_IF_LOOPBACK +set if the interface is a loopback interface +.RE +.RE +.PP +Each element of the list of addresses is of type +.BR pcap_addr_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B addr +a pointer to a +.B "struct sockaddr" +containing an address +.TP +.B netmask +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the netmask corresponding to the address pointed to by +.B addr +.TP +.B broadaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the broadcast address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface doesn't support broadcasts +.TP +.B dstaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the destination address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface isn't a point-to-point interface +.RE +.PP +.B pcap_freealldevs() +is used to free a list allocated by +.BR pcap_findalldevs() . +.PP .B pcap_lookupdev() returns a pointer to a network device suitable for use with .B pcap_open_live() @@ -284,9 +434,15 @@ causes to loop forever (or at least until an error occurs). .PP .B pcap_next() -returns a +reads the next packet (by calling +.B pcap_dispatch() +with a +.I cnt +of 1) and returns a .I u_char -pointer to the next packet. +pointer to the data in that packet. (The +.I pcap_pkthdr +struct for that packet is not supplied.) .PP .B pcap_dump() outputs a packet to the ``savefile'' opened with @@ -295,6 +451,12 @@ Note that its calling arguments are suitable for use with .B pcap_dispatch() or .BR pcap_loop() . +If called directly, the +.I user +parameter is of type +.I pcap_dumper_t +as returned by +.BR pcap_dump_open() . .PP .B pcap_compile() is used to compile the string @@ -356,8 +518,150 @@ has been made the filter program for a pcap structure by a call to .BR pcap_setfilter() . .PP .B pcap_datalink() -returns the link layer type, e.g. -.BR DLT_EN10MB . +returns the link layer type; link layer types it can return include: +.PP +.RS 5 +.TP 5 +.B DLT_NULL +BSD loopback encapsulation; the link layer header is a 4-byte field, in +.I host +byte order, containing a PF_ value from +.B socket.h +for the network-layer protocol of the packet +.IP +Note that ``host byte order'' is the byte order of the machine on which +the packets are captured, and the PF_ values are for the OS of the +machine on which the packets are captured; if a live capture is being +done, ``host byte order'' is the byte order of the machine capturing the +packets, and the PF_ values are those of the OS of the machine capturing +the packets, but if a ``savefile'' is being read, the byte order and PF_ +values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.B DLT_EN10MB +Ethernet (10Mb, 100Mb, 1000Mb, and up) +.TP 5 +.B DLT_IEEE802 +IEEE 802.5 Token Ring +.TP 5 +.B DLT_ARCNET +ARCNET +.TP 5 +.B DLT_SLIP +SLIP; the link layer header contains, in order: +.RS 10 +.LP +a 1-byte flag, which is 0 for packets received by the machine and 1 for +packets sent by the machine; +.LP +a 1-byte field, the upper 4 bits of which indicate the type of packet, +as per RFC 1144: +.RS 5 +.TP 5 +0x40 +an unmodified IP datagram (TYPE_IP); +.TP 5 +0x70 +an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being +the first byte of the raw IP header on the wire, containing the +connection number in the protocol field; +.TP 5 +0x80 +a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the +first byte of the compressed TCP/IP datagram header; +.RE +.LP +for UNCOMPRESSED_TCP, the rest of the modified IP header, and for +COMPRESSED_TCP, the compressed TCP/IP datagram header; +.RE +.RS 5 +.LP +for a total of 16 bytes; the uncompressed IP datagram follows the header +.RE +.TP 5 +.B DLT_PPP +PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like +framing, with the PPP header following those two bytes, otherwise it's +PPP without framing, and the packet begins with the PPP header +.TP 5 +.B DLT_FDDI +FDDI +.TP 5 +.B DLT_ATM_RFC1483 +RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 +LLC header +.TP 5 +.B DLT_RAW +raw IP; the packet begins with an IP header +.TP 5 +.B DLT_PPP_SERIAL +PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC +framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF +for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP +with HDLC framing +.TP 5 +.B DLT_PPP_ETHER +PPPoE; the packet begins with a PPPoE header, as per RFC 2516 +.TP 5 +.B DLT_C_HDLC +Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547 +.TP 5 +.B DLT_IEEE802_11 +IEEE 802.11 wireless LAN +.TP 5 +.B DLT_LOOP +OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in +.I network +byte order, containing a PF_ value from OpenBSD's +.B socket.h +for the network-layer protocol of the packet +.IP +Note that, if a ``savefile'' is being read, those PF_ values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.B DLT_LINUX_SLL +Linux "cooked" capture encapsulation; the link layer header contains, in +order: +.RS 10 +.LP +a 2-byte "packet type", in network byte order, which is one of: +.RS 5 +.TP 5 +0 +packet was sent to us by somebody else +.TP 5 +1 +packet was broadcast by somebody else +.TP 5 +2 +packet was multicast, but not broadcast, by somebody else +.TP 5 +3 +packet was sent by somebody else to somebody else +.TP 5 +4 +packet was sent by us +.RE +.LP +a 2-byte field, in network byte order, containing a Linux ARPHRD_ value +for the link layer device type; +.LP +a 2-byte field, in network byte order, containing the length of the +link layer address of the sender of the packet (which could be 0); +.LP +an 8-byte field containing that number of bytes of the link layer header +(if there are more than 8 bytes, only the first 8 are present); +.LP +a 2-byte field containing an Ethernet protocol type, in network byte +order, or containing 1 for Novell 802.3 frames without an 802.2 LLC +header or 4 for frames beginning with an 802.2 LLC header. +.RE +.TP 5 +.B DLT_LTALK +Apple LocalTalk; the packet begins with an AppleTalk LLAP header +.RE .PP .B pcap_snapshot() returns the snapshot length specified when @@ -377,21 +681,33 @@ returns the minor number of the version of the pcap used to write the savefile. .PP .B pcap_file() -returns the name of the ``savefile.'' +returns the standard I/O stream of the ``savefile,'' if a ``savefile'' +was opened with +.BR pcap_open_offline() , +or NULL, if a network device was opened with +.BR pcap_open_live() . .PP -.B int pcap_stats() +.B pcap_stats() returns 0 and fills in a .B pcap_stat struct. The values represent packet statistics from the start of the -run to the time of the call. If there is an error or the under lying +run to the time of the call. If there is an error or the underlying packet capture doesn't support packet statistics, \-1 is returned and the error text can be obtained with .B pcap_perror() or .BR pcap_geterr() . +.B pcap_stats() +is supported only on live captures, not on ``savefiles''; no statistics +are stored in ``savefiles'', so no statistics are available when reading +from a ``savefile''. .PP .B pcap_fileno() -returns the file descriptor number of the ``savefile.'' +returns the file descriptor number from which captured packets are read, +if a network device was opened with +.BR pcap_open_live() , +or \-1, if a ``savefile'' was opened with +.BR pcap_open_offline() . .PP .B pcap_perror() prints the text of the last pcap library error on 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/pcap.h b/contrib/libpcap/pcap.h index de92cfb3054b..accd6ab3c6bd 100644 --- a/contrib/libpcap/pcap.h +++ b/contrib/libpcap/pcap.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. @@ -30,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.31 2000/10/28 00:01:31 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.34 2001/12/09 05:10:03 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -63,6 +64,8 @@ typedef u_int bpf_u_int32; typedef struct pcap pcap_t; typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; /* * The first record in the file contains saved values for some @@ -128,6 +131,30 @@ struct pcap_stat { u_int ps_ifdrop; /* drops by interface XXX not yet supported */ }; +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + u_int flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -143,6 +170,8 @@ const u_char* pcap_next(pcap_t *, struct pcap_pkthdr *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *); char *pcap_strerror(int); char *pcap_geterr(pcap_t *); @@ -165,6 +194,9 @@ pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + /* XXX this guy lives in the bpf tree */ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); int bpf_validate(struct bpf_insn *f, int len); 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: * diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l index b3f7ba17859b..07275b5b1d6b 100644 --- a/contrib/libpcap/scanner.l +++ b/contrib/libpcap/scanner.l @@ -22,7 +22,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.70 2000/10/28 10:18:40 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.81 2001/09/14 01:40:57 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -170,15 +170,29 @@ fddi|tr return LINK; arp return ARP; rarp return RARP; ip return IP; +sctp return SCTP; tcp return TCP; udp return UDP; icmp return ICMP; igmp return IGMP; igrp return IGRP; pim return PIM; +vrrp return VRRP; -ip6 return IPV6; -icmp6 return ICMPV6; +ip6 { +#ifdef INET6 + return IPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } +icmp6 { +#ifdef INET6 + return ICMPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } ah return AH; esp return ESP; @@ -197,6 +211,12 @@ isis return ISIS; is-is return ISIS; clnp return CLNP; +stp return STP; + +ipx return IPX; + +netbeui return NETBEUI; + host return HOST; net return NET; mask return MASK; @@ -236,6 +256,8 @@ vlan return VLAN; "==" return '='; "<<" return LSH; ">>" return RSH; +${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1); + return AID; } {N} { yylval.i = stoi((char *)yytext); return NUM; } ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { yylval.s = sdup((char *)yytext); return HID; } @@ -257,11 +279,35 @@ vlan return VLAN; #endif /*INET6*/ } {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } -[A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9] { +icmptype { yylval.i = 0; return NUM; } +icmpcode { yylval.i = 1; return NUM; } +icmp-echoreply { yylval.i = 0; return NUM; } +icmp-unreach { yylval.i = 3; return NUM; } +icmp-sourcequench { yylval.i = 4; return NUM; } +icmp-redirect { yylval.i = 5; return NUM; } +icmp-echo { yylval.i = 8; return NUM; } +icmp-routeradvert { yylval.i = 9; return NUM; } +icmp-routersolicit { yylval.i = 10; return NUM; } +icmp-timxceed { yylval.i = 11; return NUM; } +icmp-paramprob { yylval.i = 12; return NUM; } +icmp-tstamp { yylval.i = 13; return NUM; } +icmp-tstampreply { yylval.i = 14; return NUM; } +icmp-ireq { yylval.i = 15; return NUM; } +icmp-ireqreply { yylval.i = 16; return NUM; } +icmp-maskreq { yylval.i = 17; return NUM; } +icmp-maskreply { yylval.i = 18; return NUM; } +tcpflags { yylval.i = 13; return NUM; } +tcp-fin { yylval.i = 0x01; return NUM; } +tcp-syn { yylval.i = 0x02; return NUM; } +tcp-rst { yylval.i = 0x04; return NUM; } +tcp-push { yylval.i = 0x08; return NUM; } +tcp-ack { yylval.i = 0x10; return NUM; } +tcp-urg { yylval.i = 0x20; return NUM; } +[A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? { yylval.s = sdup((char *)yytext); return ID; } "\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; } -[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+i { - bpf_error("illegal token: %s\n", yytext); } +[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { + bpf_error("illegal token: %s", yytext); } . { bpf_error("illegal char '%c'", *yytext); } %% void